]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
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 | ||
b3b6e05e TL |
43 | auto cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT); |
44 | const DoutPrefix dp(cct, 1, "test log backing: "); | |
45 | ||
f67539c2 TL |
46 | class LogBacking : public testing::Test { |
47 | protected: | |
48 | static constexpr int SHARDS = 3; | |
49 | const std::string pool_name = get_temp_pool_name(); | |
50 | lr::Rados rados; | |
51 | lr::IoCtx ioctx; | |
52 | lr::Rados rados2; | |
53 | lr::IoCtx ioctx2; | |
54 | ||
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)); | |
60 | } | |
61 | void TearDown() override { | |
62 | destroy_one_pool_pp(pool_name, rados); | |
63 | } | |
64 | ||
65 | std::string get_oid(uint64_t gen_id, int i) const { | |
66 | return (gen_id > 0 ? | |
67 | fmt::format("shard@G{}.{}", gen_id, i) : | |
68 | fmt::format("shard.{}", i)); | |
69 | } | |
70 | ||
71 | void make_omap() { | |
72 | for (int i = 0; i < SHARDS; ++i) { | |
73 | using ceph::encode; | |
74 | lr::ObjectWriteOperation op; | |
75 | cb::list bl; | |
76 | encode(i, bl); | |
77 | cls_log_add(op, ceph_clock_now(), {}, "meow", bl); | |
b3b6e05e | 78 | auto r = rgw_rados_operate(&dp, ioctx, get_oid(0, i), &op, null_yield); |
f67539c2 TL |
79 | ASSERT_GE(r, 0); |
80 | } | |
81 | } | |
82 | ||
83 | void add_omap(int i) { | |
84 | using ceph::encode; | |
85 | lr::ObjectWriteOperation op; | |
86 | cb::list bl; | |
87 | encode(i, bl); | |
88 | cls_log_add(op, ceph_clock_now(), {}, "meow", bl); | |
b3b6e05e | 89 | auto r = rgw_rados_operate(&dp, ioctx, get_oid(0, i), &op, null_yield); |
f67539c2 TL |
90 | ASSERT_GE(r, 0); |
91 | } | |
92 | ||
93 | void empty_omap() { | |
94 | for (int i = 0; i < SHARDS; ++i) { | |
95 | auto oid = get_oid(0, i); | |
96 | std::string to_marker; | |
97 | { | |
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); | |
b3b6e05e | 102 | auto r = rgw_rados_operate(&dp, ioctx, oid, &op, nullptr, null_yield); |
f67539c2 TL |
103 | ASSERT_GE(r, 0); |
104 | ASSERT_FALSE(entries.empty()); | |
105 | } | |
106 | { | |
107 | lr::ObjectWriteOperation op; | |
108 | cls_log_trim(op, {}, {}, {}, to_marker); | |
b3b6e05e | 109 | auto r = rgw_rados_operate(&dp, ioctx, oid, &op, null_yield); |
f67539c2 TL |
110 | ASSERT_GE(r, 0); |
111 | } | |
112 | { | |
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); | |
b3b6e05e | 117 | auto r = rgw_rados_operate(&dp, ioctx, oid, &op, nullptr, null_yield); |
f67539c2 TL |
118 | ASSERT_GE(r, 0); |
119 | ASSERT_TRUE(entries.empty()); | |
120 | } | |
121 | } | |
122 | } | |
123 | ||
124 | void make_fifo() | |
125 | { | |
126 | for (int i = 0; i < SHARDS; ++i) { | |
127 | std::unique_ptr<RCf::FIFO> fifo; | |
b3b6e05e | 128 | auto r = RCf::FIFO::create(&dp, ioctx, get_oid(0, i), &fifo, null_yield); |
f67539c2 TL |
129 | ASSERT_EQ(0, r); |
130 | ASSERT_TRUE(fifo); | |
131 | } | |
132 | } | |
133 | ||
134 | void add_fifo(int i) | |
135 | { | |
136 | using ceph::encode; | |
137 | std::unique_ptr<RCf::FIFO> fifo; | |
b3b6e05e | 138 | auto r = RCf::FIFO::open(&dp, ioctx, get_oid(0, i), &fifo, null_yield); |
f67539c2 TL |
139 | ASSERT_GE(0, r); |
140 | ASSERT_TRUE(fifo); | |
141 | cb::list bl; | |
142 | encode(i, bl); | |
b3b6e05e | 143 | r = fifo->push(&dp, bl, null_yield); |
f67539c2 TL |
144 | ASSERT_GE(0, r); |
145 | } | |
146 | ||
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); | |
152 | ASSERT_GE(r, 0); | |
153 | ASSERT_TRUE(result.empty()); | |
154 | } | |
155 | }; | |
156 | ||
157 | TEST_F(LogBacking, TestOmap) | |
158 | { | |
159 | make_omap(); | |
b3b6e05e | 160 | auto stat = log_backing_type(&dp, ioctx, log_type::fifo, SHARDS, |
f67539c2 TL |
161 | [this](int shard){ return get_oid(0, shard); }, |
162 | null_yield); | |
163 | ASSERT_EQ(log_type::omap, *stat); | |
164 | } | |
165 | ||
166 | TEST_F(LogBacking, TestOmapEmpty) | |
167 | { | |
b3b6e05e | 168 | auto stat = log_backing_type(&dp, ioctx, log_type::omap, SHARDS, |
f67539c2 TL |
169 | [this](int shard){ return get_oid(0, shard); }, |
170 | null_yield); | |
171 | ASSERT_EQ(log_type::omap, *stat); | |
172 | } | |
173 | ||
174 | TEST_F(LogBacking, TestFIFO) | |
175 | { | |
176 | make_fifo(); | |
b3b6e05e | 177 | auto stat = log_backing_type(&dp, ioctx, log_type::fifo, SHARDS, |
f67539c2 TL |
178 | [this](int shard){ return get_oid(0, shard); }, |
179 | null_yield); | |
180 | ASSERT_EQ(log_type::fifo, *stat); | |
181 | } | |
182 | ||
183 | TEST_F(LogBacking, TestFIFOEmpty) | |
184 | { | |
b3b6e05e | 185 | auto stat = log_backing_type(&dp, ioctx, log_type::fifo, SHARDS, |
f67539c2 TL |
186 | [this](int shard){ return get_oid(0, shard); }, |
187 | null_yield); | |
188 | ASSERT_EQ(log_type::fifo, *stat); | |
189 | } | |
190 | ||
191 | TEST(CursorGen, RoundTrip) { | |
192 | const auto pcurs = "fded"sv; | |
193 | { | |
194 | auto gc = gencursor(0, pcurs); | |
195 | ASSERT_EQ(pcurs, gc); | |
196 | auto [gen, cursor] = cursorgen(gc); | |
197 | ASSERT_EQ(0, gen); | |
198 | ASSERT_EQ(pcurs, cursor); | |
199 | } | |
200 | { | |
201 | auto gc = gencursor(53, pcurs); | |
202 | ASSERT_NE(pcurs, gc); | |
203 | auto [gen, cursor] = cursorgen(gc); | |
204 | ASSERT_EQ(53, gen); | |
205 | ASSERT_EQ(pcurs, cursor); | |
206 | } | |
207 | } | |
208 | ||
209 | class generations final : public logback_generations { | |
210 | public: | |
211 | ||
212 | entries_t got_entries; | |
213 | std::optional<uint64_t> tail; | |
214 | ||
215 | using logback_generations::logback_generations; | |
216 | ||
217 | bs::error_code handle_init(entries_t e) noexcept { | |
218 | got_entries = e; | |
219 | return {}; | |
220 | } | |
221 | ||
222 | bs::error_code handle_new_gens(entries_t e) noexcept { | |
223 | got_entries = e; | |
224 | return {}; | |
225 | } | |
226 | ||
227 | bs::error_code handle_empty_to(uint64_t new_tail) noexcept { | |
228 | tail = new_tail; | |
229 | return {}; | |
230 | } | |
231 | }; | |
232 | ||
233 | TEST_F(LogBacking, GenerationSingle) | |
234 | { | |
235 | auto lgr = logback_generations::init<generations>( | |
b3b6e05e | 236 | &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) { |
f67539c2 TL |
237 | return get_oid(gen_id, shard); |
238 | }, SHARDS, log_type::fifo, null_yield); | |
239 | ASSERT_TRUE(lgr); | |
240 | ||
241 | auto lg = std::move(*lgr); | |
242 | ||
243 | ASSERT_EQ(0, lg->got_entries.begin()->first); | |
244 | ||
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); | |
248 | ||
b3b6e05e | 249 | auto ec = lg->empty_to(&dp, 0, null_yield); |
f67539c2 TL |
250 | ASSERT_TRUE(ec); |
251 | ||
f67539c2 TL |
252 | lg.reset(); |
253 | ||
254 | lg = *logback_generations::init<generations>( | |
b3b6e05e | 255 | &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) { |
f67539c2 TL |
256 | return get_oid(gen_id, shard); |
257 | }, SHARDS, log_type::fifo, null_yield); | |
258 | ||
259 | ASSERT_EQ(0, lg->got_entries.begin()->first); | |
260 | ||
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); | |
264 | ||
265 | lg->got_entries.clear(); | |
266 | ||
b3b6e05e | 267 | ec = lg->new_backing(&dp, log_type::omap, null_yield); |
f67539c2 TL |
268 | ASSERT_FALSE(ec); |
269 | ||
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); | |
274 | ||
275 | lg.reset(); | |
276 | ||
277 | lg = *logback_generations::init<generations>( | |
b3b6e05e | 278 | &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) { |
f67539c2 TL |
279 | return get_oid(gen_id, shard); |
280 | }, SHARDS, log_type::fifo, null_yield); | |
281 | ||
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); | |
286 | ||
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); | |
290 | ||
b3b6e05e | 291 | ec = lg->empty_to(&dp, 0, null_yield); |
f67539c2 TL |
292 | ASSERT_FALSE(ec); |
293 | ||
294 | ASSERT_EQ(0, *lg->tail); | |
295 | ||
296 | lg.reset(); | |
297 | ||
298 | lg = *logback_generations::init<generations>( | |
b3b6e05e | 299 | &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) { |
f67539c2 TL |
300 | return get_oid(gen_id, shard); |
301 | }, SHARDS, log_type::fifo, null_yield); | |
302 | ||
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); | |
f67539c2 TL |
307 | } |
308 | ||
309 | TEST_F(LogBacking, GenerationWN) | |
310 | { | |
311 | auto lg1 = *logback_generations::init<generations>( | |
b3b6e05e | 312 | &dp, ioctx, "foobar", [this](uint64_t gen_id, int shard) { |
f67539c2 TL |
313 | return get_oid(gen_id, shard); |
314 | }, SHARDS, log_type::fifo, null_yield); | |
315 | ||
b3b6e05e | 316 | auto ec = lg1->new_backing(&dp, log_type::omap, null_yield); |
f67539c2 TL |
317 | ASSERT_FALSE(ec); |
318 | ||
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); | |
323 | ||
324 | lg1->got_entries.clear(); | |
325 | ||
326 | auto lg2 = *logback_generations::init<generations>( | |
b3b6e05e | 327 | &dp, ioctx2, "foobar", [this](uint64_t gen_id, int shard) { |
f67539c2 TL |
328 | return get_oid(gen_id, shard); |
329 | }, SHARDS, log_type::fifo, null_yield); | |
330 | ||
331 | ASSERT_EQ(2, lg2->got_entries.size()); | |
332 | ||
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); | |
336 | ||
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); | |
340 | ||
341 | lg2->got_entries.clear(); | |
342 | ||
b3b6e05e | 343 | ec = lg1->new_backing(&dp, log_type::fifo, null_yield); |
f67539c2 TL |
344 | ASSERT_FALSE(ec); |
345 | ||
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); | |
350 | ||
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); | |
355 | ||
356 | lg1->got_entries.clear(); | |
357 | lg2->got_entries.clear(); | |
358 | ||
b3b6e05e | 359 | ec = lg2->empty_to(&dp, 1, null_yield); |
f67539c2 TL |
360 | ASSERT_FALSE(ec); |
361 | ||
362 | ASSERT_EQ(1, *lg1->tail); | |
363 | ASSERT_EQ(1, *lg2->tail); | |
364 | ||
365 | lg1->tail.reset(); | |
366 | lg2->tail.reset(); | |
367 | } |