]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/rgw/test_log_backing.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2019 Red Hat, Inc.
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "rgw_log_backing.h"
19 #include <string_view>
21 #undef FMT_HEADER_ONLY
22 #define FMT_HEADER_ONLY 1
23 #include <fmt/format.h>
25 #include "include/types.h"
26 #include "include/rados/librados.hpp"
28 #include "test/librados/test_cxx.h"
29 #include "global/global_context.h"
31 #include "cls/log/cls_log_client.h"
33 #include "rgw/rgw_tools.h"
34 #include "rgw/cls_fifo_legacy.h"
36 #include "gtest/gtest.h"
38 namespace lr
= librados
;
39 namespace cb
= ceph::buffer
;
40 namespace fifo
= rados::cls::fifo
;
41 namespace RCf
= rgw::cls::fifo
;
43 auto cct
= new CephContext(CEPH_ENTITY_TYPE_CLIENT
);
44 const DoutPrefix
dp(cct
, 1, "test log backing: ");
46 class LogBacking
: public testing::Test
{
48 static constexpr int SHARDS
= 3;
49 const std::string pool_name
= get_temp_pool_name();
55 void SetUp() override
{
56 ASSERT_EQ("", create_one_pool_pp(pool_name
, rados
));
57 ASSERT_EQ(0, rados
.ioctx_create(pool_name
.c_str(), ioctx
));
58 connect_cluster_pp(rados2
);
59 ASSERT_EQ(0, rados2
.ioctx_create(pool_name
.c_str(), ioctx2
));
61 void TearDown() override
{
62 destroy_one_pool_pp(pool_name
, rados
);
65 std::string
get_oid(uint64_t gen_id
, int i
) const {
67 fmt::format("shard@G{}.{}", gen_id
, i
) :
68 fmt::format("shard.{}", i
));
72 for (int i
= 0; i
< SHARDS
; ++i
) {
74 lr::ObjectWriteOperation op
;
77 cls_log_add(op
, ceph_clock_now(), {}, "meow", bl
);
78 auto r
= rgw_rados_operate(&dp
, ioctx
, get_oid(0, i
), &op
, null_yield
);
83 void add_omap(int i
) {
85 lr::ObjectWriteOperation op
;
88 cls_log_add(op
, ceph_clock_now(), {}, "meow", bl
);
89 auto r
= rgw_rados_operate(&dp
, ioctx
, get_oid(0, i
), &op
, null_yield
);
94 for (int i
= 0; i
< SHARDS
; ++i
) {
95 auto oid
= get_oid(0, i
);
96 std::string to_marker
;
98 lr::ObjectReadOperation op
;
99 std::list
<cls_log_entry
> entries
;
100 bool truncated
= false;
101 cls_log_list(op
, {}, {}, {}, 1, entries
, &to_marker
, &truncated
);
102 auto r
= rgw_rados_operate(&dp
, ioctx
, oid
, &op
, nullptr, null_yield
);
104 ASSERT_FALSE(entries
.empty());
107 lr::ObjectWriteOperation op
;
108 cls_log_trim(op
, {}, {}, {}, to_marker
);
109 auto r
= rgw_rados_operate(&dp
, ioctx
, oid
, &op
, null_yield
);
113 lr::ObjectReadOperation op
;
114 std::list
<cls_log_entry
> entries
;
115 bool truncated
= false;
116 cls_log_list(op
, {}, {}, {}, 1, entries
, &to_marker
, &truncated
);
117 auto r
= rgw_rados_operate(&dp
, ioctx
, oid
, &op
, nullptr, null_yield
);
119 ASSERT_TRUE(entries
.empty());
126 for (int i
= 0; i
< SHARDS
; ++i
) {
127 std::unique_ptr
<RCf::FIFO
> fifo
;
128 auto r
= RCf::FIFO::create(&dp
, ioctx
, get_oid(0, i
), &fifo
, null_yield
);
137 std::unique_ptr
<RCf::FIFO
> fifo
;
138 auto r
= RCf::FIFO::open(&dp
, ioctx
, get_oid(0, i
), &fifo
, null_yield
);
143 r
= fifo
->push(&dp
, bl
, null_yield
);
147 void assert_empty() {
148 std::vector
<lr::ObjectItem
> result
;
149 lr::ObjectCursor next
;
150 auto r
= ioctx
.object_list(ioctx
.object_list_begin(), ioctx
.object_list_end(),
151 100, {}, &result
, &next
);
153 ASSERT_TRUE(result
.empty());
157 TEST_F(LogBacking
, TestOmap
)
160 auto stat
= log_backing_type(&dp
, ioctx
, log_type::fifo
, SHARDS
,
161 [this](int shard
){ return get_oid(0, shard
); },
163 ASSERT_EQ(log_type::omap
, *stat
);
166 TEST_F(LogBacking
, TestOmapEmpty
)
168 auto stat
= log_backing_type(&dp
, ioctx
, log_type::omap
, SHARDS
,
169 [this](int shard
){ return get_oid(0, shard
); },
171 ASSERT_EQ(log_type::omap
, *stat
);
174 TEST_F(LogBacking
, TestFIFO
)
177 auto stat
= log_backing_type(&dp
, ioctx
, log_type::fifo
, SHARDS
,
178 [this](int shard
){ return get_oid(0, shard
); },
180 ASSERT_EQ(log_type::fifo
, *stat
);
183 TEST_F(LogBacking
, TestFIFOEmpty
)
185 auto stat
= log_backing_type(&dp
, ioctx
, log_type::fifo
, SHARDS
,
186 [this](int shard
){ return get_oid(0, shard
); },
188 ASSERT_EQ(log_type::fifo
, *stat
);
191 TEST(CursorGen
, RoundTrip
) {
192 const std::string_view pcurs
= "fded";
194 auto gc
= gencursor(0, pcurs
);
195 ASSERT_EQ(pcurs
, gc
);
196 auto [gen
, cursor
] = cursorgen(gc
);
198 ASSERT_EQ(pcurs
, cursor
);
201 auto gc
= gencursor(53, pcurs
);
202 ASSERT_NE(pcurs
, gc
);
203 auto [gen
, cursor
] = cursorgen(gc
);
205 ASSERT_EQ(pcurs
, cursor
);
209 class generations final
: public logback_generations
{
212 entries_t got_entries
;
213 std::optional
<uint64_t> tail
;
215 using logback_generations::logback_generations
;
217 bs::error_code
handle_init(entries_t e
) noexcept
{
222 bs::error_code
handle_new_gens(entries_t e
) noexcept
{
227 bs::error_code
handle_empty_to(uint64_t new_tail
) noexcept
{
233 TEST_F(LogBacking
, GenerationSingle
)
235 auto lgr
= logback_generations::init
<generations
>(
236 &dp
, ioctx
, "foobar", [this](uint64_t gen_id
, int shard
) {
237 return get_oid(gen_id
, shard
);
238 }, SHARDS
, log_type::fifo
, null_yield
);
241 auto lg
= std::move(*lgr
);
243 ASSERT_EQ(0, lg
->got_entries
.begin()->first
);
245 ASSERT_EQ(0, lg
->got_entries
[0].gen_id
);
246 ASSERT_EQ(log_type::fifo
, lg
->got_entries
[0].type
);
247 ASSERT_FALSE(lg
->got_entries
[0].pruned
);
249 auto ec
= lg
->empty_to(&dp
, 0, null_yield
);
254 lg
= *logback_generations::init
<generations
>(
255 &dp
, ioctx
, "foobar", [this](uint64_t gen_id
, int shard
) {
256 return get_oid(gen_id
, shard
);
257 }, SHARDS
, log_type::fifo
, null_yield
);
259 ASSERT_EQ(0, lg
->got_entries
.begin()->first
);
261 ASSERT_EQ(0, lg
->got_entries
[0].gen_id
);
262 ASSERT_EQ(log_type::fifo
, lg
->got_entries
[0].type
);
263 ASSERT_FALSE(lg
->got_entries
[0].pruned
);
265 lg
->got_entries
.clear();
267 ec
= lg
->new_backing(&dp
, log_type::omap
, null_yield
);
270 ASSERT_EQ(1, lg
->got_entries
.size());
271 ASSERT_EQ(1, lg
->got_entries
[1].gen_id
);
272 ASSERT_EQ(log_type::omap
, lg
->got_entries
[1].type
);
273 ASSERT_FALSE(lg
->got_entries
[1].pruned
);
277 lg
= *logback_generations::init
<generations
>(
278 &dp
, ioctx
, "foobar", [this](uint64_t gen_id
, int shard
) {
279 return get_oid(gen_id
, shard
);
280 }, SHARDS
, log_type::fifo
, null_yield
);
282 ASSERT_EQ(2, lg
->got_entries
.size());
283 ASSERT_EQ(0, lg
->got_entries
[0].gen_id
);
284 ASSERT_EQ(log_type::fifo
, lg
->got_entries
[0].type
);
285 ASSERT_FALSE(lg
->got_entries
[0].pruned
);
287 ASSERT_EQ(1, lg
->got_entries
[1].gen_id
);
288 ASSERT_EQ(log_type::omap
, lg
->got_entries
[1].type
);
289 ASSERT_FALSE(lg
->got_entries
[1].pruned
);
291 ec
= lg
->empty_to(&dp
, 0, null_yield
);
294 ASSERT_EQ(0, *lg
->tail
);
298 lg
= *logback_generations::init
<generations
>(
299 &dp
, ioctx
, "foobar", [this](uint64_t gen_id
, int shard
) {
300 return get_oid(gen_id
, shard
);
301 }, SHARDS
, log_type::fifo
, null_yield
);
303 ASSERT_EQ(1, lg
->got_entries
.size());
304 ASSERT_EQ(1, lg
->got_entries
[1].gen_id
);
305 ASSERT_EQ(log_type::omap
, lg
->got_entries
[1].type
);
306 ASSERT_FALSE(lg
->got_entries
[1].pruned
);
309 TEST_F(LogBacking
, GenerationWN
)
311 auto lg1
= *logback_generations::init
<generations
>(
312 &dp
, ioctx
, "foobar", [this](uint64_t gen_id
, int shard
) {
313 return get_oid(gen_id
, shard
);
314 }, SHARDS
, log_type::fifo
, null_yield
);
316 auto ec
= lg1
->new_backing(&dp
, log_type::omap
, null_yield
);
319 ASSERT_EQ(1, lg1
->got_entries
.size());
320 ASSERT_EQ(1, lg1
->got_entries
[1].gen_id
);
321 ASSERT_EQ(log_type::omap
, lg1
->got_entries
[1].type
);
322 ASSERT_FALSE(lg1
->got_entries
[1].pruned
);
324 lg1
->got_entries
.clear();
326 auto lg2
= *logback_generations::init
<generations
>(
327 &dp
, ioctx2
, "foobar", [this](uint64_t gen_id
, int shard
) {
328 return get_oid(gen_id
, shard
);
329 }, SHARDS
, log_type::fifo
, null_yield
);
331 ASSERT_EQ(2, lg2
->got_entries
.size());
333 ASSERT_EQ(0, lg2
->got_entries
[0].gen_id
);
334 ASSERT_EQ(log_type::fifo
, lg2
->got_entries
[0].type
);
335 ASSERT_FALSE(lg2
->got_entries
[0].pruned
);
337 ASSERT_EQ(1, lg2
->got_entries
[1].gen_id
);
338 ASSERT_EQ(log_type::omap
, lg2
->got_entries
[1].type
);
339 ASSERT_FALSE(lg2
->got_entries
[1].pruned
);
341 lg2
->got_entries
.clear();
343 ec
= lg1
->new_backing(&dp
, log_type::fifo
, null_yield
);
346 ASSERT_EQ(1, lg1
->got_entries
.size());
347 ASSERT_EQ(2, lg1
->got_entries
[2].gen_id
);
348 ASSERT_EQ(log_type::fifo
, lg1
->got_entries
[2].type
);
349 ASSERT_FALSE(lg1
->got_entries
[2].pruned
);
351 ASSERT_EQ(1, lg2
->got_entries
.size());
352 ASSERT_EQ(2, lg2
->got_entries
[2].gen_id
);
353 ASSERT_EQ(log_type::fifo
, lg2
->got_entries
[2].type
);
354 ASSERT_FALSE(lg2
->got_entries
[2].pruned
);
356 lg1
->got_entries
.clear();
357 lg2
->got_entries
.clear();
359 ec
= lg2
->empty_to(&dp
, 1, null_yield
);
362 ASSERT_EQ(1, *lg1
->tail
);
363 ASSERT_EQ(1, *lg2
->tail
);