]>
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 <cerrno> | |
16 | #include <iostream> | |
17 | #include <string_view> | |
18 | ||
19 | #include "include/scope_guard.h" | |
20 | #include "include/types.h" | |
21 | #include "include/rados/librados.hpp" | |
b3b6e05e | 22 | #include "common/ceph_context.h" |
f67539c2 TL |
23 | |
24 | #include "cls/fifo/cls_fifo_ops.h" | |
25 | #include "test/librados/test_cxx.h" | |
26 | #include "global/global_context.h" | |
27 | ||
28 | #include "rgw/rgw_tools.h" | |
29 | #include "rgw/cls_fifo_legacy.h" | |
30 | ||
31 | #include "gtest/gtest.h" | |
32 | ||
33 | namespace R = librados; | |
34 | namespace cb = ceph::buffer; | |
35 | namespace fifo = rados::cls::fifo; | |
36 | namespace RCf = rgw::cls::fifo; | |
37 | ||
b3b6e05e TL |
38 | auto cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT); |
39 | const DoutPrefix dp(cct, 1, "test legacy cls fifo: "); | |
40 | ||
f67539c2 | 41 | namespace { |
b3b6e05e | 42 | int fifo_create(const DoutPrefixProvider *dpp, R::IoCtx& ioctx, |
f67539c2 TL |
43 | const std::string& oid, |
44 | std::string_view id, | |
45 | optional_yield y, | |
46 | std::optional<fifo::objv> objv = std::nullopt, | |
47 | std::optional<std::string_view> oid_prefix = std::nullopt, | |
48 | bool exclusive = false, | |
49 | std::uint64_t max_part_size = RCf::default_max_part_size, | |
50 | std::uint64_t max_entry_size = RCf::default_max_entry_size) | |
51 | { | |
52 | R::ObjectWriteOperation op; | |
53 | RCf::create_meta(&op, id, objv, oid_prefix, exclusive, max_part_size, | |
54 | max_entry_size); | |
b3b6e05e | 55 | return rgw_rados_operate(dpp, ioctx, oid, &op, y); |
f67539c2 TL |
56 | } |
57 | } | |
58 | ||
59 | class LegacyFIFO : public testing::Test { | |
60 | protected: | |
61 | const std::string pool_name = get_temp_pool_name(); | |
62 | const std::string fifo_id = "fifo"; | |
63 | R::Rados rados; | |
64 | librados::IoCtx ioctx; | |
65 | ||
66 | void SetUp() override { | |
67 | ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); | |
68 | ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); | |
69 | } | |
70 | void TearDown() override { | |
71 | destroy_one_pool_pp(pool_name, rados); | |
72 | } | |
73 | }; | |
74 | ||
75 | using LegacyClsFIFO = LegacyFIFO; | |
76 | using AioLegacyFIFO = LegacyFIFO; | |
77 | ||
78 | ||
79 | TEST_F(LegacyClsFIFO, TestCreate) | |
80 | { | |
b3b6e05e | 81 | auto r = fifo_create(&dp, ioctx, fifo_id, ""s, null_yield); |
f67539c2 | 82 | EXPECT_EQ(-EINVAL, r); |
b3b6e05e | 83 | r = fifo_create(&dp, ioctx, fifo_id, fifo_id, null_yield, std::nullopt, |
f67539c2 TL |
84 | std::nullopt, false, 0); |
85 | EXPECT_EQ(-EINVAL, r); | |
b3b6e05e | 86 | r = fifo_create(&dp, ioctx, fifo_id, {}, null_yield, |
f67539c2 TL |
87 | std::nullopt, std::nullopt, |
88 | false, RCf::default_max_part_size, 0); | |
89 | EXPECT_EQ(-EINVAL, r); | |
b3b6e05e | 90 | r = fifo_create(&dp, ioctx, fifo_id, fifo_id, null_yield); |
f67539c2 TL |
91 | EXPECT_EQ(0, r); |
92 | std::uint64_t size; | |
93 | ioctx.stat(fifo_id, &size, nullptr); | |
94 | EXPECT_GT(size, 0); | |
95 | /* test idempotency */ | |
b3b6e05e | 96 | r = fifo_create(&dp, ioctx, fifo_id, fifo_id, null_yield); |
f67539c2 | 97 | EXPECT_EQ(0, r); |
b3b6e05e | 98 | r = fifo_create(&dp, ioctx, fifo_id, {}, null_yield, std::nullopt, |
f67539c2 TL |
99 | std::nullopt, false); |
100 | EXPECT_EQ(-EINVAL, r); | |
b3b6e05e | 101 | r = fifo_create(&dp, ioctx, fifo_id, {}, null_yield, std::nullopt, |
f67539c2 TL |
102 | "myprefix"sv, false); |
103 | EXPECT_EQ(-EINVAL, r); | |
b3b6e05e | 104 | r = fifo_create(&dp, ioctx, fifo_id, "foo"sv, null_yield, |
f67539c2 TL |
105 | std::nullopt, std::nullopt, false); |
106 | EXPECT_EQ(-EEXIST, r); | |
107 | } | |
108 | ||
109 | TEST_F(LegacyClsFIFO, TestGetInfo) | |
110 | { | |
b3b6e05e | 111 | auto r = fifo_create(&dp, ioctx, fifo_id, fifo_id, null_yield); |
f67539c2 TL |
112 | fifo::info info; |
113 | std::uint32_t part_header_size; | |
114 | std::uint32_t part_entry_overhead; | |
b3b6e05e | 115 | r = RCf::get_meta(&dp, ioctx, fifo_id, std::nullopt, &info, &part_header_size, |
f67539c2 TL |
116 | &part_entry_overhead, 0, null_yield); |
117 | EXPECT_EQ(0, r); | |
118 | EXPECT_GT(part_header_size, 0); | |
119 | EXPECT_GT(part_entry_overhead, 0); | |
120 | EXPECT_FALSE(info.version.instance.empty()); | |
121 | ||
b3b6e05e | 122 | r = RCf::get_meta(&dp, ioctx, fifo_id, info.version, &info, &part_header_size, |
f67539c2 TL |
123 | &part_entry_overhead, 0, null_yield); |
124 | EXPECT_EQ(0, r); | |
125 | fifo::objv objv; | |
126 | objv.instance = "foo"; | |
127 | objv.ver = 12; | |
b3b6e05e | 128 | r = RCf::get_meta(&dp, ioctx, fifo_id, objv, &info, &part_header_size, |
f67539c2 TL |
129 | &part_entry_overhead, 0, null_yield); |
130 | EXPECT_EQ(-ECANCELED, r); | |
131 | } | |
132 | ||
133 | TEST_F(LegacyFIFO, TestOpenDefault) | |
134 | { | |
135 | std::unique_ptr<RCf::FIFO> fifo; | |
b3b6e05e | 136 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &fifo, null_yield); |
f67539c2 TL |
137 | ASSERT_EQ(0, r); |
138 | // force reading from backend | |
b3b6e05e | 139 | r = fifo->read_meta(&dp, null_yield); |
f67539c2 TL |
140 | EXPECT_EQ(0, r); |
141 | auto info = fifo->meta(); | |
142 | EXPECT_EQ(info.id, fifo_id); | |
143 | } | |
144 | ||
145 | TEST_F(LegacyFIFO, TestOpenParams) | |
146 | { | |
147 | const std::uint64_t max_part_size = 10 * 1024; | |
148 | const std::uint64_t max_entry_size = 128; | |
149 | auto oid_prefix = "foo.123."sv; | |
150 | fifo::objv objv; | |
151 | objv.instance = "fooz"s; | |
152 | objv.ver = 10; | |
153 | ||
154 | /* first successful create */ | |
155 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 156 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, objv, oid_prefix, |
f67539c2 TL |
157 | false, max_part_size, max_entry_size); |
158 | ASSERT_EQ(0, r); | |
159 | ||
160 | /* force reading from backend */ | |
b3b6e05e | 161 | r = f->read_meta(&dp, null_yield); |
f67539c2 TL |
162 | auto info = f->meta(); |
163 | EXPECT_EQ(info.id, fifo_id); | |
164 | EXPECT_EQ(info.params.max_part_size, max_part_size); | |
165 | EXPECT_EQ(info.params.max_entry_size, max_entry_size); | |
166 | EXPECT_EQ(info.version, objv); | |
167 | } | |
168 | ||
169 | namespace { | |
170 | template<class T> | |
171 | std::pair<T, std::string> decode_entry(const RCf::list_entry& entry) | |
172 | { | |
173 | T val; | |
174 | auto iter = entry.data.cbegin(); | |
175 | decode(val, iter); | |
176 | return std::make_pair(std::move(val), entry.marker); | |
177 | } | |
178 | } | |
179 | ||
180 | ||
181 | TEST_F(LegacyFIFO, TestPushListTrim) | |
182 | { | |
183 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 184 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield); |
f67539c2 TL |
185 | ASSERT_EQ(0, r); |
186 | static constexpr auto max_entries = 10u; | |
187 | for (uint32_t i = 0; i < max_entries; ++i) { | |
188 | cb::list bl; | |
189 | encode(i, bl); | |
b3b6e05e | 190 | r = f->push(&dp, bl, null_yield); |
f67539c2 TL |
191 | ASSERT_EQ(0, r); |
192 | } | |
193 | ||
194 | std::optional<std::string> marker; | |
195 | /* get entries one by one */ | |
196 | std::vector<RCf::list_entry> result; | |
197 | bool more = false; | |
198 | for (auto i = 0u; i < max_entries; ++i) { | |
199 | ||
b3b6e05e | 200 | r = f->list(&dp, 1, marker, &result, &more, null_yield); |
f67539c2 TL |
201 | ASSERT_EQ(0, r); |
202 | ||
203 | bool expected_more = (i != (max_entries - 1)); | |
204 | ASSERT_EQ(expected_more, more); | |
205 | ASSERT_EQ(1, result.size()); | |
206 | ||
207 | std::uint32_t val; | |
208 | std::tie(val, marker) = decode_entry<std::uint32_t>(result.front()); | |
209 | ||
210 | ASSERT_EQ(i, val); | |
211 | result.clear(); | |
212 | } | |
213 | ||
214 | /* get all entries at once */ | |
215 | std::string markers[max_entries]; | |
216 | std::uint32_t min_entry = 0; | |
b3b6e05e | 217 | r = f->list(&dp, max_entries * 10, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
218 | ASSERT_EQ(0, r); |
219 | ||
220 | ASSERT_FALSE(more); | |
221 | ASSERT_EQ(max_entries, result.size()); | |
222 | for (auto i = 0u; i < max_entries; ++i) { | |
223 | std::uint32_t val; | |
224 | std::tie(val, markers[i]) = decode_entry<std::uint32_t>(result[i]); | |
225 | ASSERT_EQ(i, val); | |
226 | } | |
227 | ||
228 | /* trim one entry */ | |
b3b6e05e | 229 | r = f->trim(&dp, markers[min_entry], false, null_yield); |
f67539c2 TL |
230 | ASSERT_EQ(0, r); |
231 | ++min_entry; | |
232 | ||
b3b6e05e | 233 | r = f->list(&dp, max_entries * 10, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
234 | ASSERT_EQ(0, r); |
235 | ASSERT_FALSE(more); | |
236 | ASSERT_EQ(max_entries - min_entry, result.size()); | |
237 | ||
238 | for (auto i = min_entry; i < max_entries; ++i) { | |
239 | std::uint32_t val; | |
240 | std::tie(val, markers[i - min_entry]) = | |
241 | decode_entry<std::uint32_t>(result[i - min_entry]); | |
242 | EXPECT_EQ(i, val); | |
243 | } | |
244 | } | |
245 | ||
246 | ||
247 | TEST_F(LegacyFIFO, TestPushTooBig) | |
248 | { | |
249 | static constexpr auto max_part_size = 2048ull; | |
250 | static constexpr auto max_entry_size = 128ull; | |
251 | ||
252 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 253 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
254 | std::nullopt, false, max_part_size, max_entry_size); |
255 | ASSERT_EQ(0, r); | |
256 | ||
257 | char buf[max_entry_size + 1]; | |
258 | memset(buf, 0, sizeof(buf)); | |
259 | ||
260 | cb::list bl; | |
261 | bl.append(buf, sizeof(buf)); | |
262 | ||
b3b6e05e | 263 | r = f->push(&dp, bl, null_yield); |
f67539c2 TL |
264 | EXPECT_EQ(-E2BIG, r); |
265 | } | |
266 | ||
267 | ||
268 | TEST_F(LegacyFIFO, TestMultipleParts) | |
269 | { | |
270 | static constexpr auto max_part_size = 2048ull; | |
271 | static constexpr auto max_entry_size = 128ull; | |
272 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 273 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
274 | std::nullopt, false, max_part_size, |
275 | max_entry_size); | |
276 | ASSERT_EQ(0, r); | |
277 | ||
278 | char buf[max_entry_size]; | |
279 | memset(buf, 0, sizeof(buf)); | |
280 | const auto [part_header_size, part_entry_overhead] = | |
281 | f->get_part_layout_info(); | |
282 | const auto entries_per_part = ((max_part_size - part_header_size) / | |
283 | (max_entry_size + part_entry_overhead)); | |
284 | const auto max_entries = entries_per_part * 4 + 1; | |
285 | /* push enough entries */ | |
286 | for (auto i = 0u; i < max_entries; ++i) { | |
287 | cb::list bl; | |
288 | *(int *)buf = i; | |
289 | bl.append(buf, sizeof(buf)); | |
b3b6e05e | 290 | r = f->push(&dp, bl, null_yield); |
f67539c2 TL |
291 | ASSERT_EQ(0, r); |
292 | } | |
293 | ||
294 | auto info = f->meta(); | |
295 | ASSERT_EQ(info.id, fifo_id); | |
296 | /* head should have advanced */ | |
297 | ASSERT_GT(info.head_part_num, 0); | |
298 | ||
299 | /* list all at once */ | |
300 | std::vector<RCf::list_entry> result; | |
301 | bool more = false; | |
b3b6e05e | 302 | r = f->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
303 | ASSERT_EQ(0, r); |
304 | EXPECT_EQ(false, more); | |
305 | ASSERT_EQ(max_entries, result.size()); | |
306 | ||
307 | for (auto i = 0u; i < max_entries; ++i) { | |
308 | auto& bl = result[i].data; | |
309 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
310 | } | |
311 | ||
312 | std::optional<std::string> marker; | |
313 | /* get entries one by one */ | |
314 | ||
315 | for (auto i = 0u; i < max_entries; ++i) { | |
b3b6e05e | 316 | r = f->list(&dp, 1, marker, &result, &more, null_yield); |
f67539c2 TL |
317 | ASSERT_EQ(0, r); |
318 | ASSERT_EQ(result.size(), 1); | |
319 | const bool expected_more = (i != (max_entries - 1)); | |
320 | ASSERT_EQ(expected_more, more); | |
321 | ||
322 | std::uint32_t val; | |
323 | std::tie(val, marker) = decode_entry<std::uint32_t>(result.front()); | |
324 | ||
325 | auto& entry = result.front(); | |
326 | auto& bl = entry.data; | |
327 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
328 | marker = entry.marker; | |
329 | } | |
330 | ||
331 | /* trim one at a time */ | |
332 | marker.reset(); | |
333 | for (auto i = 0u; i < max_entries; ++i) { | |
334 | /* read single entry */ | |
b3b6e05e | 335 | r = f->list(&dp, 1, marker, &result, &more, null_yield); |
f67539c2 TL |
336 | ASSERT_EQ(0, r); |
337 | ASSERT_EQ(result.size(), 1); | |
338 | const bool expected_more = (i != (max_entries - 1)); | |
339 | ASSERT_EQ(expected_more, more); | |
340 | ||
341 | marker = result.front().marker; | |
b3b6e05e | 342 | r = f->trim(&dp, *marker, false, null_yield); |
f67539c2 TL |
343 | ASSERT_EQ(0, r); |
344 | ||
345 | /* check tail */ | |
346 | info = f->meta(); | |
347 | ASSERT_EQ(info.tail_part_num, i / entries_per_part); | |
348 | ||
349 | /* try to read all again, see how many entries left */ | |
b3b6e05e | 350 | r = f->list(&dp, max_entries, marker, &result, &more, null_yield); |
f67539c2 TL |
351 | ASSERT_EQ(max_entries - i - 1, result.size()); |
352 | ASSERT_EQ(false, more); | |
353 | } | |
354 | ||
355 | /* tail now should point at head */ | |
356 | info = f->meta(); | |
357 | ASSERT_EQ(info.head_part_num, info.tail_part_num); | |
358 | ||
359 | RCf::part_info partinfo; | |
360 | /* check old tails are removed */ | |
361 | for (auto i = 0; i < info.tail_part_num; ++i) { | |
b3b6e05e | 362 | r = f->get_part_info(&dp, i, &partinfo, null_yield); |
f67539c2 TL |
363 | ASSERT_EQ(-ENOENT, r); |
364 | } | |
365 | /* check current tail exists */ | |
b3b6e05e | 366 | r = f->get_part_info(&dp, info.tail_part_num, &partinfo, null_yield); |
f67539c2 TL |
367 | ASSERT_EQ(0, r); |
368 | } | |
369 | ||
370 | TEST_F(LegacyFIFO, TestTwoPushers) | |
371 | { | |
372 | static constexpr auto max_part_size = 2048ull; | |
373 | static constexpr auto max_entry_size = 128ull; | |
374 | ||
375 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 376 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
377 | std::nullopt, false, max_part_size, |
378 | max_entry_size); | |
379 | ASSERT_EQ(0, r); | |
380 | char buf[max_entry_size]; | |
381 | memset(buf, 0, sizeof(buf)); | |
382 | ||
383 | auto [part_header_size, part_entry_overhead] = f->get_part_layout_info(); | |
384 | const auto entries_per_part = ((max_part_size - part_header_size) / | |
385 | (max_entry_size + part_entry_overhead)); | |
386 | const auto max_entries = entries_per_part * 4 + 1; | |
387 | std::unique_ptr<RCf::FIFO> f2; | |
b3b6e05e | 388 | r = RCf::FIFO::open(&dp, ioctx, fifo_id, &f2, null_yield); |
f67539c2 TL |
389 | std::vector fifos{&f, &f2}; |
390 | ||
391 | for (auto i = 0u; i < max_entries; ++i) { | |
392 | cb::list bl; | |
393 | *(int *)buf = i; | |
394 | bl.append(buf, sizeof(buf)); | |
395 | auto& f = *fifos[i % fifos.size()]; | |
b3b6e05e | 396 | r = f->push(&dp, bl, null_yield); |
f67539c2 TL |
397 | ASSERT_EQ(0, r); |
398 | } | |
399 | ||
400 | /* list all by both */ | |
401 | std::vector<RCf::list_entry> result; | |
402 | bool more = false; | |
b3b6e05e | 403 | r = f2->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
404 | ASSERT_EQ(0, r); |
405 | ASSERT_EQ(false, more); | |
406 | ASSERT_EQ(max_entries, result.size()); | |
407 | ||
b3b6e05e | 408 | r = f2->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
409 | ASSERT_EQ(0, r); |
410 | ASSERT_EQ(false, more); | |
411 | ASSERT_EQ(max_entries, result.size()); | |
412 | ||
413 | for (auto i = 0u; i < max_entries; ++i) { | |
414 | auto& bl = result[i].data; | |
415 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
416 | } | |
417 | } | |
418 | ||
419 | TEST_F(LegacyFIFO, TestTwoPushersTrim) | |
420 | { | |
421 | static constexpr auto max_part_size = 2048ull; | |
422 | static constexpr auto max_entry_size = 128ull; | |
423 | std::unique_ptr<RCf::FIFO> f1; | |
b3b6e05e | 424 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f1, null_yield, std::nullopt, |
f67539c2 TL |
425 | std::nullopt, false, max_part_size, |
426 | max_entry_size); | |
427 | ASSERT_EQ(0, r); | |
428 | ||
429 | char buf[max_entry_size]; | |
430 | memset(buf, 0, sizeof(buf)); | |
431 | ||
432 | auto [part_header_size, part_entry_overhead] = f1->get_part_layout_info(); | |
433 | const auto entries_per_part = ((max_part_size - part_header_size) / | |
434 | (max_entry_size + part_entry_overhead)); | |
435 | const auto max_entries = entries_per_part * 4 + 1; | |
436 | ||
437 | std::unique_ptr<RCf::FIFO> f2; | |
b3b6e05e | 438 | r = RCf::FIFO::open(&dp, ioctx, fifo_id, &f2, null_yield); |
f67539c2 TL |
439 | ASSERT_EQ(0, r); |
440 | ||
441 | /* push one entry to f2 and the rest to f1 */ | |
442 | for (auto i = 0u; i < max_entries; ++i) { | |
443 | cb::list bl; | |
444 | *(int *)buf = i; | |
445 | bl.append(buf, sizeof(buf)); | |
446 | auto& f = (i < 1 ? f2 : f1); | |
b3b6e05e | 447 | r = f->push(&dp, bl, null_yield); |
f67539c2 TL |
448 | ASSERT_EQ(0, r); |
449 | } | |
450 | ||
451 | /* trim half by fifo1 */ | |
452 | auto num = max_entries / 2; | |
453 | std::string marker; | |
454 | std::vector<RCf::list_entry> result; | |
455 | bool more = false; | |
b3b6e05e | 456 | r = f1->list(&dp, num, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
457 | ASSERT_EQ(0, r); |
458 | ASSERT_EQ(true, more); | |
459 | ASSERT_EQ(num, result.size()); | |
460 | ||
461 | for (auto i = 0u; i < num; ++i) { | |
462 | auto& bl = result[i].data; | |
463 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
464 | } | |
465 | ||
466 | auto& entry = result[num - 1]; | |
467 | marker = entry.marker; | |
b3b6e05e | 468 | r = f1->trim(&dp, marker, false, null_yield); |
f67539c2 TL |
469 | /* list what's left by fifo2 */ |
470 | ||
471 | const auto left = max_entries - num; | |
b3b6e05e | 472 | f2->list(&dp, left, marker, &result, &more, null_yield); |
f67539c2 TL |
473 | ASSERT_EQ(left, result.size()); |
474 | ASSERT_EQ(false, more); | |
475 | ||
476 | for (auto i = num; i < max_entries; ++i) { | |
477 | auto& bl = result[i - num].data; | |
478 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
479 | } | |
480 | } | |
481 | ||
482 | TEST_F(LegacyFIFO, TestPushBatch) | |
483 | { | |
484 | static constexpr auto max_part_size = 2048ull; | |
485 | static constexpr auto max_entry_size = 128ull; | |
486 | ||
487 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 488 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
489 | std::nullopt, false, max_part_size, |
490 | max_entry_size); | |
491 | ASSERT_EQ(0, r); | |
492 | ||
493 | char buf[max_entry_size]; | |
494 | memset(buf, 0, sizeof(buf)); | |
495 | auto [part_header_size, part_entry_overhead] = f->get_part_layout_info(); | |
496 | auto entries_per_part = ((max_part_size - part_header_size) / | |
497 | (max_entry_size + part_entry_overhead)); | |
498 | auto max_entries = entries_per_part * 4 + 1; /* enough entries to span multiple parts */ | |
499 | std::vector<cb::list> bufs; | |
500 | for (auto i = 0u; i < max_entries; ++i) { | |
501 | cb::list bl; | |
502 | *(int *)buf = i; | |
503 | bl.append(buf, sizeof(buf)); | |
504 | bufs.push_back(bl); | |
505 | } | |
506 | ASSERT_EQ(max_entries, bufs.size()); | |
507 | ||
b3b6e05e | 508 | r = f->push(&dp, bufs, null_yield); |
f67539c2 TL |
509 | ASSERT_EQ(0, r); |
510 | ||
511 | /* list all */ | |
512 | ||
513 | std::vector<RCf::list_entry> result; | |
514 | bool more = false; | |
b3b6e05e | 515 | r = f->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
516 | ASSERT_EQ(0, r); |
517 | ASSERT_EQ(false, more); | |
518 | ASSERT_EQ(max_entries, result.size()); | |
519 | for (auto i = 0u; i < max_entries; ++i) { | |
520 | auto& bl = result[i].data; | |
521 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
522 | } | |
523 | auto& info = f->meta(); | |
524 | ASSERT_EQ(info.head_part_num, 4); | |
525 | } | |
526 | ||
527 | TEST_F(LegacyFIFO, TestAioTrim) | |
528 | { | |
529 | static constexpr auto max_part_size = 2048ull; | |
530 | static constexpr auto max_entry_size = 128ull; | |
531 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 532 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
533 | std::nullopt, false, max_part_size, |
534 | max_entry_size); | |
535 | ASSERT_EQ(0, r); | |
536 | ||
537 | char buf[max_entry_size]; | |
538 | memset(buf, 0, sizeof(buf)); | |
539 | const auto [part_header_size, part_entry_overhead] = | |
540 | f->get_part_layout_info(); | |
541 | const auto entries_per_part = ((max_part_size - part_header_size) / | |
542 | (max_entry_size + part_entry_overhead)); | |
543 | const auto max_entries = entries_per_part * 4 + 1; | |
544 | /* push enough entries */ | |
545 | std::vector<cb::list> bufs; | |
546 | for (auto i = 0u; i < max_entries; ++i) { | |
547 | cb::list bl; | |
548 | *(int *)buf = i; | |
549 | bl.append(buf, sizeof(buf)); | |
550 | bufs.push_back(std::move(bl)); | |
551 | } | |
552 | ASSERT_EQ(max_entries, bufs.size()); | |
553 | ||
b3b6e05e | 554 | r = f->push(&dp, bufs, null_yield); |
f67539c2 TL |
555 | ASSERT_EQ(0, r); |
556 | ||
557 | auto info = f->meta(); | |
558 | ASSERT_EQ(info.id, fifo_id); | |
559 | /* head should have advanced */ | |
560 | ASSERT_GT(info.head_part_num, 0); | |
561 | ||
562 | /* list all at once */ | |
563 | std::vector<RCf::list_entry> result; | |
564 | bool more = false; | |
b3b6e05e | 565 | r = f->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
566 | ASSERT_EQ(0, r); |
567 | ASSERT_EQ(false, more); | |
568 | ASSERT_EQ(max_entries, result.size()); | |
569 | ||
570 | std::optional<std::string> marker; | |
571 | /* trim one at a time */ | |
572 | result.clear(); | |
573 | more = false; | |
574 | marker.reset(); | |
575 | for (auto i = 0u; i < max_entries; ++i) { | |
576 | /* read single entry */ | |
b3b6e05e | 577 | r = f->list(&dp, 1, marker, &result, &more, null_yield); |
f67539c2 TL |
578 | ASSERT_EQ(0, r); |
579 | ASSERT_EQ(result.size(), 1); | |
580 | const bool expected_more = (i != (max_entries - 1)); | |
581 | ASSERT_EQ(expected_more, more); | |
582 | ||
583 | marker = result.front().marker; | |
584 | std::unique_ptr<R::AioCompletion> c(rados.aio_create_completion(nullptr, | |
585 | nullptr)); | |
b3b6e05e | 586 | f->trim(&dp, *marker, false, c.get()); |
f67539c2 TL |
587 | c->wait_for_complete(); |
588 | r = c->get_return_value(); | |
589 | ASSERT_EQ(0, r); | |
590 | ||
591 | /* check tail */ | |
592 | info = f->meta(); | |
593 | ASSERT_EQ(info.tail_part_num, i / entries_per_part); | |
594 | ||
595 | /* try to read all again, see how many entries left */ | |
b3b6e05e | 596 | r = f->list(&dp, max_entries, marker, &result, &more, null_yield); |
f67539c2 TL |
597 | ASSERT_EQ(max_entries - i - 1, result.size()); |
598 | ASSERT_EQ(false, more); | |
599 | } | |
600 | ||
601 | /* tail now should point at head */ | |
602 | info = f->meta(); | |
603 | ASSERT_EQ(info.head_part_num, info.tail_part_num); | |
604 | ||
605 | RCf::part_info partinfo; | |
606 | /* check old tails are removed */ | |
607 | for (auto i = 0; i < info.tail_part_num; ++i) { | |
b3b6e05e | 608 | r = f->get_part_info(&dp, i, &partinfo, null_yield); |
f67539c2 TL |
609 | ASSERT_EQ(-ENOENT, r); |
610 | } | |
611 | /* check current tail exists */ | |
b3b6e05e | 612 | r = f->get_part_info(&dp, info.tail_part_num, &partinfo, null_yield); |
f67539c2 TL |
613 | ASSERT_EQ(0, r); |
614 | } | |
615 | ||
616 | TEST_F(LegacyFIFO, TestTrimExclusive) { | |
617 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 618 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield); |
f67539c2 TL |
619 | ASSERT_EQ(0, r); |
620 | std::vector<RCf::list_entry> result; | |
621 | bool more = false; | |
622 | ||
623 | static constexpr auto max_entries = 10u; | |
624 | for (uint32_t i = 0; i < max_entries; ++i) { | |
625 | cb::list bl; | |
626 | encode(i, bl); | |
b3b6e05e | 627 | f->push(&dp, bl, null_yield); |
f67539c2 TL |
628 | } |
629 | ||
b3b6e05e | 630 | f->list(&dp, 1, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
631 | auto [val, marker] = decode_entry<std::uint32_t>(result.front()); |
632 | ASSERT_EQ(0, val); | |
b3b6e05e | 633 | f->trim(&dp, marker, true, null_yield); |
f67539c2 TL |
634 | |
635 | result.clear(); | |
b3b6e05e | 636 | f->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
637 | std::tie(val, marker) = decode_entry<std::uint32_t>(result.front()); |
638 | ASSERT_EQ(0, val); | |
b3b6e05e | 639 | f->trim(&dp, result[4].marker, true, null_yield); |
f67539c2 TL |
640 | |
641 | result.clear(); | |
b3b6e05e | 642 | f->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
643 | std::tie(val, marker) = decode_entry<std::uint32_t>(result.front()); |
644 | ASSERT_EQ(4, val); | |
b3b6e05e | 645 | f->trim(&dp, result.back().marker, true, null_yield); |
f67539c2 TL |
646 | |
647 | result.clear(); | |
b3b6e05e | 648 | f->list(&dp, max_entries, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
649 | std::tie(val, marker) = decode_entry<std::uint32_t>(result.front()); |
650 | ASSERT_EQ(result.size(), 1); | |
651 | ASSERT_EQ(max_entries - 1, val); | |
652 | } | |
653 | ||
654 | TEST_F(AioLegacyFIFO, TestPushListTrim) | |
655 | { | |
656 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 657 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield); |
f67539c2 TL |
658 | ASSERT_EQ(0, r); |
659 | static constexpr auto max_entries = 10u; | |
660 | for (uint32_t i = 0; i < max_entries; ++i) { | |
661 | cb::list bl; | |
662 | encode(i, bl); | |
663 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 664 | f->push(&dp, bl, c); |
f67539c2 TL |
665 | c->wait_for_complete(); |
666 | r = c->get_return_value(); | |
667 | c->release(); | |
668 | ASSERT_EQ(0, r); | |
669 | } | |
670 | ||
671 | std::optional<std::string> marker; | |
672 | /* get entries one by one */ | |
673 | std::vector<RCf::list_entry> result; | |
674 | bool more = false; | |
675 | for (auto i = 0u; i < max_entries; ++i) { | |
676 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 677 | f->list(&dp, 1, marker, &result, &more, c); |
f67539c2 TL |
678 | c->wait_for_complete(); |
679 | r = c->get_return_value(); | |
680 | c->release(); | |
681 | ASSERT_EQ(0, r); | |
682 | ||
683 | bool expected_more = (i != (max_entries - 1)); | |
684 | ASSERT_EQ(expected_more, more); | |
685 | ASSERT_EQ(1, result.size()); | |
686 | ||
687 | std::uint32_t val; | |
688 | std::tie(val, marker) = decode_entry<std::uint32_t>(result.front()); | |
689 | ||
690 | ASSERT_EQ(i, val); | |
691 | result.clear(); | |
692 | } | |
693 | ||
694 | /* get all entries at once */ | |
695 | std::string markers[max_entries]; | |
696 | std::uint32_t min_entry = 0; | |
697 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 698 | f->list(&dp, max_entries * 10, std::nullopt, &result, &more, c); |
f67539c2 TL |
699 | c->wait_for_complete(); |
700 | r = c->get_return_value(); | |
701 | c->release(); | |
702 | ASSERT_EQ(0, r); | |
703 | ||
704 | ASSERT_FALSE(more); | |
705 | ASSERT_EQ(max_entries, result.size()); | |
706 | for (auto i = 0u; i < max_entries; ++i) { | |
707 | std::uint32_t val; | |
708 | std::tie(val, markers[i]) = decode_entry<std::uint32_t>(result[i]); | |
709 | ASSERT_EQ(i, val); | |
710 | } | |
711 | ||
712 | /* trim one entry */ | |
713 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 714 | f->trim(&dp, markers[min_entry], false, c); |
f67539c2 TL |
715 | c->wait_for_complete(); |
716 | r = c->get_return_value(); | |
717 | c->release(); | |
718 | ASSERT_EQ(0, r); | |
719 | ++min_entry; | |
720 | ||
721 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 722 | f->list(&dp, max_entries * 10, std::nullopt, &result, &more, c); |
f67539c2 TL |
723 | c->wait_for_complete(); |
724 | r = c->get_return_value(); | |
725 | c->release(); | |
726 | ASSERT_EQ(0, r); | |
727 | ASSERT_FALSE(more); | |
728 | ASSERT_EQ(max_entries - min_entry, result.size()); | |
729 | ||
730 | for (auto i = min_entry; i < max_entries; ++i) { | |
731 | std::uint32_t val; | |
732 | std::tie(val, markers[i - min_entry]) = | |
733 | decode_entry<std::uint32_t>(result[i - min_entry]); | |
734 | EXPECT_EQ(i, val); | |
735 | } | |
736 | } | |
737 | ||
738 | ||
739 | TEST_F(AioLegacyFIFO, TestPushTooBig) | |
740 | { | |
741 | static constexpr auto max_part_size = 2048ull; | |
742 | static constexpr auto max_entry_size = 128ull; | |
743 | ||
744 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 745 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
746 | std::nullopt, false, max_part_size, max_entry_size); |
747 | ASSERT_EQ(0, r); | |
748 | ||
749 | char buf[max_entry_size + 1]; | |
750 | memset(buf, 0, sizeof(buf)); | |
751 | ||
752 | cb::list bl; | |
753 | bl.append(buf, sizeof(buf)); | |
754 | ||
755 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 756 | f->push(&dp, bl, c); |
f67539c2 TL |
757 | c->wait_for_complete(); |
758 | r = c->get_return_value(); | |
759 | ASSERT_EQ(-E2BIG, r); | |
760 | c->release(); | |
761 | ||
762 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 763 | f->push(&dp, std::vector<cb::list>{}, c); |
f67539c2 TL |
764 | c->wait_for_complete(); |
765 | r = c->get_return_value(); | |
766 | c->release(); | |
767 | EXPECT_EQ(0, r); | |
768 | } | |
769 | ||
770 | ||
771 | TEST_F(AioLegacyFIFO, TestMultipleParts) | |
772 | { | |
773 | static constexpr auto max_part_size = 2048ull; | |
774 | static constexpr auto max_entry_size = 128ull; | |
775 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 776 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
777 | std::nullopt, false, max_part_size, |
778 | max_entry_size); | |
779 | ASSERT_EQ(0, r); | |
780 | ||
781 | { | |
782 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 783 | f->get_head_info(&dp, [&](int r, RCf::part_info&& p) { |
f67539c2 TL |
784 | ASSERT_TRUE(p.tag.empty()); |
785 | ASSERT_EQ(0, p.magic); | |
786 | ASSERT_EQ(0, p.min_ofs); | |
787 | ASSERT_EQ(0, p.last_ofs); | |
788 | ASSERT_EQ(0, p.next_ofs); | |
789 | ASSERT_EQ(0, p.min_index); | |
790 | ASSERT_EQ(0, p.max_index); | |
791 | ASSERT_EQ(ceph::real_time{}, p.max_time); | |
792 | }, c); | |
793 | c->wait_for_complete(); | |
794 | r = c->get_return_value(); | |
795 | c->release(); | |
796 | } | |
797 | ||
798 | char buf[max_entry_size]; | |
799 | memset(buf, 0, sizeof(buf)); | |
800 | const auto [part_header_size, part_entry_overhead] = | |
801 | f->get_part_layout_info(); | |
802 | const auto entries_per_part = ((max_part_size - part_header_size) / | |
803 | (max_entry_size + part_entry_overhead)); | |
804 | const auto max_entries = entries_per_part * 4 + 1; | |
805 | /* push enough entries */ | |
806 | for (auto i = 0u; i < max_entries; ++i) { | |
807 | cb::list bl; | |
808 | *(int *)buf = i; | |
809 | bl.append(buf, sizeof(buf)); | |
810 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 811 | f->push(&dp, bl, c); |
f67539c2 TL |
812 | c->wait_for_complete(); |
813 | r = c->get_return_value(); | |
814 | c->release(); | |
815 | EXPECT_EQ(0, r); | |
816 | } | |
817 | ||
818 | auto info = f->meta(); | |
819 | ASSERT_EQ(info.id, fifo_id); | |
820 | /* head should have advanced */ | |
821 | ASSERT_GT(info.head_part_num, 0); | |
822 | ||
823 | /* list all at once */ | |
824 | std::vector<RCf::list_entry> result; | |
825 | bool more = false; | |
826 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 827 | f->list(&dp, max_entries, std::nullopt, &result, &more, c); |
f67539c2 TL |
828 | c->wait_for_complete(); |
829 | r = c->get_return_value(); | |
830 | c->release(); | |
831 | EXPECT_EQ(0, r); | |
832 | EXPECT_EQ(false, more); | |
833 | ASSERT_EQ(max_entries, result.size()); | |
834 | ||
835 | for (auto i = 0u; i < max_entries; ++i) { | |
836 | auto& bl = result[i].data; | |
837 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
838 | } | |
839 | ||
840 | std::optional<std::string> marker; | |
841 | /* get entries one by one */ | |
842 | ||
843 | for (auto i = 0u; i < max_entries; ++i) { | |
844 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 845 | f->list(&dp, 1, marker, &result, &more, c); |
f67539c2 TL |
846 | c->wait_for_complete(); |
847 | r = c->get_return_value(); | |
848 | c->release(); | |
849 | EXPECT_EQ(0, r); | |
850 | ASSERT_EQ(result.size(), 1); | |
851 | const bool expected_more = (i != (max_entries - 1)); | |
852 | ASSERT_EQ(expected_more, more); | |
853 | ||
854 | std::uint32_t val; | |
855 | std::tie(val, marker) = decode_entry<std::uint32_t>(result.front()); | |
856 | ||
857 | auto& entry = result.front(); | |
858 | auto& bl = entry.data; | |
859 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
860 | marker = entry.marker; | |
861 | } | |
862 | ||
863 | /* trim one at a time */ | |
864 | marker.reset(); | |
865 | for (auto i = 0u; i < max_entries; ++i) { | |
866 | /* read single entry */ | |
867 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 868 | f->list(&dp, 1, marker, &result, &more, c); |
f67539c2 TL |
869 | c->wait_for_complete(); |
870 | r = c->get_return_value(); | |
871 | c->release(); | |
872 | EXPECT_EQ(0, r); | |
873 | ASSERT_EQ(result.size(), 1); | |
874 | const bool expected_more = (i != (max_entries - 1)); | |
875 | ASSERT_EQ(expected_more, more); | |
876 | ||
877 | marker = result.front().marker; | |
878 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 879 | f->trim(&dp, *marker, false, c); |
f67539c2 TL |
880 | c->wait_for_complete(); |
881 | r = c->get_return_value(); | |
882 | c->release(); | |
883 | EXPECT_EQ(0, r); | |
884 | ASSERT_EQ(result.size(), 1); | |
885 | ||
886 | /* check tail */ | |
887 | info = f->meta(); | |
888 | ASSERT_EQ(info.tail_part_num, i / entries_per_part); | |
889 | ||
890 | /* try to read all again, see how many entries left */ | |
891 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 892 | f->list(&dp, max_entries, marker, &result, &more, c); |
f67539c2 TL |
893 | c->wait_for_complete(); |
894 | r = c->get_return_value(); | |
895 | c->release(); | |
896 | EXPECT_EQ(0, r); | |
897 | ASSERT_EQ(max_entries - i - 1, result.size()); | |
898 | ASSERT_EQ(false, more); | |
899 | } | |
900 | ||
901 | /* tail now should point at head */ | |
902 | info = f->meta(); | |
903 | ASSERT_EQ(info.head_part_num, info.tail_part_num); | |
904 | ||
905 | /* check old tails are removed */ | |
906 | for (auto i = 0; i < info.tail_part_num; ++i) { | |
907 | c = R::Rados::aio_create_completion(); | |
908 | RCf::part_info partinfo; | |
909 | f->get_part_info(i, &partinfo, c); | |
910 | c->wait_for_complete(); | |
911 | r = c->get_return_value(); | |
912 | c->release(); | |
913 | ASSERT_EQ(-ENOENT, r); | |
914 | } | |
915 | /* check current tail exists */ | |
916 | std::uint64_t next_ofs; | |
917 | { | |
918 | c = R::Rados::aio_create_completion(); | |
919 | RCf::part_info partinfo; | |
920 | f->get_part_info(info.tail_part_num, &partinfo, c); | |
921 | c->wait_for_complete(); | |
922 | r = c->get_return_value(); | |
923 | c->release(); | |
924 | next_ofs = partinfo.next_ofs; | |
925 | } | |
926 | ASSERT_EQ(0, r); | |
927 | ||
928 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 929 | f->get_head_info(&dp, [&](int r, RCf::part_info&& p) { |
f67539c2 TL |
930 | ASSERT_EQ(next_ofs, p.next_ofs); |
931 | }, c); | |
932 | c->wait_for_complete(); | |
933 | r = c->get_return_value(); | |
934 | c->release(); | |
935 | ASSERT_EQ(0, r); | |
936 | } | |
937 | ||
938 | TEST_F(AioLegacyFIFO, TestTwoPushers) | |
939 | { | |
940 | static constexpr auto max_part_size = 2048ull; | |
941 | static constexpr auto max_entry_size = 128ull; | |
942 | ||
943 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 944 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
945 | std::nullopt, false, max_part_size, |
946 | max_entry_size); | |
947 | ASSERT_EQ(0, r); | |
948 | char buf[max_entry_size]; | |
949 | memset(buf, 0, sizeof(buf)); | |
950 | ||
951 | auto [part_header_size, part_entry_overhead] = f->get_part_layout_info(); | |
952 | const auto entries_per_part = ((max_part_size - part_header_size) / | |
953 | (max_entry_size + part_entry_overhead)); | |
954 | const auto max_entries = entries_per_part * 4 + 1; | |
955 | std::unique_ptr<RCf::FIFO> f2; | |
b3b6e05e | 956 | r = RCf::FIFO::open(&dp, ioctx, fifo_id, &f2, null_yield); |
f67539c2 TL |
957 | std::vector fifos{&f, &f2}; |
958 | ||
959 | for (auto i = 0u; i < max_entries; ++i) { | |
960 | cb::list bl; | |
961 | *(int *)buf = i; | |
962 | bl.append(buf, sizeof(buf)); | |
963 | auto& f = *fifos[i % fifos.size()]; | |
964 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 965 | f->push(&dp, bl, c); |
f67539c2 TL |
966 | c->wait_for_complete(); |
967 | r = c->get_return_value(); | |
968 | c->release(); | |
969 | ASSERT_EQ(0, r); | |
970 | } | |
971 | ||
972 | /* list all by both */ | |
973 | std::vector<RCf::list_entry> result; | |
974 | bool more = false; | |
975 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 976 | f2->list(&dp, max_entries, std::nullopt, &result, &more, c); |
f67539c2 TL |
977 | c->wait_for_complete(); |
978 | r = c->get_return_value(); | |
979 | c->release(); | |
980 | ASSERT_EQ(0, r); | |
981 | ASSERT_EQ(false, more); | |
982 | ASSERT_EQ(max_entries, result.size()); | |
983 | ||
984 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 985 | f2->list(&dp, max_entries, std::nullopt, &result, &more, c); |
f67539c2 TL |
986 | c->wait_for_complete(); |
987 | r = c->get_return_value(); | |
988 | c->release(); | |
989 | ASSERT_EQ(0, r); | |
990 | ASSERT_EQ(false, more); | |
991 | ASSERT_EQ(max_entries, result.size()); | |
992 | ||
993 | for (auto i = 0u; i < max_entries; ++i) { | |
994 | auto& bl = result[i].data; | |
995 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
996 | } | |
997 | } | |
998 | ||
999 | TEST_F(AioLegacyFIFO, TestTwoPushersTrim) | |
1000 | { | |
1001 | static constexpr auto max_part_size = 2048ull; | |
1002 | static constexpr auto max_entry_size = 128ull; | |
1003 | std::unique_ptr<RCf::FIFO> f1; | |
b3b6e05e | 1004 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f1, null_yield, std::nullopt, |
f67539c2 TL |
1005 | std::nullopt, false, max_part_size, |
1006 | max_entry_size); | |
1007 | ASSERT_EQ(0, r); | |
1008 | ||
1009 | char buf[max_entry_size]; | |
1010 | memset(buf, 0, sizeof(buf)); | |
1011 | ||
1012 | auto [part_header_size, part_entry_overhead] = f1->get_part_layout_info(); | |
1013 | const auto entries_per_part = ((max_part_size - part_header_size) / | |
1014 | (max_entry_size + part_entry_overhead)); | |
1015 | const auto max_entries = entries_per_part * 4 + 1; | |
1016 | ||
1017 | std::unique_ptr<RCf::FIFO> f2; | |
b3b6e05e | 1018 | r = RCf::FIFO::open(&dp, ioctx, fifo_id, &f2, null_yield); |
f67539c2 TL |
1019 | ASSERT_EQ(0, r); |
1020 | ||
1021 | /* push one entry to f2 and the rest to f1 */ | |
1022 | for (auto i = 0u; i < max_entries; ++i) { | |
1023 | cb::list bl; | |
1024 | *(int *)buf = i; | |
1025 | bl.append(buf, sizeof(buf)); | |
1026 | auto& f = (i < 1 ? f2 : f1); | |
1027 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 1028 | f->push(&dp, bl, c); |
f67539c2 TL |
1029 | c->wait_for_complete(); |
1030 | r = c->get_return_value(); | |
1031 | c->release(); | |
1032 | ASSERT_EQ(0, r); | |
1033 | } | |
1034 | ||
1035 | /* trim half by fifo1 */ | |
1036 | auto num = max_entries / 2; | |
1037 | std::string marker; | |
1038 | std::vector<RCf::list_entry> result; | |
1039 | bool more = false; | |
1040 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 1041 | f1->list(&dp, num, std::nullopt, &result, &more, c); |
f67539c2 TL |
1042 | c->wait_for_complete(); |
1043 | r = c->get_return_value(); | |
1044 | c->release(); | |
1045 | ASSERT_EQ(0, r); | |
1046 | ASSERT_EQ(true, more); | |
1047 | ASSERT_EQ(num, result.size()); | |
1048 | ||
1049 | for (auto i = 0u; i < num; ++i) { | |
1050 | auto& bl = result[i].data; | |
1051 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
1052 | } | |
1053 | ||
1054 | auto& entry = result[num - 1]; | |
1055 | marker = entry.marker; | |
1056 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 1057 | f1->trim(&dp, marker, false, c); |
f67539c2 TL |
1058 | c->wait_for_complete(); |
1059 | r = c->get_return_value(); | |
1060 | c->release(); | |
1061 | ASSERT_EQ(0, r); | |
1062 | /* list what's left by fifo2 */ | |
1063 | ||
1064 | const auto left = max_entries - num; | |
1065 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 1066 | f2->list(&dp, left, marker, &result, &more, c); |
f67539c2 TL |
1067 | c->wait_for_complete(); |
1068 | r = c->get_return_value(); | |
1069 | c->release(); | |
1070 | ASSERT_EQ(0, r); | |
1071 | ASSERT_EQ(left, result.size()); | |
1072 | ASSERT_EQ(false, more); | |
1073 | ||
1074 | for (auto i = num; i < max_entries; ++i) { | |
1075 | auto& bl = result[i - num].data; | |
1076 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
1077 | } | |
1078 | } | |
1079 | ||
1080 | TEST_F(AioLegacyFIFO, TestPushBatch) | |
1081 | { | |
1082 | static constexpr auto max_part_size = 2048ull; | |
1083 | static constexpr auto max_entry_size = 128ull; | |
1084 | ||
1085 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 1086 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield, std::nullopt, |
f67539c2 TL |
1087 | std::nullopt, false, max_part_size, |
1088 | max_entry_size); | |
1089 | ASSERT_EQ(0, r); | |
1090 | ||
1091 | char buf[max_entry_size]; | |
1092 | memset(buf, 0, sizeof(buf)); | |
1093 | auto [part_header_size, part_entry_overhead] = f->get_part_layout_info(); | |
1094 | auto entries_per_part = ((max_part_size - part_header_size) / | |
1095 | (max_entry_size + part_entry_overhead)); | |
1096 | auto max_entries = entries_per_part * 4 + 1; /* enough entries to span multiple parts */ | |
1097 | std::vector<cb::list> bufs; | |
1098 | for (auto i = 0u; i < max_entries; ++i) { | |
1099 | cb::list bl; | |
1100 | *(int *)buf = i; | |
1101 | bl.append(buf, sizeof(buf)); | |
1102 | bufs.push_back(bl); | |
1103 | } | |
1104 | ASSERT_EQ(max_entries, bufs.size()); | |
1105 | ||
1106 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 1107 | f->push(&dp, bufs, c); |
f67539c2 TL |
1108 | c->wait_for_complete(); |
1109 | r = c->get_return_value(); | |
1110 | c->release(); | |
1111 | ASSERT_EQ(0, r); | |
1112 | ||
1113 | /* list all */ | |
1114 | ||
1115 | std::vector<RCf::list_entry> result; | |
1116 | bool more = false; | |
1117 | c = R::Rados::aio_create_completion(); | |
b3b6e05e | 1118 | f->list(&dp, max_entries, std::nullopt, &result, &more, c); |
f67539c2 TL |
1119 | c->wait_for_complete(); |
1120 | r = c->get_return_value(); | |
1121 | c->release(); | |
1122 | ASSERT_EQ(0, r); | |
1123 | ASSERT_EQ(false, more); | |
1124 | ASSERT_EQ(max_entries, result.size()); | |
1125 | for (auto i = 0u; i < max_entries; ++i) { | |
1126 | auto& bl = result[i].data; | |
1127 | ASSERT_EQ(i, *(int *)bl.c_str()); | |
1128 | } | |
1129 | auto& info = f->meta(); | |
1130 | ASSERT_EQ(info.head_part_num, 4); | |
1131 | } | |
1132 | ||
1133 | TEST_F(LegacyFIFO, TrimAll) | |
1134 | { | |
1135 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 1136 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield); |
f67539c2 TL |
1137 | ASSERT_EQ(0, r); |
1138 | static constexpr auto max_entries = 10u; | |
1139 | for (uint32_t i = 0; i < max_entries; ++i) { | |
1140 | cb::list bl; | |
1141 | encode(i, bl); | |
b3b6e05e | 1142 | r = f->push(&dp, bl, null_yield); |
f67539c2 TL |
1143 | ASSERT_EQ(0, r); |
1144 | } | |
1145 | ||
1146 | /* trim one entry */ | |
b3b6e05e | 1147 | r = f->trim(&dp, RCf::marker::max().to_string(), false, null_yield); |
f67539c2 TL |
1148 | ASSERT_EQ(-ENODATA, r); |
1149 | ||
1150 | std::vector<RCf::list_entry> result; | |
1151 | bool more; | |
b3b6e05e | 1152 | r = f->list(&dp, 1, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
1153 | ASSERT_EQ(0, r); |
1154 | ASSERT_TRUE(result.empty()); | |
1155 | } | |
1156 | ||
1157 | TEST_F(LegacyFIFO, AioTrimAll) | |
1158 | { | |
1159 | std::unique_ptr<RCf::FIFO> f; | |
b3b6e05e | 1160 | auto r = RCf::FIFO::create(&dp, ioctx, fifo_id, &f, null_yield); |
f67539c2 TL |
1161 | ASSERT_EQ(0, r); |
1162 | static constexpr auto max_entries = 10u; | |
1163 | for (uint32_t i = 0; i < max_entries; ++i) { | |
1164 | cb::list bl; | |
1165 | encode(i, bl); | |
b3b6e05e | 1166 | r = f->push(&dp, bl, null_yield); |
f67539c2 TL |
1167 | ASSERT_EQ(0, r); |
1168 | } | |
1169 | ||
1170 | auto c = R::Rados::aio_create_completion(); | |
b3b6e05e | 1171 | f->trim(&dp, RCf::marker::max().to_string(), false, c); |
f67539c2 TL |
1172 | c->wait_for_complete(); |
1173 | r = c->get_return_value(); | |
1174 | c->release(); | |
1175 | ASSERT_EQ(-ENODATA, r); | |
1176 | ||
1177 | std::vector<RCf::list_entry> result; | |
1178 | bool more; | |
b3b6e05e | 1179 | r = f->list(&dp, 1, std::nullopt, &result, &more, null_yield); |
f67539c2 TL |
1180 | ASSERT_EQ(0, r); |
1181 | ASSERT_TRUE(result.empty()); | |
1182 | } |