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