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