]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rgw/test_log_backing.cc
update ceph source to reef 18.2.1
[ceph.git] / 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
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2019 Red Hat, Inc.
7 *
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.
12 *
13 */
14
15 #include "rgw_log_backing.h"
16
17 #include <cerrno>
18 #include <iostream>
19 #include <string_view>
20
21 #include <fmt/format.h>
22
23 #include "include/types.h"
24 #include "include/rados/librados.hpp"
25
26 #include "test/librados/test_cxx.h"
27 #include "global/global_context.h"
28
29 #include "cls/log/cls_log_client.h"
30
31 #include "rgw_tools.h"
32 #include "cls_fifo_legacy.h"
33
34 #include "gtest/gtest.h"
35
36 namespace lr = librados;
37 namespace cb = ceph::buffer;
38 namespace fifo = rados::cls::fifo;
39 namespace RCf = rgw::cls::fifo;
40
41 auto cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT);
42 const DoutPrefix dp(cct, 1, "test log backing: ");
43
44 class LogBacking : public testing::Test {
45 protected:
46 static constexpr int SHARDS = 3;
47 const std::string pool_name = get_temp_pool_name();
48 lr::Rados rados;
49 lr::IoCtx ioctx;
50 lr::Rados rados2;
51 lr::IoCtx ioctx2;
52
53 void SetUp() override {
54 ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
55 ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
56 connect_cluster_pp(rados2);
57 ASSERT_EQ(0, rados2.ioctx_create(pool_name.c_str(), ioctx2));
58 }
59 void TearDown() override {
60 destroy_one_pool_pp(pool_name, rados);
61 }
62
63 std::string get_oid(uint64_t gen_id, int i) const {
64 return (gen_id > 0 ?
65 fmt::format("shard@G{}.{}", gen_id, i) :
66 fmt::format("shard.{}", i));
67 }
68
69 void make_omap() {
70 for (int i = 0; i < SHARDS; ++i) {
71 using ceph::encode;
72 lr::ObjectWriteOperation op;
73 cb::list bl;
74 encode(i, bl);
75 cls_log_add(op, ceph_clock_now(), {}, "meow", bl);
76 auto r = rgw_rados_operate(&dp, ioctx, get_oid(0, i), &op, null_yield);
77 ASSERT_GE(r, 0);
78 }
79 }
80
81 void add_omap(int i) {
82 using ceph::encode;
83 lr::ObjectWriteOperation op;
84 cb::list bl;
85 encode(i, bl);
86 cls_log_add(op, ceph_clock_now(), {}, "meow", bl);
87 auto r = rgw_rados_operate(&dp, ioctx, get_oid(0, i), &op, null_yield);
88 ASSERT_GE(r, 0);
89 }
90
91 void empty_omap() {
92 for (int i = 0; i < SHARDS; ++i) {
93 auto oid = get_oid(0, i);
94 std::string to_marker;
95 {
96 lr::ObjectReadOperation op;
97 std::list<cls_log_entry> entries;
98 bool truncated = false;
99 cls_log_list(op, {}, {}, {}, 1, entries, &to_marker, &truncated);
100 auto r = rgw_rados_operate(&dp, ioctx, oid, &op, nullptr, null_yield);
101 ASSERT_GE(r, 0);
102 ASSERT_FALSE(entries.empty());
103 }
104 {
105 lr::ObjectWriteOperation op;
106 cls_log_trim(op, {}, {}, {}, to_marker);
107 auto r = rgw_rados_operate(&dp, ioctx, oid, &op, null_yield);
108 ASSERT_GE(r, 0);
109 }
110 {
111 lr::ObjectReadOperation op;
112 std::list<cls_log_entry> entries;
113 bool truncated = false;
114 cls_log_list(op, {}, {}, {}, 1, entries, &to_marker, &truncated);
115 auto r = rgw_rados_operate(&dp, ioctx, oid, &op, nullptr, null_yield);
116 ASSERT_GE(r, 0);
117 ASSERT_TRUE(entries.empty());
118 }
119 }
120 }
121
122 void make_fifo()
123 {
124 for (int i = 0; i < SHARDS; ++i) {
125 std::unique_ptr<RCf::FIFO> fifo;
126 auto r = RCf::FIFO::create(&dp, ioctx, get_oid(0, i), &fifo, null_yield);
127 ASSERT_EQ(0, r);
128 ASSERT_TRUE(fifo);
129 }
130 }
131
132 void add_fifo(int i)
133 {
134 using ceph::encode;
135 std::unique_ptr<RCf::FIFO> fifo;
136 auto r = RCf::FIFO::open(&dp, ioctx, get_oid(0, i), &fifo, null_yield);
137 ASSERT_GE(0, r);
138 ASSERT_TRUE(fifo);
139 cb::list bl;
140 encode(i, bl);
141 r = fifo->push(&dp, bl, null_yield);
142 ASSERT_GE(0, r);
143 }
144
145 void assert_empty() {
146 std::vector<lr::ObjectItem> result;
147 lr::ObjectCursor next;
148 auto r = ioctx.object_list(ioctx.object_list_begin(), ioctx.object_list_end(),
149 100, {}, &result, &next);
150 ASSERT_GE(r, 0);
151 ASSERT_TRUE(result.empty());
152 }
153 };
154
155 TEST_F(LogBacking, TestOmap)
156 {
157 make_omap();
158 auto stat = log_backing_type(&dp, ioctx, log_type::fifo, SHARDS,
159 [this](int shard){ return get_oid(0, shard); },
160 null_yield);
161 ASSERT_EQ(log_type::omap, *stat);
162 }
163
164 TEST_F(LogBacking, TestOmapEmpty)
165 {
166 auto stat = log_backing_type(&dp, ioctx, log_type::omap, SHARDS,
167 [this](int shard){ return get_oid(0, shard); },
168 null_yield);
169 ASSERT_EQ(log_type::omap, *stat);
170 }
171
172 TEST_F(LogBacking, TestFIFO)
173 {
174 make_fifo();
175 auto stat = log_backing_type(&dp, ioctx, log_type::fifo, SHARDS,
176 [this](int shard){ return get_oid(0, shard); },
177 null_yield);
178 ASSERT_EQ(log_type::fifo, *stat);
179 }
180
181 TEST_F(LogBacking, TestFIFOEmpty)
182 {
183 auto stat = log_backing_type(&dp, ioctx, log_type::fifo, SHARDS,
184 [this](int shard){ return get_oid(0, shard); },
185 null_yield);
186 ASSERT_EQ(log_type::fifo, *stat);
187 }
188
189 TEST(CursorGen, RoundTrip) {
190 const std::string_view pcurs = "fded";
191 {
192 auto gc = gencursor(0, pcurs);
193 ASSERT_EQ(pcurs, gc);
194 auto [gen, cursor] = cursorgen(gc);
195 ASSERT_EQ(0, gen);
196 ASSERT_EQ(pcurs, cursor);
197 }
198 {
199 auto gc = gencursor(53, pcurs);
200 ASSERT_NE(pcurs, gc);
201 auto [gen, cursor] = cursorgen(gc);
202 ASSERT_EQ(53, gen);
203 ASSERT_EQ(pcurs, cursor);
204 }
205 }
206
207 class generations final : public logback_generations {
208 public:
209
210 entries_t got_entries;
211 std::optional<uint64_t> tail;
212
213 using logback_generations::logback_generations;
214
215 bs::error_code handle_init(entries_t e) noexcept {
216 got_entries = e;
217 return {};
218 }
219
220 bs::error_code handle_new_gens(entries_t e) noexcept {
221 got_entries = e;
222 return {};
223 }
224
225 bs::error_code handle_empty_to(uint64_t new_tail) noexcept {
226 tail = new_tail;
227 return {};
228 }
229 };
230
231 TEST_F(LogBacking, GenerationSingle)
232 {
233 auto lgr = logback_generations::init<generations>(
234 &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) {
235 return get_oid(gen_id, shard);
236 }, SHARDS, log_type::fifo, null_yield);
237 ASSERT_TRUE(lgr);
238
239 auto lg = std::move(*lgr);
240
241 ASSERT_EQ(0, lg->got_entries.begin()->first);
242
243 ASSERT_EQ(0, lg->got_entries[0].gen_id);
244 ASSERT_EQ(log_type::fifo, lg->got_entries[0].type);
245 ASSERT_FALSE(lg->got_entries[0].pruned);
246
247 auto ec = lg->empty_to(&dp, 0, null_yield);
248 ASSERT_TRUE(ec);
249
250 lg.reset();
251
252 lg = *logback_generations::init<generations>(
253 &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) {
254 return get_oid(gen_id, shard);
255 }, SHARDS, log_type::fifo, null_yield);
256
257 ASSERT_EQ(0, lg->got_entries.begin()->first);
258
259 ASSERT_EQ(0, lg->got_entries[0].gen_id);
260 ASSERT_EQ(log_type::fifo, lg->got_entries[0].type);
261 ASSERT_FALSE(lg->got_entries[0].pruned);
262
263 lg->got_entries.clear();
264
265 ec = lg->new_backing(&dp, log_type::omap, null_yield);
266 ASSERT_FALSE(ec);
267
268 ASSERT_EQ(1, lg->got_entries.size());
269 ASSERT_EQ(1, lg->got_entries[1].gen_id);
270 ASSERT_EQ(log_type::omap, lg->got_entries[1].type);
271 ASSERT_FALSE(lg->got_entries[1].pruned);
272
273 lg.reset();
274
275 lg = *logback_generations::init<generations>(
276 &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) {
277 return get_oid(gen_id, shard);
278 }, SHARDS, log_type::fifo, null_yield);
279
280 ASSERT_EQ(2, lg->got_entries.size());
281 ASSERT_EQ(0, lg->got_entries[0].gen_id);
282 ASSERT_EQ(log_type::fifo, lg->got_entries[0].type);
283 ASSERT_FALSE(lg->got_entries[0].pruned);
284
285 ASSERT_EQ(1, lg->got_entries[1].gen_id);
286 ASSERT_EQ(log_type::omap, lg->got_entries[1].type);
287 ASSERT_FALSE(lg->got_entries[1].pruned);
288
289 ec = lg->empty_to(&dp, 0, null_yield);
290 ASSERT_FALSE(ec);
291
292 ASSERT_EQ(0, *lg->tail);
293
294 lg.reset();
295
296 lg = *logback_generations::init<generations>(
297 &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) {
298 return get_oid(gen_id, shard);
299 }, SHARDS, log_type::fifo, null_yield);
300
301 ASSERT_EQ(1, lg->got_entries.size());
302 ASSERT_EQ(1, lg->got_entries[1].gen_id);
303 ASSERT_EQ(log_type::omap, lg->got_entries[1].type);
304 ASSERT_FALSE(lg->got_entries[1].pruned);
305 }
306
307 TEST_F(LogBacking, GenerationWN)
308 {
309 auto lg1 = *logback_generations::init<generations>(
310 &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) {
311 return get_oid(gen_id, shard);
312 }, SHARDS, log_type::fifo, null_yield);
313
314 auto ec = lg1->new_backing(&dp, log_type::omap, null_yield);
315 ASSERT_FALSE(ec);
316
317 ASSERT_EQ(1, lg1->got_entries.size());
318 ASSERT_EQ(1, lg1->got_entries[1].gen_id);
319 ASSERT_EQ(log_type::omap, lg1->got_entries[1].type);
320 ASSERT_FALSE(lg1->got_entries[1].pruned);
321
322 lg1->got_entries.clear();
323
324 auto lg2 = *logback_generations::init<generations>(
325 &dp, ioctx2, "foobar", [this](uint64_t gen_id, int shard) {
326 return get_oid(gen_id, shard);
327 }, SHARDS, log_type::fifo, null_yield);
328
329 ASSERT_EQ(2, lg2->got_entries.size());
330
331 ASSERT_EQ(0, lg2->got_entries[0].gen_id);
332 ASSERT_EQ(log_type::fifo, lg2->got_entries[0].type);
333 ASSERT_FALSE(lg2->got_entries[0].pruned);
334
335 ASSERT_EQ(1, lg2->got_entries[1].gen_id);
336 ASSERT_EQ(log_type::omap, lg2->got_entries[1].type);
337 ASSERT_FALSE(lg2->got_entries[1].pruned);
338
339 lg2->got_entries.clear();
340
341 ec = lg1->new_backing(&dp, log_type::fifo, null_yield);
342 ASSERT_FALSE(ec);
343
344 ASSERT_EQ(1, lg1->got_entries.size());
345 ASSERT_EQ(2, lg1->got_entries[2].gen_id);
346 ASSERT_EQ(log_type::fifo, lg1->got_entries[2].type);
347 ASSERT_FALSE(lg1->got_entries[2].pruned);
348
349 ASSERT_EQ(1, lg2->got_entries.size());
350 ASSERT_EQ(2, lg2->got_entries[2].gen_id);
351 ASSERT_EQ(log_type::fifo, lg2->got_entries[2].type);
352 ASSERT_FALSE(lg2->got_entries[2].pruned);
353
354 lg1->got_entries.clear();
355 lg2->got_entries.clear();
356
357 ec = lg2->empty_to(&dp, 1, null_yield);
358 ASSERT_FALSE(ec);
359
360 ASSERT_EQ(1, *lg1->tail);
361 ASSERT_EQ(1, *lg2->tail);
362
363 lg1->tail.reset();
364 lg2->tail.reset();
365 }