]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/aio_cxx.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / librados / aio_cxx.cc
CommitLineData
11fdf7f2
TL
1#include <errno.h>
2#include <fcntl.h>
3#include <sstream>
4#include <string>
5#include <utility>
6#include <boost/scoped_ptr.hpp>
1e59de90 7#include <fmt/format.h>
11fdf7f2
TL
8
9#include "gtest/gtest.h"
10
11#include "common/errno.h"
12#include "include/err.h"
13#include "include/rados/librados.hpp"
14#include "include/types.h"
15#include "include/stringify.h"
16#include "include/scope_guard.h"
20effc67 17#include "common/ceph_mutex.h"
1e59de90 18#include <fmt/format.h>
11fdf7f2
TL
19
20#include "test_cxx.h"
1e59de90 21#include "crimson_utils.h"
11fdf7f2 22
20effc67 23using namespace std;
11fdf7f2 24using namespace librados;
11fdf7f2
TL
25
26class AioTestDataPP
27{
28public:
29 AioTestDataPP()
1e59de90
TL
30 : m_init(false),
31 m_oid("foo")
11fdf7f2
TL
32 {
33 }
34
35 ~AioTestDataPP()
36 {
37 if (m_init) {
38 m_ioctx.close();
39 destroy_one_pool_pp(m_pool_name, m_cluster);
40 }
41 }
42
43 std::string init()
44 {
45 return init({});
46 }
47
48 std::string init(const std::map<std::string, std::string> &config)
49 {
50 int ret;
1e59de90
TL
51 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
52 m_pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
53 std::string err = create_one_pool_pp(m_pool_name, m_cluster, config);
54 if (!err.empty()) {
55 ostringstream oss;
56 oss << "create_one_pool(" << m_pool_name << ") failed: error " << err;
57 return oss.str();
58 }
59 ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
60 if (ret) {
61 destroy_one_pool_pp(m_pool_name, m_cluster);
62 ostringstream oss;
63 oss << "rados_ioctx_create failed: error " << ret;
64 return oss.str();
65 }
1e59de90 66 m_oid = fmt::format("oid_{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
11fdf7f2
TL
67 m_init = true;
68 return "";
69 }
70
71 Rados m_cluster;
72 IoCtx m_ioctx;
73 std::string m_pool_name;
74 bool m_init;
1e59de90 75 std::string m_oid;
11fdf7f2
TL
76};
77
78TEST(LibRadosAio, TooBigPP) {
79 AioTestDataPP test_data;
80 ASSERT_EQ("", test_data.init());
81
82 bufferlist bl;
9f95a23c 83 auto aio_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90
TL
84 ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_write(test_data.m_oid, aio_completion.get(), bl, UINT_MAX, 0));
85 ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_append(test_data.m_oid, aio_completion.get(), bl, UINT_MAX));
11fdf7f2 86 // ioctx.aio_write_full no way to overflow bl.length()
11fdf7f2
TL
87}
88
89TEST(LibRadosAio, PoolQuotaPP) {
90 AioTestDataPP test_data;
91 ASSERT_EQ("", test_data.init());
1e59de90
TL
92 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
93 string p = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
94 ASSERT_EQ(0, test_data.m_cluster.pool_create(p.c_str()));
95 IoCtx ioctx;
96 ASSERT_EQ(0, test_data.m_cluster.ioctx_create(p.c_str(), ioctx));
97 ioctx.application_enable("rados", true);
98
99 bufferlist inbl;
100 ASSERT_EQ(0, test_data.m_cluster.mon_command(
101 "{\"prefix\": \"osd pool set-quota\", \"pool\": \"" + p +
102 "\", \"field\": \"max_bytes\", \"val\": \"4096\"}",
103 inbl, NULL, NULL));
104
105 bufferlist bl;
106 bufferptr z(4096);
107 bl.append(z);
108 int n;
109 for (n = 0; n < 1024; ++n) {
110 ObjectWriteOperation op;
111 op.write_full(bl);
9f95a23c 112 auto completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 113 ASSERT_EQ(0, ioctx.aio_operate(test_data.m_oid + stringify(n),
9f95a23c
TL
114 completion.get(), &op,
115 librados::OPERATION_FULL_TRY));
116 completion->wait_for_complete();
11fdf7f2 117 int r = completion->get_return_value();
11fdf7f2
TL
118 if (r == -EDQUOT)
119 break;
120 ASSERT_EQ(0, r);
121 sleep(1);
122 }
123 ASSERT_LT(n, 1024);
124
125 // make sure we have latest map that marked the pool full
126 test_data.m_cluster.wait_for_latest_osdmap();
127
128 // make sure we block without FULL_TRY
129 {
130 ObjectWriteOperation op;
131 op.write_full(bl);
9f95a23c
TL
132 auto completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
133 ASSERT_EQ(0, ioctx.aio_operate("bar", completion.get(), &op, 0));
11fdf7f2 134 sleep(5);
9f95a23c 135 ASSERT_FALSE(completion->is_complete());
11fdf7f2
TL
136 }
137
138 ioctx.close();
139 ASSERT_EQ(0, test_data.m_cluster.pool_delete(p.c_str()));
140}
141
142TEST(LibRadosAio, SimpleWritePP) {
143 char buf[128];
144 memset(buf, 0xcc, sizeof(buf));
145 bufferlist bl1;
146 bl1.append(buf, sizeof(buf));
147 {
148 AioTestDataPP test_data;
149 ASSERT_EQ("", test_data.init());
9f95a23c
TL
150 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
151 ASSERT_TRUE(my_completion);
1e59de90 152 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 153 bl1, sizeof(buf), 0));
11fdf7f2
TL
154 {
155 TestAlarm alarm;
156 ASSERT_EQ(0, my_completion->wait_for_complete());
157 }
158 ASSERT_EQ(0, my_completion->get_return_value());
11fdf7f2
TL
159 }
160
161 {
162 AioTestDataPP test_data;
163 ASSERT_EQ("", test_data.init());
164 test_data.m_ioctx.set_namespace("nspace");
9f95a23c 165 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 166 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 167 bl1, sizeof(buf), 0));
11fdf7f2
TL
168 {
169 TestAlarm alarm;
170 ASSERT_EQ(0, my_completion->wait_for_complete());
171 }
172 ASSERT_EQ(0, my_completion->get_return_value());
11fdf7f2
TL
173 }
174}
175
176TEST(LibRadosAio, WaitForSafePP) {
177 AioTestDataPP test_data;
178 ASSERT_EQ("", test_data.init());
9f95a23c
TL
179 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
180 ASSERT_TRUE(my_completion);
11fdf7f2
TL
181 char buf[128];
182 memset(buf, 0xcc, sizeof(buf));
183 bufferlist bl1;
184 bl1.append(buf, sizeof(buf));
1e59de90 185 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 186 bl1, sizeof(buf), 0));
11fdf7f2 187 TestAlarm alarm;
9f95a23c 188 ASSERT_EQ(0, my_completion->wait_for_complete());
11fdf7f2 189 ASSERT_EQ(0, my_completion->get_return_value());
11fdf7f2
TL
190}
191
192TEST(LibRadosAio, RoundTripPP) {
193 AioTestDataPP test_data;
194 ASSERT_EQ("", test_data.init());
9f95a23c
TL
195 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
196 ASSERT_TRUE(my_completion);
11fdf7f2
TL
197 char buf[128];
198 memset(buf, 0xcc, sizeof(buf));
199 bufferlist bl1;
200 bl1.append(buf, sizeof(buf));
1e59de90 201 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 202 bl1, sizeof(buf), 0));
11fdf7f2
TL
203 {
204 TestAlarm alarm;
205 ASSERT_EQ(0, my_completion->wait_for_complete());
206 }
207 ASSERT_EQ(0, my_completion->get_return_value());
208 bufferlist bl2;
9f95a23c
TL
209 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
210 ASSERT_TRUE(my_completion2);
1e59de90 211 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
9f95a23c 212 &bl2, sizeof(buf), 0));
11fdf7f2
TL
213 {
214 TestAlarm alarm;
215 ASSERT_EQ(0, my_completion2->wait_for_complete());
216 }
217 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
218 ASSERT_EQ(sizeof(buf), bl2.length());
219 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
220}
221
222TEST(LibRadosAio, RoundTripPP2) {
223 AioTestDataPP test_data;
224 ASSERT_EQ("", test_data.init());
9f95a23c
TL
225 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
226 ASSERT_TRUE(my_completion);
11fdf7f2
TL
227 char buf[128];
228 memset(buf, 0xcc, sizeof(buf));
229 bufferlist bl1;
230 bl1.append(buf, sizeof(buf));
1e59de90 231 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 232 bl1, sizeof(buf), 0));
11fdf7f2
TL
233 {
234 TestAlarm alarm;
235 ASSERT_EQ(0, my_completion->wait_for_complete());
236 }
237 ASSERT_EQ(0, my_completion->get_return_value());
238 bufferlist bl2;
9f95a23c
TL
239 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
240 ASSERT_TRUE(my_completion2);
1e59de90 241 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
9f95a23c 242 &bl2, sizeof(buf), 0));
11fdf7f2
TL
243 {
244 TestAlarm alarm;
11fdf7f2
TL
245 ASSERT_EQ(0, my_completion2->wait_for_complete());
246 }
247 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
248 ASSERT_EQ(sizeof(buf), bl2.length());
249 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
250}
251
252//using ObjectWriteOperation/ObjectReadOperation with iohint
253TEST(LibRadosAio, RoundTripPP3)
254{
255 Rados cluster;
1e59de90
TL
256 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
257 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
258 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
259 IoCtx ioctx;
260 cluster.ioctx_create(pool_name.c_str(), ioctx);
261
9f95a23c 262 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
263 ObjectWriteOperation op;
264 char buf[128];
265 memset(buf, 0xcc, sizeof(buf));
266 bufferlist bl;
267 bl.append(buf, sizeof(buf));
268
269 op.write(0, bl);
270 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
271 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
272 {
273 TestAlarm alarm;
274 ASSERT_EQ(0, my_completion1->wait_for_complete());
275 }
276 EXPECT_EQ(0, my_completion1->get_return_value());
277
9f95a23c 278 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
279 bl.clear();
280 ObjectReadOperation op1;
281 op1.read(0, sizeof(buf), &bl, NULL);
282 op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
283 bufferlist init_value_bl;
284 encode(static_cast<int32_t>(-1), init_value_bl);
285 bufferlist csum_bl;
286 op1.checksum(LIBRADOS_CHECKSUM_TYPE_CRC32C, init_value_bl,
287 0, 0, 0, &csum_bl, nullptr);
288 ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
289 {
290 TestAlarm alarm;
291 ASSERT_EQ(0, my_completion2->wait_for_complete());
292 }
293 EXPECT_EQ(0, my_completion2->get_return_value());
294 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
295
296 ASSERT_EQ(8U, csum_bl.length());
297 auto csum_bl_it = csum_bl.cbegin();
298 uint32_t csum_count;
299 uint32_t csum;
300 decode(csum_count, csum_bl_it);
301 ASSERT_EQ(1U, csum_count);
302 decode(csum, csum_bl_it);
303 ASSERT_EQ(bl.crc32c(-1), csum);
304 ioctx.remove("test_obj");
305 destroy_one_pool_pp(pool_name, cluster);
306}
307
308TEST(LibRadosAio, RoundTripSparseReadPP) {
309 AioTestDataPP test_data;
310 ASSERT_EQ("", test_data.init());
9f95a23c
TL
311 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
312 ASSERT_TRUE(my_completion);
11fdf7f2
TL
313 char buf[128];
314 memset(buf, 0xcc, sizeof(buf));
315 bufferlist bl1;
316 bl1.append(buf, sizeof(buf));
1e59de90 317 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
318 bl1, sizeof(buf), 0));
319 {
320 TestAlarm alarm;
321 ASSERT_EQ(0, my_completion->wait_for_complete());
322 }
323 ASSERT_EQ(0, my_completion->get_return_value());
324 std::map<uint64_t, uint64_t> extents;
325 bufferlist bl2;
9f95a23c
TL
326 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
327 ASSERT_TRUE(my_completion2);
1e59de90 328 ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read(test_data.m_oid, my_completion2.get(),
9f95a23c 329 &extents, &bl2, sizeof(buf), 0));
11fdf7f2
TL
330 {
331 TestAlarm alarm;
332 ASSERT_EQ(0, my_completion2->wait_for_complete());
333 }
334 ASSERT_EQ(0, my_completion2->get_return_value());
335 assert_eq_sparse(bl1, extents, bl2);
11fdf7f2
TL
336}
337
338TEST(LibRadosAioPP, ReadIntoBufferlist) {
339
340 // here we test reading into a non-empty bufferlist referencing existing
341 // buffers
342
343 AioTestDataPP test_data;
344 ASSERT_EQ("", test_data.init());
9f95a23c
TL
345 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
346 ASSERT_TRUE(my_completion);
11fdf7f2
TL
347 char buf[128];
348 memset(buf, 0xcc, sizeof(buf));
349 bufferlist bl1;
350 bl1.append(buf, sizeof(buf));
1e59de90 351 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 352 bl1, sizeof(buf), 0));
11fdf7f2
TL
353 {
354 TestAlarm alarm;
355 ASSERT_EQ(0, my_completion->wait_for_complete());
356 }
357 ASSERT_EQ(0, my_completion->get_return_value());
358
359 bufferlist bl2;
360 char buf2[sizeof(buf)];
361 memset(buf2, 0xbb, sizeof(buf2));
362 bl2.append(buffer::create_static(sizeof(buf2), buf2));
9f95a23c
TL
363 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
364 ASSERT_TRUE(my_completion2);
1e59de90 365 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
9f95a23c 366 &bl2, sizeof(buf), 0));
11fdf7f2
TL
367 {
368 TestAlarm alarm;
369 ASSERT_EQ(0, my_completion2->wait_for_complete());
370 }
371 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
372 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
11fdf7f2
TL
373}
374
375TEST(LibRadosAioPP, XattrsRoundTripPP) {
376 char buf[128];
377 char attr1[] = "attr1";
378 char attr1_buf[] = "foo bar baz";
379 memset(buf, 0xaa, sizeof(buf));
380 bufferlist bl1;
381 bl1.append(buf, sizeof(buf));
382 AioTestDataPP test_data;
383 ASSERT_EQ("", test_data.init());
1e59de90 384 ASSERT_EQ(0, test_data.m_ioctx.append(test_data.m_oid, bl1, sizeof(buf)));
11fdf7f2
TL
385 bufferlist bl2;
386 // async getxattr
9f95a23c 387 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 388 ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr(test_data.m_oid, my_completion.get(), attr1, bl2));
11fdf7f2
TL
389 {
390 TestAlarm alarm;
391 ASSERT_EQ(0, my_completion->wait_for_complete());
392 }
393 ASSERT_EQ(-ENODATA, my_completion->get_return_value());
394 // append
395 bufferlist bl3;
396 bl3.append(attr1_buf, sizeof(attr1_buf));
397 // async setxattr
398 AioTestDataPP test_data2;
399 ASSERT_EQ("", test_data2.init());
9f95a23c 400 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 401 ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr(test_data.m_oid, my_completion2.get(), attr1, bl3));
11fdf7f2
TL
402 {
403 TestAlarm alarm;
404 ASSERT_EQ(0, my_completion2->wait_for_complete());
405 }
406 ASSERT_EQ(0, my_completion2->get_return_value());
407 // async getxattr
408 bufferlist bl4;
409 AioTestDataPP test_data3;
410 ASSERT_EQ("", test_data3.init());
9f95a23c 411 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 412 ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr(test_data.m_oid, my_completion3.get(), attr1, bl4));
11fdf7f2
TL
413 {
414 TestAlarm alarm;
415 ASSERT_EQ(0, my_completion3->wait_for_complete());
416 }
417 ASSERT_EQ((int)sizeof(attr1_buf), my_completion3->get_return_value());
418 // check content of attribute
419 ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
420}
421
422TEST(LibRadosAioPP, RmXattrPP) {
423 char buf[128];
424 char attr1[] = "attr1";
425 char attr1_buf[] = "foo bar baz";
426 memset(buf, 0xaa, sizeof(buf));
427 bufferlist bl1;
428 bl1.append(buf, sizeof(buf));
429 AioTestDataPP test_data;
430 ASSERT_EQ("", test_data.init());
1e59de90 431 ASSERT_EQ(0, test_data.m_ioctx.append(test_data.m_oid, bl1, sizeof(buf)));
11fdf7f2
TL
432 // async setxattr
433 bufferlist bl2;
434 bl2.append(attr1_buf, sizeof(attr1_buf));
9f95a23c 435 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 436 ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr(test_data.m_oid, my_completion.get(), attr1, bl2));
11fdf7f2
TL
437 {
438 TestAlarm alarm;
439 ASSERT_EQ(0, my_completion->wait_for_complete());
440 }
441 ASSERT_EQ(0, my_completion->get_return_value());
442 // async rmxattr
443 AioTestDataPP test_data2;
444 ASSERT_EQ("", test_data2.init());
9f95a23c 445 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 446 ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr(test_data.m_oid, my_completion2.get(), attr1));
11fdf7f2
TL
447 {
448 TestAlarm alarm;
449 ASSERT_EQ(0, my_completion2->wait_for_complete());
450 }
451 ASSERT_EQ(0, my_completion2->get_return_value());
452 // async getxattr
453 AioTestDataPP test_data3;
454 ASSERT_EQ("", test_data3.init());
9f95a23c 455 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2 456 bufferlist bl3;
1e59de90 457 ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr(test_data.m_oid, my_completion3.get(), attr1, bl3));
11fdf7f2
TL
458 {
459 TestAlarm alarm;
460 ASSERT_EQ(0, my_completion3->wait_for_complete());
461 }
462 ASSERT_EQ(-ENODATA, my_completion3->get_return_value());
463 // Test rmxattr on a removed object
464 char buf2[128];
465 char attr2[] = "attr2";
466 char attr2_buf[] = "foo bar baz";
467 memset(buf2, 0xbb, sizeof(buf2));
468 bufferlist bl21;
469 bl21.append(buf, sizeof(buf));
470 ASSERT_EQ(0, test_data.m_ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
471 bufferlist bl22;
472 bl22.append(attr2_buf, sizeof(attr2_buf));
473 // async setxattr
474 AioTestDataPP test_data4;
475 ASSERT_EQ("", test_data4.init());
9f95a23c 476 auto my_completion4 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
477 ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo_rmxattr", my_completion4.get(), attr2, bl22));
478 {
479 TestAlarm alarm;
480 ASSERT_EQ(0, my_completion4->wait_for_complete());
481 }
482 ASSERT_EQ(0, my_completion4->get_return_value());
483 // remove object
484 ASSERT_EQ(0, test_data.m_ioctx.remove("foo_rmxattr"));
485 // async rmxattr on non existing object
486 AioTestDataPP test_data5;
487 ASSERT_EQ("", test_data5.init());
9f95a23c 488 auto my_completion5 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
489 ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr("foo_rmxattr", my_completion5.get(), attr2));
490 {
491 TestAlarm alarm;
492 ASSERT_EQ(0, my_completion5->wait_for_complete());
493 }
494 ASSERT_EQ(-ENOENT, my_completion5->get_return_value());
495}
496
497TEST(LibRadosIoPP, XattrListPP) {
498 AioTestDataPP test_data;
499 ASSERT_EQ("", test_data.init());
500 // create an object with 2 attributes
501 char buf[128];
502 char attr1[] = "attr1";
503 char attr1_buf[] = "foo bar baz";
504 char attr2[] = "attr2";
505 char attr2_buf[256];
506 for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
507 attr2_buf[j] = j % 0xff;
508 }
509 memset(buf, 0xaa, sizeof(buf));
510 bufferlist bl1;
511 bl1.append(buf, sizeof(buf));
1e59de90 512 ASSERT_EQ(0, test_data.m_ioctx.append(test_data.m_oid, bl1, sizeof(buf)));
11fdf7f2
TL
513 bufferlist bl2;
514 bl2.append(attr1_buf, sizeof(attr1_buf));
1e59de90 515 ASSERT_EQ(0, test_data.m_ioctx.setxattr(test_data.m_oid, attr1, bl2));
11fdf7f2
TL
516 bufferlist bl3;
517 bl3.append(attr2_buf, sizeof(attr2_buf));
1e59de90 518 ASSERT_EQ(0, test_data.m_ioctx.setxattr(test_data.m_oid, attr2, bl3));
11fdf7f2 519 // call async version of getxattrs
9f95a23c 520 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2 521 std::map<std::string, bufferlist> attrset;
1e59de90 522 ASSERT_EQ(0, test_data.m_ioctx.aio_getxattrs(test_data.m_oid, my_completion.get(), attrset));
11fdf7f2
TL
523 {
524 TestAlarm alarm;
525 ASSERT_EQ(0, my_completion->wait_for_complete());
526 }
527 ASSERT_EQ(0, my_completion->get_return_value());
528 for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
529 i != attrset.end(); ++i) {
530 if (i->first == string(attr1)) {
531 ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
532 }
533 else if (i->first == string(attr2)) {
534 ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
535 }
536 else {
537 ASSERT_EQ(0, 1);
538 }
539 }
540}
541
542TEST(LibRadosAio, IsCompletePP) {
543 AioTestDataPP test_data;
544 ASSERT_EQ("", test_data.init());
9f95a23c
TL
545 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
546 ASSERT_TRUE(my_completion);
11fdf7f2
TL
547 char buf[128];
548 memset(buf, 0xcc, sizeof(buf));
549 bufferlist bl1;
550 bl1.append(buf, sizeof(buf));
1e59de90 551 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
552 bl1, sizeof(buf), 0));
553 {
554 TestAlarm alarm;
555 ASSERT_EQ(0, my_completion->wait_for_complete());
556 }
557 ASSERT_EQ(0, my_completion->get_return_value());
558 bufferlist bl2;
9f95a23c
TL
559 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
560 ASSERT_TRUE(my_completion2);
1e59de90 561 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
9f95a23c 562 &bl2, sizeof(buf), 0));
11fdf7f2
TL
563 {
564 TestAlarm alarm;
565
566 // Busy-wait until the AIO completes.
567 // Normally we wouldn't do this, but we want to test is_complete.
568 while (true) {
569 int is_complete = my_completion2->is_complete();
570 if (is_complete)
571 break;
572 }
573 }
574 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
575 ASSERT_EQ(sizeof(buf), bl2.length());
576 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
577}
578
579TEST(LibRadosAio, IsSafePP) {
580 AioTestDataPP test_data;
581 ASSERT_EQ("", test_data.init());
9f95a23c
TL
582 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
583 ASSERT_TRUE(my_completion);
11fdf7f2
TL
584 char buf[128];
585 memset(buf, 0xcc, sizeof(buf));
586 bufferlist bl1;
587 bl1.append(buf, sizeof(buf));
1e59de90 588 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
589 bl1, sizeof(buf), 0));
590 {
591 TestAlarm alarm;
592
593 // Busy-wait until the AIO completes.
594 // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
595 while (true) {
9f95a23c
TL
596 int is_complete = my_completion->is_complete();
597 if (is_complete)
11fdf7f2
TL
598 break;
599 }
600 }
601 ASSERT_EQ(0, my_completion->get_return_value());
9f95a23c 602 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2 603 bufferlist bl2;
9f95a23c 604 ASSERT_TRUE(my_completion2);
1e59de90 605 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
606 &bl2, sizeof(buf), 0));
607 {
608 TestAlarm alarm;
609 ASSERT_EQ(0, my_completion2->wait_for_complete());
610 }
611 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
612 ASSERT_EQ(sizeof(buf), bl2.length());
613 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
614}
615
616TEST(LibRadosAio, ReturnValuePP) {
617 AioTestDataPP test_data;
618 ASSERT_EQ("", test_data.init());
9f95a23c
TL
619 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
620 ASSERT_TRUE(my_completion);
11fdf7f2 621 bufferlist bl1;
9f95a23c
TL
622 ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent", my_completion.get(),
623 &bl1, 128, 0));
11fdf7f2
TL
624 {
625 TestAlarm alarm;
626 ASSERT_EQ(0, my_completion->wait_for_complete());
627 }
628 ASSERT_EQ(-ENOENT, my_completion->get_return_value());
11fdf7f2
TL
629}
630
631TEST(LibRadosAio, FlushPP) {
632 AioTestDataPP test_data;
633 ASSERT_EQ("", test_data.init());
9f95a23c
TL
634 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
635 ASSERT_TRUE(my_completion);
11fdf7f2
TL
636 char buf[128];
637 memset(buf, 0xee, sizeof(buf));
638 bufferlist bl1;
639 bl1.append(buf, sizeof(buf));
1e59de90 640 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
641 bl1, sizeof(buf), 0));
642 ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
643 ASSERT_EQ(0, my_completion->get_return_value());
644 bufferlist bl2;
9f95a23c
TL
645 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
646 ASSERT_TRUE(my_completion2);
1e59de90 647 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
648 &bl2, sizeof(buf), 0));
649 {
650 TestAlarm alarm;
651 ASSERT_EQ(0, my_completion2->wait_for_complete());
652 }
653 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
654 ASSERT_EQ(sizeof(buf), bl2.length());
655 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
656}
657
658TEST(LibRadosAio, FlushAsyncPP) {
659 AioTestDataPP test_data;
660 ASSERT_EQ("", test_data.init());
9f95a23c
TL
661 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
662 auto flush_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
663 ASSERT_TRUE(my_completion);
11fdf7f2
TL
664 char buf[128];
665 memset(buf, 0xee, sizeof(buf));
666 bufferlist bl1;
667 bl1.append(buf, sizeof(buf));
1e59de90 668 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2 669 bl1, sizeof(buf), 0));
9f95a23c 670 ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion.get()));
11fdf7f2
TL
671 {
672 TestAlarm alarm;
673 ASSERT_EQ(0, flush_completion->wait_for_complete());
11fdf7f2
TL
674 }
675 ASSERT_EQ(1, my_completion->is_complete());
11fdf7f2 676 ASSERT_EQ(1, flush_completion->is_complete());
11fdf7f2
TL
677 ASSERT_EQ(0, my_completion->get_return_value());
678 bufferlist bl2;
9f95a23c
TL
679 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
680 ASSERT_TRUE(my_completion2);
1e59de90 681 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
682 &bl2, sizeof(buf), 0));
683 {
684 TestAlarm alarm;
685 ASSERT_EQ(0, my_completion2->wait_for_complete());
686 }
687 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
688 ASSERT_EQ(sizeof(buf), bl2.length());
689 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
690}
691
692TEST(LibRadosAio, RoundTripWriteFullPP) {
693 AioTestDataPP test_data;
694 ASSERT_EQ("", test_data.init());
9f95a23c
TL
695 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
696 ASSERT_TRUE(my_completion);
11fdf7f2
TL
697 char buf[128];
698 memset(buf, 0xcc, sizeof(buf));
699 bufferlist bl1;
700 bl1.append(buf, sizeof(buf));
1e59de90 701 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
702 bl1, sizeof(buf), 0));
703 {
704 TestAlarm alarm;
705 ASSERT_EQ(0, my_completion->wait_for_complete());
706 }
707 ASSERT_EQ(0, my_completion->get_return_value());
708 char buf2[64];
709 memset(buf2, 0xdd, sizeof(buf2));
710 bufferlist bl2;
711 bl2.append(buf2, sizeof(buf2));
9f95a23c
TL
712 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
713 ASSERT_TRUE(my_completion2);
1e59de90 714 ASSERT_EQ(0, test_data.m_ioctx.aio_write_full(test_data.m_oid, my_completion2.get(), bl2));
11fdf7f2
TL
715 {
716 TestAlarm alarm;
717 ASSERT_EQ(0, my_completion2->wait_for_complete());
718 }
719 ASSERT_EQ(0, my_completion2->get_return_value());
720 bufferlist bl3;
9f95a23c
TL
721 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
722 ASSERT_TRUE(my_completion3);
1e59de90 723 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion3.get(),
11fdf7f2
TL
724 &bl3, sizeof(buf), 0));
725 {
726 TestAlarm alarm;
727 ASSERT_EQ(0, my_completion3->wait_for_complete());
728 }
729 ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
730 ASSERT_EQ(sizeof(buf2), bl3.length());
731 ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
11fdf7f2
TL
732}
733
734//using ObjectWriteOperation/ObjectReadOperation with iohint
735TEST(LibRadosAio, RoundTripWriteFullPP2)
736{
737 Rados cluster;
1e59de90
TL
738 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
739 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
740 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
741 IoCtx ioctx;
742 cluster.ioctx_create(pool_name.c_str(), ioctx);
743
9f95a23c 744 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
745 ObjectWriteOperation op;
746 char buf[128];
747 memset(buf, 0xcc, sizeof(buf));
748 bufferlist bl;
749 bl.append(buf);
750
751 op.write_full(bl);
752 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
753 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
754 {
755 TestAlarm alarm;
756 ASSERT_EQ(0, my_completion1->wait_for_complete());
757 }
758 EXPECT_EQ(0, my_completion1->get_return_value());
759
9f95a23c 760 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
761 bl.clear();
762 ObjectReadOperation op1;
763 op1.read(0, sizeof(buf), &bl, NULL);
764 op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
765 ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
766 {
767 TestAlarm alarm;
768 ASSERT_EQ(0, my_completion2->wait_for_complete());
769 }
770 EXPECT_EQ(0, my_completion2->get_return_value());
771 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
772
773 ioctx.remove("test_obj");
774 destroy_one_pool_pp(pool_name, cluster);
775}
776
777TEST(LibRadosAio, RoundTripWriteSamePP) {
778 AioTestDataPP test_data;
779 ASSERT_EQ("", test_data.init());
9f95a23c
TL
780 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
781 ASSERT_TRUE(my_completion);
11fdf7f2
TL
782 char full[128];
783 memset(full, 0xcc, sizeof(full));
784 bufferlist bl1;
785 bl1.append(full, sizeof(full));
1e59de90 786 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
787 bl1, sizeof(full), 0));
788 {
789 TestAlarm alarm;
790 ASSERT_EQ(0, my_completion->wait_for_complete());
791 }
792 ASSERT_EQ(0, my_completion->get_return_value());
793 /* write the same buf four times */
794 char buf[32];
795 size_t ws_write_len = sizeof(full);
796 memset(buf, 0xdd, sizeof(buf));
797 bufferlist bl2;
798 bl2.append(buf, sizeof(buf));
9f95a23c
TL
799 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
800 ASSERT_TRUE(my_completion2);
1e59de90 801 ASSERT_EQ(0, test_data.m_ioctx.aio_writesame(test_data.m_oid, my_completion2.get(), bl2,
11fdf7f2
TL
802 ws_write_len, 0));
803 {
804 TestAlarm alarm;
805 ASSERT_EQ(0, my_completion2->wait_for_complete());
806 }
807 ASSERT_EQ(0, my_completion2->get_return_value());
808 bufferlist bl3;
9f95a23c
TL
809 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
810 ASSERT_TRUE(my_completion3);
1e59de90 811 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion3.get(),
11fdf7f2
TL
812 &bl3, sizeof(full), 0));
813 {
814 TestAlarm alarm;
815 ASSERT_EQ(0, my_completion3->wait_for_complete());
816 }
817 ASSERT_EQ((int)sizeof(full), my_completion3->get_return_value());
818 ASSERT_EQ(sizeof(full), bl3.length());
819 for (char *cmp = bl3.c_str(); cmp < bl3.c_str() + bl3.length();
820 cmp += sizeof(buf)) {
821 ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
822 }
11fdf7f2
TL
823}
824
825TEST(LibRadosAio, RoundTripWriteSamePP2)
826{
827 Rados cluster;
1e59de90
TL
828 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
829 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
830 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
831 IoCtx ioctx;
832 cluster.ioctx_create(pool_name.c_str(), ioctx);
833
9f95a23c 834 auto wr_cmpl = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
835 ObjectWriteOperation op;
836 char buf[128];
837 memset(buf, 0xcc, sizeof(buf));
838 bufferlist bl;
839 bl.append(buf, sizeof(buf));
840
841 op.writesame(0, sizeof(buf) * 4, bl);
842 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
843 ioctx.aio_operate("test_obj", wr_cmpl.get(), &op);
844 {
845 TestAlarm alarm;
846 ASSERT_EQ(0, wr_cmpl->wait_for_complete());
847 }
848 EXPECT_EQ(0, wr_cmpl->get_return_value());
849
850 boost::scoped_ptr<AioCompletion>
9f95a23c 851 rd_cmpl(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
852 char *cmp;
853 char full[sizeof(buf) * 4];
854 memset(full, 0, sizeof(full));
855 bufferlist fl;
856 fl.append(full, sizeof(full));
857 ObjectReadOperation op1;
858 op1.read(0, sizeof(full), &fl, NULL);
859 op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
860 ioctx.aio_operate("test_obj", rd_cmpl.get(), &op1, 0);
861 {
862 TestAlarm alarm;
863 ASSERT_EQ(0, rd_cmpl->wait_for_complete());
864 }
865 EXPECT_EQ(0, rd_cmpl->get_return_value());
866 for (cmp = fl.c_str(); cmp < fl.c_str() + fl.length(); cmp += sizeof(buf)) {
867 ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
868 }
869
870 ioctx.remove("test_obj");
871 destroy_one_pool_pp(pool_name, cluster);
872}
873
874TEST(LibRadosAio, SimpleStatPPNS) {
875 AioTestDataPP test_data;
876 ASSERT_EQ("", test_data.init());
9f95a23c
TL
877 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
878 ASSERT_TRUE(my_completion);
11fdf7f2
TL
879 char buf[128];
880 memset(buf, 0xcc, sizeof(buf));
881 bufferlist bl1;
882 bl1.append(buf, sizeof(buf));
1e59de90 883 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
884 bl1, sizeof(buf), 0));
885 {
886 TestAlarm alarm;
887 ASSERT_EQ(0, my_completion->wait_for_complete());
888 }
889 ASSERT_EQ(0, my_completion->get_return_value());
890 uint64_t psize;
891 time_t pmtime;
9f95a23c
TL
892 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
893 ASSERT_TRUE(my_completion2);
1e59de90 894 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
895 &psize, &pmtime));
896 {
897 TestAlarm alarm;
898 ASSERT_EQ(0, my_completion2->wait_for_complete());
899 }
900 ASSERT_EQ(0, my_completion2->get_return_value());
901 ASSERT_EQ(sizeof(buf), psize);
11fdf7f2
TL
902}
903
904TEST(LibRadosAio, SimpleStatPP) {
905 AioTestDataPP test_data;
906 ASSERT_EQ("", test_data.init());
9f95a23c
TL
907 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
908 ASSERT_TRUE(my_completion);
11fdf7f2
TL
909 char buf[128];
910 memset(buf, 0xcc, sizeof(buf));
911 bufferlist bl1;
912 bl1.append(buf, sizeof(buf));
1e59de90 913 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
914 bl1, sizeof(buf), 0));
915 {
916 TestAlarm alarm;
917 ASSERT_EQ(0, my_completion->wait_for_complete());
918 }
919 ASSERT_EQ(0, my_completion->get_return_value());
920 uint64_t psize;
921 time_t pmtime;
9f95a23c
TL
922 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
923 ASSERT_TRUE(my_completion2);
1e59de90 924 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
925 &psize, &pmtime));
926 {
927 TestAlarm alarm;
928 ASSERT_EQ(0, my_completion2->wait_for_complete());
929 }
930 ASSERT_EQ(0, my_completion2->get_return_value());
931 ASSERT_EQ(sizeof(buf), psize);
11fdf7f2
TL
932}
933
1e59de90
TL
934TEST(LibRadosAio, OperateMtime)
935{
936 AioTestDataPP test_data;
937 ASSERT_EQ("", test_data.init());
938
939 time_t set_mtime = 1457129052;
940 {
941 auto c = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
942 librados::ObjectWriteOperation op;
943 op.mtime(&set_mtime);
944 op.create(false);
945 ASSERT_EQ(0, test_data.m_ioctx.aio_operate(test_data.m_oid, c.get(), &op));
946 {
947 TestAlarm alarm;
948 ASSERT_EQ(0, c->wait_for_complete());
949 }
950 ASSERT_EQ(0, c->get_return_value());
951 }
952 {
953 uint64_t size;
954 timespec mtime;
955 ASSERT_EQ(0, test_data.m_ioctx.stat2(test_data.m_oid, &size, &mtime));
956 EXPECT_EQ(0, size);
957 EXPECT_EQ(set_mtime, mtime.tv_sec);
958 EXPECT_EQ(0, mtime.tv_nsec);
959 }
960}
961
962TEST(LibRadosAio, OperateMtime2)
963{
964 AioTestDataPP test_data;
965 ASSERT_EQ("", test_data.init());
966
967 timespec set_mtime{1457129052, 123456789};
968 {
969 auto c = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
970 librados::ObjectWriteOperation op;
971 op.mtime2(&set_mtime);
972 op.create(false);
973 ASSERT_EQ(0, test_data.m_ioctx.aio_operate(test_data.m_oid, c.get(), &op));
974 {
975 TestAlarm alarm;
976 ASSERT_EQ(0, c->wait_for_complete());
977 }
978 ASSERT_EQ(0, c->get_return_value());
979 }
980 {
981 uint64_t size;
982 timespec mtime;
983 ASSERT_EQ(0, test_data.m_ioctx.stat2(test_data.m_oid, &size, &mtime));
984 EXPECT_EQ(0, size);
985 EXPECT_EQ(set_mtime.tv_sec, mtime.tv_sec);
986 EXPECT_EQ(set_mtime.tv_nsec, mtime.tv_nsec);
987 }
988}
989
11fdf7f2
TL
990TEST(LibRadosAio, StatRemovePP) {
991 AioTestDataPP test_data;
992 ASSERT_EQ("", test_data.init());
9f95a23c
TL
993 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
994 ASSERT_TRUE(my_completion);
11fdf7f2
TL
995 char buf[128];
996 memset(buf, 0xcc, sizeof(buf));
997 bufferlist bl1;
998 bl1.append(buf, sizeof(buf));
1e59de90 999 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1000 bl1, sizeof(buf), 0));
1001 {
1002 TestAlarm alarm;
1003 ASSERT_EQ(0, my_completion->wait_for_complete());
1004 }
1005 ASSERT_EQ(0, my_completion->get_return_value());
1006 uint64_t psize;
1007 time_t pmtime;
9f95a23c
TL
1008 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1009 ASSERT_TRUE(my_completion2);
1e59de90 1010 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1011 &psize, &pmtime));
1012 {
1013 TestAlarm alarm;
1014 ASSERT_EQ(0, my_completion2->wait_for_complete());
1015 }
1016 ASSERT_EQ(0, my_completion2->get_return_value());
1017 ASSERT_EQ(sizeof(buf), psize);
1018 uint64_t psize2;
1019 time_t pmtime2;
9f95a23c
TL
1020 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1021 ASSERT_TRUE(my_completion3);
1e59de90 1022 ASSERT_EQ(0, test_data.m_ioctx.aio_remove(test_data.m_oid, my_completion3.get()));
11fdf7f2
TL
1023 {
1024 TestAlarm alarm;
1025 ASSERT_EQ(0, my_completion3->wait_for_complete());
1026 }
1027 ASSERT_EQ(0, my_completion3->get_return_value());
1028
9f95a23c
TL
1029 auto my_completion4 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1030 ASSERT_TRUE(my_completion4);
1e59de90 1031 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion4.get(),
11fdf7f2
TL
1032 &psize2, &pmtime2));
1033 {
1034 TestAlarm alarm;
1035 ASSERT_EQ(0, my_completion4->wait_for_complete());
1036 }
1037 ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
11fdf7f2
TL
1038}
1039
1040TEST(LibRadosAio, ExecuteClassPP) {
1041 AioTestDataPP test_data;
1042 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1043 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1044 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1045 char buf[128];
1046 memset(buf, 0xcc, sizeof(buf));
1047 bufferlist bl1;
1048 bl1.append(buf, sizeof(buf));
1e59de90 1049 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1050 bl1, sizeof(buf), 0));
1051 {
1052 TestAlarm alarm;
1053 ASSERT_EQ(0, my_completion->wait_for_complete());
1054 }
1055 ASSERT_EQ(0, my_completion->get_return_value());
9f95a23c
TL
1056 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1057 ASSERT_TRUE(my_completion2);
11fdf7f2 1058 bufferlist in, out;
1e59de90 1059 ASSERT_EQ(0, test_data.m_ioctx.aio_exec(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1060 "hello", "say_hello", in, &out));
1061 {
1062 TestAlarm alarm;
1063 ASSERT_EQ(0, my_completion2->wait_for_complete());
1064 }
1065 ASSERT_EQ(0, my_completion2->get_return_value());
1066 ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
11fdf7f2
TL
1067}
1068
1069using std::string;
1070using std::map;
1071using std::set;
1072
1073TEST(LibRadosAio, OmapPP) {
1074 Rados cluster;
1e59de90
TL
1075 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
1076 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
1077 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1078 IoCtx ioctx;
1079 cluster.ioctx_create(pool_name.c_str(), ioctx);
1080
1081 string header_str = "baz";
1082 bufferptr bp(header_str.c_str(), header_str.size() + 1);
1083 bufferlist header_to_set;
1084 header_to_set.push_back(bp);
1085 map<string, bufferlist> to_set;
1086 {
9f95a23c 1087 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1088 ObjectWriteOperation op;
1089 to_set["foo"] = header_to_set;
1090 to_set["foo2"] = header_to_set;
1091 to_set["qfoo3"] = header_to_set;
1092 op.omap_set(to_set);
1093
1094 op.omap_set_header(header_to_set);
1095
1096 ioctx.aio_operate("test_obj", my_completion.get(), &op);
1097 {
1098 TestAlarm alarm;
1099 ASSERT_EQ(0, my_completion->wait_for_complete());
1100 }
1101 EXPECT_EQ(0, my_completion->get_return_value());
1102 }
1103
1104 {
9f95a23c 1105 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1106 ObjectReadOperation op;
1107 map<string, pair<bufferlist, int> > assertions;
1108 bufferlist val;
1109 val.append(string("bar"));
1110 assertions["foo"] = pair<bufferlist, int>(val, CEPH_OSD_CMPXATTR_OP_EQ);
1111
1112 int r;
1113 op.omap_cmp(assertions, &r);
1114
1115 ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
1116 {
1117 TestAlarm alarm;
1118 ASSERT_EQ(0, my_completion->wait_for_complete());
1119 }
1120 EXPECT_EQ(-ECANCELED, my_completion->get_return_value());
1121 ASSERT_EQ(-ECANCELED, r);
1122 }
1123
1124 {
9f95a23c 1125 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1126 ObjectReadOperation op;
1127
1128 set<string> set_got;
1129 map<string, bufferlist> map_got;
1130
1131 set<string> to_get;
1132 map<string, bufferlist> got3;
1133
1134 map<string, bufferlist> got4;
1135
1136 bufferlist header;
1137
1138 op.omap_get_keys2("", 1, &set_got, nullptr, 0);
1139 op.omap_get_vals2("foo", 1, &map_got, nullptr, 0);
1140
1141 to_get.insert("foo");
1142 to_get.insert("qfoo3");
1143 op.omap_get_vals_by_keys(to_get, &got3, 0);
1144
1145 op.omap_get_header(&header, 0);
1146
1147 op.omap_get_vals2("foo2", "q", 1, &got4, nullptr, 0);
1148
1149 ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
1150 {
1151 TestAlarm alarm;
1152 ASSERT_EQ(0, my_completion->wait_for_complete());
1153 }
1154 EXPECT_EQ(0, my_completion->get_return_value());
1155
1156 ASSERT_EQ(header.length(), header_to_set.length());
1157 ASSERT_EQ(set_got.size(), (unsigned)1);
1158 ASSERT_EQ(*set_got.begin(), "foo");
1159 ASSERT_EQ(map_got.size(), (unsigned)1);
1160 ASSERT_EQ(map_got.begin()->first, "foo2");
1161 ASSERT_EQ(got3.size(), (unsigned)2);
1162 ASSERT_EQ(got3.begin()->first, "foo");
1163 ASSERT_EQ(got3.rbegin()->first, "qfoo3");
1164 ASSERT_EQ(got4.size(), (unsigned)1);
1165 ASSERT_EQ(got4.begin()->first, "qfoo3");
1166 }
1167
1168 {
9f95a23c 1169 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1170 ObjectWriteOperation op;
1171 set<string> to_remove;
1172 to_remove.insert("foo2");
1173 op.omap_rm_keys(to_remove);
1174 ioctx.aio_operate("test_obj", my_completion.get(), &op);
1175 {
1176 TestAlarm alarm;
1177 ASSERT_EQ(0, my_completion->wait_for_complete());
1178 }
1179 EXPECT_EQ(0, my_completion->get_return_value());
1180 }
1181
1182 {
9f95a23c 1183 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1184 ObjectReadOperation op;
1185
1186 set<string> set_got;
1187 op.omap_get_keys2("", -1, &set_got, nullptr, 0);
1188 ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
1189 {
1190 TestAlarm alarm;
1191 ASSERT_EQ(0, my_completion->wait_for_complete());
1192 }
1193 EXPECT_EQ(0, my_completion->get_return_value());
1194 ASSERT_EQ(set_got.size(), (unsigned)2);
1195 }
1196
1197 {
9f95a23c 1198 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1199 ObjectWriteOperation op;
1200 op.omap_clear();
1201 ioctx.aio_operate("test_obj", my_completion.get(), &op);
1202 {
1203 TestAlarm alarm;
1204 ASSERT_EQ(0, my_completion->wait_for_complete());
1205 }
1206 EXPECT_EQ(0, my_completion->get_return_value());
1207 }
1208
1209 {
9f95a23c 1210 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1211 ObjectReadOperation op;
1212
1213 set<string> set_got;
1214 op.omap_get_keys2("", -1, &set_got, nullptr, 0);
1215 ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
1216 {
1217 TestAlarm alarm;
1218 ASSERT_EQ(0, my_completion->wait_for_complete());
1219 }
1220 EXPECT_EQ(0, my_completion->get_return_value());
1221 ASSERT_EQ(set_got.size(), (unsigned)0);
1222 }
1223
1224 // omap_clear clears header *and* keys
1225 {
9f95a23c 1226 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1227 ObjectWriteOperation op;
1228 bufferlist bl;
1229 bl.append("some data");
1230 map<string,bufferlist> to_set;
1231 to_set["foo"] = bl;
1232 to_set["foo2"] = bl;
1233 to_set["qfoo3"] = bl;
1234 op.omap_set(to_set);
1235 op.omap_set_header(bl);
1236 ioctx.aio_operate("foo3", my_completion.get(), &op);
1237 {
1238 TestAlarm alarm;
1239 ASSERT_EQ(0, my_completion->wait_for_complete());
1240 }
1241 EXPECT_EQ(0, my_completion->get_return_value());
1242 }
1243 {
9f95a23c 1244 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1245 ObjectWriteOperation op;
1246 op.omap_clear();
1247 ioctx.aio_operate("foo3", my_completion.get(), &op);
1248 {
1249 TestAlarm alarm;
1250 ASSERT_EQ(0, my_completion->wait_for_complete());
1251 }
1252 EXPECT_EQ(0, my_completion->get_return_value());
1253 }
1254 {
9f95a23c 1255 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
11fdf7f2
TL
1256 ObjectReadOperation op;
1257 set<string> set_got;
1258 bufferlist hdr;
1259 op.omap_get_keys2("", -1, &set_got, nullptr, 0);
1260 op.omap_get_header(&hdr, NULL);
1261 ioctx.aio_operate("foo3", my_completion.get(), &op, 0);
1262 {
1263 TestAlarm alarm;
1264 ASSERT_EQ(0, my_completion->wait_for_complete());
1265 }
1266 EXPECT_EQ(0, my_completion->get_return_value());
1267 ASSERT_EQ(set_got.size(), (unsigned)0);
1268 ASSERT_EQ(hdr.length(), 0u);
1269 }
1270
1271 ioctx.remove("test_obj");
1272 destroy_one_pool_pp(pool_name, cluster);
1273}
1274
1275TEST(LibRadosAio, MultiWritePP) {
1276 AioTestDataPP test_data;
1277 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1278 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1279 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1280 char buf[128];
1281 memset(buf, 0xcc, sizeof(buf));
1282 bufferlist bl1;
1283 bl1.append(buf, sizeof(buf));
1e59de90 1284 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1285 bl1, sizeof(buf), 0));
1286 {
1287 TestAlarm alarm;
1288 ASSERT_EQ(0, my_completion->wait_for_complete());
1289 }
1290 ASSERT_EQ(0, my_completion->get_return_value());
1291
1292 char buf2[64];
1293 memset(buf2, 0xdd, sizeof(buf2));
1294 bufferlist bl2;
1295 bl2.append(buf2, sizeof(buf2));
9f95a23c
TL
1296 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1297 ASSERT_TRUE(my_completion2);
1e59de90 1298 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1299 bl2, sizeof(buf2), sizeof(buf)));
1300 {
1301 TestAlarm alarm;
1302 ASSERT_EQ(0, my_completion2->wait_for_complete());
1303 }
1304 ASSERT_EQ(0, my_completion2->get_return_value());
1305
1306 bufferlist bl3;
9f95a23c
TL
1307 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1308 ASSERT_TRUE(my_completion3);
1e59de90 1309 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion3.get(),
11fdf7f2
TL
1310 &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
1311 {
1312 TestAlarm alarm;
1313 ASSERT_EQ(0, my_completion3->wait_for_complete());
1314 }
1315 ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)), my_completion3->get_return_value());
1316 ASSERT_EQ(sizeof(buf) + sizeof(buf2), bl3.length());
1317 ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
1318 ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
11fdf7f2
TL
1319}
1320
1321TEST(LibRadosAio, AioUnlockPP) {
1322 AioTestDataPP test_data;
1323 ASSERT_EQ("", test_data.init());
1e59de90 1324 ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive(test_data.m_oid, "TestLock", "Cookie", "", NULL, 0));
9f95a23c 1325 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 1326 ASSERT_EQ(0, test_data.m_ioctx.aio_unlock(test_data.m_oid, "TestLock", "Cookie", my_completion.get()));
11fdf7f2
TL
1327 {
1328 TestAlarm alarm;
1329 ASSERT_EQ(0, my_completion->wait_for_complete());
1330 }
1331 ASSERT_EQ(0, my_completion->get_return_value());
1332 bufferlist bl2;
1e59de90 1333 ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive(test_data.m_oid, "TestLock", "Cookie", "", NULL, 0));
11fdf7f2
TL
1334}
1335
1336class AioTestDataECPP
1337{
1338public:
1339 AioTestDataECPP()
1e59de90
TL
1340 : m_init(false),
1341 m_oid("foo")
11fdf7f2
TL
1342 {}
1343
1344 ~AioTestDataECPP()
1345 {
1346 if (m_init) {
1347 m_ioctx.close();
1348 destroy_one_ec_pool_pp(m_pool_name, m_cluster);
1349 }
1350 }
1351
1352 std::string init()
1353 {
1354 int ret;
1e59de90
TL
1355 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
1356 m_pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
1357 std::string err = create_one_ec_pool_pp(m_pool_name, m_cluster);
1358 if (!err.empty()) {
1359 ostringstream oss;
1360 oss << "create_one_ec_pool(" << m_pool_name << ") failed: error " << err;
1361 return oss.str();
1362 }
1363 ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
1364 if (ret) {
1365 destroy_one_ec_pool_pp(m_pool_name, m_cluster);
1366 ostringstream oss;
1367 oss << "rados_ioctx_create failed: error " << ret;
1368 return oss.str();
1369 }
1e59de90 1370 m_oid = fmt::format("oid_{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
11fdf7f2
TL
1371 m_init = true;
1372 return "";
1373 }
1374
1375 Rados m_cluster;
1376 IoCtx m_ioctx;
1377 std::string m_pool_name;
1378 bool m_init;
1e59de90 1379 std::string m_oid;
11fdf7f2
TL
1380};
1381
1382// EC test cases
1383TEST(LibRadosAioEC, SimpleWritePP) {
1e59de90 1384 SKIP_IF_CRIMSON();
11fdf7f2
TL
1385 char buf[128];
1386 memset(buf, 0xcc, sizeof(buf));
1387 bufferlist bl1;
1388 bl1.append(buf, sizeof(buf));
1389 {
1390 AioTestDataECPP test_data;
1391 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1392 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1393 ASSERT_TRUE(my_completion);
1e59de90 1394 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 1395 bl1, sizeof(buf), 0));
11fdf7f2
TL
1396 {
1397 TestAlarm alarm;
1398 ASSERT_EQ(0, my_completion->wait_for_complete());
1399 }
1400 ASSERT_EQ(0, my_completion->get_return_value());
11fdf7f2
TL
1401 }
1402
1403 {
1404 AioTestDataECPP test_data;
1405 ASSERT_EQ("", test_data.init());
1406 test_data.m_ioctx.set_namespace("nspace");
9f95a23c 1407 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 1408 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 1409 bl1, sizeof(buf), 0));
11fdf7f2
TL
1410 {
1411 TestAlarm alarm;
1412 ASSERT_EQ(0, my_completion->wait_for_complete());
1413 }
1414 ASSERT_EQ(0, my_completion->get_return_value());
11fdf7f2
TL
1415 }
1416}
1417
1418TEST(LibRadosAioEC, WaitForSafePP) {
1e59de90 1419 SKIP_IF_CRIMSON();
11fdf7f2
TL
1420 AioTestDataECPP test_data;
1421 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1422 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1423 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1424 char buf[128];
1425 memset(buf, 0xcc, sizeof(buf));
1426 bufferlist bl1;
1427 bl1.append(buf, sizeof(buf));
1e59de90 1428 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
9f95a23c 1429 bl1, sizeof(buf), 0));
11fdf7f2 1430 TestAlarm alarm;
9f95a23c 1431 ASSERT_EQ(0, my_completion->wait_for_complete());
11fdf7f2 1432 ASSERT_EQ(0, my_completion->get_return_value());
11fdf7f2
TL
1433}
1434
1435TEST(LibRadosAioEC, RoundTripPP) {
1e59de90 1436 SKIP_IF_CRIMSON();
11fdf7f2
TL
1437 AioTestDataECPP test_data;
1438 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1439 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1440 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1441 char buf[128];
1442 memset(buf, 0xcc, sizeof(buf));
1443 bufferlist bl1;
1444 bl1.append(buf, sizeof(buf));
1e59de90 1445 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1446 bl1, sizeof(buf), 0));
1447 {
1448 TestAlarm alarm;
1449 ASSERT_EQ(0, my_completion->wait_for_complete());
1450 }
1451 ASSERT_EQ(0, my_completion->get_return_value());
1452 bufferlist bl2;
9f95a23c
TL
1453 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1454 ASSERT_TRUE(my_completion2);
1e59de90 1455 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
9f95a23c 1456 &bl2, sizeof(buf), 0));
11fdf7f2
TL
1457 {
1458 TestAlarm alarm;
1459 ASSERT_EQ(0, my_completion2->wait_for_complete());
1460 }
1461 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1462 ASSERT_EQ(sizeof(buf), bl2.length());
1463 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
1464}
1465
1466TEST(LibRadosAioEC, RoundTripPP2) {
1e59de90 1467 SKIP_IF_CRIMSON();
11fdf7f2
TL
1468 AioTestDataECPP test_data;
1469 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1470 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1471 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1472 char buf[128];
1473 memset(buf, 0xcc, sizeof(buf));
1474 bufferlist bl1;
1475 bl1.append(buf, sizeof(buf));
1e59de90 1476 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1477 bl1, sizeof(buf), 0));
1478 {
1479 TestAlarm alarm;
1480 ASSERT_EQ(0, my_completion->wait_for_complete());
1481 }
1482 ASSERT_EQ(0, my_completion->get_return_value());
1483 bufferlist bl2;
9f95a23c
TL
1484 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1485 ASSERT_TRUE(my_completion2);
1e59de90 1486 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
9f95a23c 1487 &bl2, sizeof(buf), 0));
11fdf7f2
TL
1488 {
1489 TestAlarm alarm;
11fdf7f2
TL
1490 ASSERT_EQ(0, my_completion2->wait_for_complete());
1491 }
1492 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1493 ASSERT_EQ(sizeof(buf), bl2.length());
1494 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
1495}
1496
1497//using ObjectWriteOperation/ObjectReadOperation with iohint
1498TEST(LibRadosAioEC, RoundTripPP3)
1499{
1e59de90 1500 SKIP_IF_CRIMSON();
11fdf7f2 1501 Rados cluster;
1e59de90
TL
1502 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
1503 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
1504 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1505 IoCtx ioctx;
1506 cluster.ioctx_create(pool_name.c_str(), ioctx);
1507
9f95a23c 1508 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};;
11fdf7f2
TL
1509 ObjectWriteOperation op;
1510 char buf[128];
1511 memset(buf, 0xcc, sizeof(buf));
1512 bufferlist bl;
1513 bl.append(buf);
1514
1515 op.write(0, bl);
1516 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
1517 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
1518 {
1519 TestAlarm alarm;
1520 ASSERT_EQ(0, my_completion1->wait_for_complete());
1521 }
1522 EXPECT_EQ(0, my_completion1->get_return_value());
1523
9f95a23c 1524 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
1525 bl.clear();
1526 ObjectReadOperation op1;
1527 op1.read(0, sizeof(buf), &bl, NULL);
1528 op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
1529 ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
1530 {
1531 TestAlarm alarm;
1532 ASSERT_EQ(0, my_completion2->wait_for_complete());
1533 }
1534 EXPECT_EQ(0, my_completion2->get_return_value());
1535 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
1536
1537 ioctx.remove("test_obj");
1538 destroy_one_pool_pp(pool_name, cluster);
1539}
1540
1541TEST(LibRadosAio, RoundTripAppendPP) {
1542 AioTestDataPP test_data;
1543 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1544 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1545 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1546 char buf[128];
1547 memset(buf, 0xcc, sizeof(buf));
1548 bufferlist bl1;
1549 bl1.append(buf, sizeof(buf));
1e59de90 1550 ASSERT_EQ(0, test_data.m_ioctx.aio_append(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1551 bl1, sizeof(buf)));
1552 {
1553 TestAlarm alarm;
1554 ASSERT_EQ(0, my_completion->wait_for_complete());
1555 }
1556 ASSERT_EQ(0, my_completion->get_return_value());
1557 char buf2[128];
1558 memset(buf2, 0xdd, sizeof(buf2));
1559 bufferlist bl2;
1560 bl2.append(buf2, sizeof(buf2));
9f95a23c
TL
1561 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1562 ASSERT_TRUE(my_completion2);
1e59de90 1563 ASSERT_EQ(0, test_data.m_ioctx.aio_append(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1564 bl2, sizeof(buf2)));
1565 {
1566 TestAlarm alarm;
1567 ASSERT_EQ(0, my_completion2->wait_for_complete());
1568 }
1569 ASSERT_EQ(0, my_completion2->get_return_value());
1570 bufferlist bl3;
9f95a23c
TL
1571 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1572 ASSERT_TRUE(my_completion3);
1e59de90 1573 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion3.get(),
9f95a23c 1574 &bl3, 2 * sizeof(buf), 0));
11fdf7f2
TL
1575 {
1576 TestAlarm alarm;
1577 ASSERT_EQ(0, my_completion3->wait_for_complete());
1578 }
1579 ASSERT_EQ((int)(sizeof(buf) * 2), my_completion3->get_return_value());
1580 ASSERT_EQ(sizeof(buf) * 2, bl3.length());
1581 ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
1582 ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
11fdf7f2
TL
1583}
1584
1585TEST(LibRadosAioPP, RemoveTestPP) {
1586 char buf[128];
1587 memset(buf, 0xaa, sizeof(buf));
1588 bufferlist bl1;
1589 bl1.append(buf, sizeof(buf));
1590 AioTestDataPP test_data;
1591 ASSERT_EQ("", test_data.init());
1e59de90 1592 ASSERT_EQ(0, test_data.m_ioctx.append(test_data.m_oid, bl1, sizeof(buf)));
9f95a23c 1593 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 1594 ASSERT_EQ(0, test_data.m_ioctx.aio_remove(test_data.m_oid, my_completion.get()));
11fdf7f2
TL
1595 {
1596 TestAlarm alarm;
1597 ASSERT_EQ(0, my_completion->wait_for_complete());
1598 }
1599 ASSERT_EQ(0, my_completion->get_return_value());
1600 bufferlist bl2;
1e59de90 1601 ASSERT_EQ(-ENOENT, test_data.m_ioctx.read(test_data.m_oid, bl2, sizeof(buf), 0));
11fdf7f2
TL
1602}
1603
1604TEST(LibRadosAioEC, RoundTripSparseReadPP) {
1e59de90 1605 SKIP_IF_CRIMSON();
11fdf7f2
TL
1606 AioTestDataECPP test_data;
1607 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1608 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1609 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1610 char buf[128];
1611 memset(buf, 0xcc, sizeof(buf));
1612 bufferlist bl1;
1613 bl1.append(buf, sizeof(buf));
1e59de90 1614 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1615 bl1, sizeof(buf), 0));
1616 {
1617 TestAlarm alarm;
1618 ASSERT_EQ(0, my_completion->wait_for_complete());
1619 }
1620 ASSERT_EQ(0, my_completion->get_return_value());
1621
1622 map<uint64_t, uint64_t> extents;
1623 bufferlist bl2;
9f95a23c
TL
1624 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1625 ASSERT_TRUE(my_completion2);
1e59de90 1626 ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read(test_data.m_oid, my_completion2.get(),
9f95a23c 1627 &extents, &bl2, sizeof(buf), 0));
11fdf7f2
TL
1628 {
1629 TestAlarm alarm;
1630 ASSERT_EQ(0, my_completion2->wait_for_complete());
1631 }
1632 ASSERT_EQ(0, my_completion2->get_return_value());
1633 assert_eq_sparse(bl1, extents, bl2);
11fdf7f2
TL
1634}
1635
1636TEST(LibRadosAioEC, RoundTripAppendPP) {
1e59de90 1637 SKIP_IF_CRIMSON();
11fdf7f2
TL
1638 AioTestDataECPP test_data;
1639 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1640 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1641 ASSERT_TRUE(my_completion);
1e59de90
TL
1642 bool req;
1643 ASSERT_EQ(0, test_data.m_ioctx.pool_requires_alignment2(&req));
1644 ASSERT_TRUE(req);
11fdf7f2
TL
1645 uint64_t alignment;
1646 ASSERT_EQ(0, test_data.m_ioctx.pool_required_alignment2(&alignment));
1647 ASSERT_NE((unsigned)0, alignment);
1648 int bsize = alignment;
1649 char *buf = (char *)new char[bsize];
1650 memset(buf, 0xcc, bsize);
1651 bufferlist bl1;
1652 bl1.append(buf, bsize);
1e59de90 1653 ASSERT_EQ(0, test_data.m_ioctx.aio_append(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1654 bl1, bsize));
1655 {
1656 TestAlarm alarm;
1657 ASSERT_EQ(0, my_completion->wait_for_complete());
1658 }
1659 ASSERT_EQ(0, my_completion->get_return_value());
1660
1661 int hbsize = bsize / 2;
1662 char *buf2 = (char *)new char[hbsize];
1663 memset(buf2, 0xdd, hbsize);
1664 bufferlist bl2;
1665 bl2.append(buf2, hbsize);
9f95a23c
TL
1666 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1667 ASSERT_TRUE(my_completion2);
1e59de90 1668 ASSERT_EQ(0, test_data.m_ioctx.aio_append(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1669 bl2, hbsize));
1670 {
1671 TestAlarm alarm;
1672 ASSERT_EQ(0, my_completion2->wait_for_complete());
1673 }
1674 ASSERT_EQ(0, my_completion2->get_return_value());
1675
9f95a23c
TL
1676 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1677 ASSERT_TRUE(my_completion3);
1e59de90 1678 ASSERT_EQ(0, test_data.m_ioctx.aio_append(test_data.m_oid, my_completion3.get(),
11fdf7f2
TL
1679 bl2, hbsize));
1680 {
1681 TestAlarm alarm;
1682 ASSERT_EQ(0, my_completion3->wait_for_complete());
1683 }
1684 EXPECT_EQ(-EOPNOTSUPP, my_completion3->get_return_value());
1685
1686 bufferlist bl3;
9f95a23c
TL
1687 auto my_completion4 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1688 ASSERT_TRUE(my_completion4);
1e59de90 1689 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion4.get(),
9f95a23c 1690 &bl3, bsize * 3, 0));
11fdf7f2
TL
1691 {
1692 TestAlarm alarm;
1693 ASSERT_EQ(0, my_completion4->wait_for_complete());
1694 }
1695 int tbsize = bsize + hbsize;
1696 ASSERT_EQ(tbsize, my_completion4->get_return_value());
1697 ASSERT_EQ((unsigned)tbsize, bl3.length());
1698 ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
1699 ASSERT_EQ(0, memcmp(bl3.c_str() + bsize, buf2, hbsize));
11fdf7f2
TL
1700 delete[] buf;
1701 delete[] buf2;
1702}
1703
1704TEST(LibRadosAioEC, IsCompletePP) {
1e59de90 1705 SKIP_IF_CRIMSON();
11fdf7f2
TL
1706 AioTestDataECPP test_data;
1707 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1708 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1709 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1710 char buf[128];
1711 memset(buf, 0xcc, sizeof(buf));
1712 bufferlist bl1;
1713 bl1.append(buf, sizeof(buf));
1e59de90 1714 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1715 bl1, sizeof(buf), 0));
1716 {
1717 TestAlarm alarm;
1718 ASSERT_EQ(0, my_completion->wait_for_complete());
1719 }
1720 ASSERT_EQ(0, my_completion->get_return_value());
1721 bufferlist bl2;
9f95a23c
TL
1722 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1723 ASSERT_TRUE(my_completion2);
1e59de90 1724 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1725 &bl2, sizeof(buf), 0));
1726 {
1727 TestAlarm alarm;
1728
1729 // Busy-wait until the AIO completes.
1730 // Normally we wouldn't do this, but we want to test is_complete.
1731 while (true) {
1732 int is_complete = my_completion2->is_complete();
1733 if (is_complete)
1734 break;
1735 }
1736 }
1737 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1738 ASSERT_EQ(sizeof(buf), bl2.length());
1739 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
1740}
1741TEST(LibRadosAioEC, IsSafePP) {
1e59de90 1742 SKIP_IF_CRIMSON();
11fdf7f2
TL
1743 AioTestDataECPP test_data;
1744 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1745 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1746 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1747 char buf[128];
1748 memset(buf, 0xcc, sizeof(buf));
1749 bufferlist bl1;
1750 bl1.append(buf, sizeof(buf));
1e59de90 1751 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1752 bl1, sizeof(buf), 0));
1753 {
1754 TestAlarm alarm;
1755
1756 // Busy-wait until the AIO completes.
1757 // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
1758 while (true) {
9f95a23c
TL
1759 int is_complete = my_completion->is_complete();
1760 if (is_complete)
11fdf7f2
TL
1761 break;
1762 }
1763 }
1764 ASSERT_EQ(0, my_completion->get_return_value());
9f95a23c 1765 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2 1766 bufferlist bl2;
9f95a23c 1767 ASSERT_TRUE(my_completion2);
1e59de90 1768 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1769 &bl2, sizeof(buf), 0));
1770 {
1771 TestAlarm alarm;
1772 ASSERT_EQ(0, my_completion2->wait_for_complete());
1773 }
1774 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1775 ASSERT_EQ(sizeof(buf), bl2.length());
1776 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
1777}
1778
1779TEST(LibRadosAioEC, ReturnValuePP) {
1e59de90 1780 SKIP_IF_CRIMSON();
11fdf7f2
TL
1781 AioTestDataECPP test_data;
1782 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1783 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1784 ASSERT_TRUE(my_completion);
11fdf7f2 1785 bufferlist bl1;
9f95a23c
TL
1786 ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent", my_completion.get(),
1787 &bl1, 128, 0));
11fdf7f2
TL
1788 {
1789 TestAlarm alarm;
1790 ASSERT_EQ(0, my_completion->wait_for_complete());
1791 }
1792 ASSERT_EQ(-ENOENT, my_completion->get_return_value());
11fdf7f2
TL
1793}
1794
1795TEST(LibRadosAioEC, FlushPP) {
1e59de90 1796 SKIP_IF_CRIMSON();
11fdf7f2
TL
1797 AioTestDataECPP test_data;
1798 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1799 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1800 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1801 char buf[128];
1802 memset(buf, 0xee, sizeof(buf));
1803 bufferlist bl1;
1804 bl1.append(buf, sizeof(buf));
1e59de90 1805 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1806 bl1, sizeof(buf), 0));
1807 ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
1808 ASSERT_EQ(0, my_completion->get_return_value());
1809 bufferlist bl2;
9f95a23c
TL
1810 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1811 ASSERT_TRUE(my_completion2);
1e59de90 1812 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1813 &bl2, sizeof(buf), 0));
1814 {
1815 TestAlarm alarm;
1816 ASSERT_EQ(0, my_completion2->wait_for_complete());
1817 }
1818 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1819 ASSERT_EQ(sizeof(buf), bl2.length());
1820 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
1821}
1822
1823TEST(LibRadosAioEC, FlushAsyncPP) {
1e59de90 1824 SKIP_IF_CRIMSON();
11fdf7f2
TL
1825 AioTestDataECPP test_data;
1826 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1827 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1828 auto flush_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1829 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1830 char buf[128];
1831 memset(buf, 0xee, sizeof(buf));
1832 bufferlist bl1;
1833 bl1.append(buf, sizeof(buf));
1e59de90 1834 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2 1835 bl1, sizeof(buf), 0));
9f95a23c 1836 ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion.get()));
11fdf7f2
TL
1837 {
1838 TestAlarm alarm;
1839 ASSERT_EQ(0, flush_completion->wait_for_complete());
11fdf7f2
TL
1840 }
1841 ASSERT_EQ(1, my_completion->is_complete());
11fdf7f2 1842 ASSERT_EQ(1, flush_completion->is_complete());
11fdf7f2
TL
1843 ASSERT_EQ(0, my_completion->get_return_value());
1844 bufferlist bl2;
9f95a23c
TL
1845 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1846 ASSERT_TRUE(my_completion2);
1e59de90 1847 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1848 &bl2, sizeof(buf), 0));
1849 {
1850 TestAlarm alarm;
1851 ASSERT_EQ(0, my_completion2->wait_for_complete());
1852 }
1853 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1854 ASSERT_EQ(sizeof(buf), bl2.length());
1855 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
11fdf7f2
TL
1856}
1857
1858TEST(LibRadosAioEC, RoundTripWriteFullPP) {
1e59de90 1859 SKIP_IF_CRIMSON();
11fdf7f2
TL
1860 AioTestDataECPP test_data;
1861 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1862 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1863 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1864 char buf[128];
1865 memset(buf, 0xcc, sizeof(buf));
1866 bufferlist bl1;
1867 bl1.append(buf, sizeof(buf));
1e59de90 1868 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1869 bl1, sizeof(buf), 0));
1870 {
1871 TestAlarm alarm;
1872 ASSERT_EQ(0, my_completion->wait_for_complete());
1873 }
1874 ASSERT_EQ(0, my_completion->get_return_value());
1875 char buf2[64];
1876 memset(buf2, 0xdd, sizeof(buf2));
1877 bufferlist bl2;
1878 bl2.append(buf2, sizeof(buf2));
9f95a23c
TL
1879 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1880 ASSERT_TRUE(my_completion2);
1e59de90 1881 ASSERT_EQ(0, test_data.m_ioctx.aio_write_full(test_data.m_oid, my_completion2.get(), bl2));
11fdf7f2
TL
1882 {
1883 TestAlarm alarm;
1884 ASSERT_EQ(0, my_completion2->wait_for_complete());
1885 }
1886 ASSERT_EQ(0, my_completion2->get_return_value());
1887 bufferlist bl3;
9f95a23c
TL
1888 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1889 ASSERT_TRUE(my_completion3);
1e59de90 1890 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion3.get(),
11fdf7f2
TL
1891 &bl3, sizeof(buf), 0));
1892 {
1893 TestAlarm alarm;
1894 ASSERT_EQ(0, my_completion3->wait_for_complete());
1895 }
1896 ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
1897 ASSERT_EQ(sizeof(buf2), bl3.length());
1898 ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
11fdf7f2
TL
1899}
1900
1901//using ObjectWriteOperation/ObjectReadOperation with iohint
1902TEST(LibRadosAioEC, RoundTripWriteFullPP2)
1903{
1e59de90 1904 SKIP_IF_CRIMSON();
11fdf7f2 1905 Rados cluster;
1e59de90
TL
1906 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
1907 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
1908 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1909 IoCtx ioctx;
1910 cluster.ioctx_create(pool_name.c_str(), ioctx);
1911
9f95a23c 1912 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
1913 ObjectWriteOperation op;
1914 char buf[128];
1915 memset(buf, 0xcc, sizeof(buf));
1916 bufferlist bl;
1917 bl.append(buf);
1918
1919 op.write_full(bl);
1920 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
1921 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
1922 {
1923 TestAlarm alarm;
1924 ASSERT_EQ(0, my_completion1->wait_for_complete());
1925 }
1926 EXPECT_EQ(0, my_completion1->get_return_value());
1927
9f95a23c 1928 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
1929 bl.clear();
1930 ObjectReadOperation op1;
1931 op1.read(0, sizeof(buf), &bl, NULL);
1932 op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
1933 ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
1934 {
1935 TestAlarm alarm;
1936 ASSERT_EQ(0, my_completion2->wait_for_complete());
1937 }
1938 EXPECT_EQ(0, my_completion2->get_return_value());
1939 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
1940
1941 ioctx.remove("test_obj");
1942 destroy_one_pool_pp(pool_name, cluster);
1943}
1944
1945TEST(LibRadosAioEC, SimpleStatPP) {
1e59de90 1946 SKIP_IF_CRIMSON();
11fdf7f2
TL
1947 AioTestDataECPP test_data;
1948 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1949 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1950 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1951 char buf[128];
1952 memset(buf, 0xcc, sizeof(buf));
1953 bufferlist bl1;
1954 bl1.append(buf, sizeof(buf));
1e59de90 1955 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1956 bl1, sizeof(buf), 0));
1957 {
1958 TestAlarm alarm;
1959 ASSERT_EQ(0, my_completion->wait_for_complete());
1960 }
1961 ASSERT_EQ(0, my_completion->get_return_value());
1962 uint64_t psize;
1963 time_t pmtime;
9f95a23c
TL
1964 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1965 ASSERT_TRUE(my_completion2);
1e59de90 1966 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1967 &psize, &pmtime));
1968 {
1969 TestAlarm alarm;
1970 ASSERT_EQ(0, my_completion2->wait_for_complete());
1971 }
1972 ASSERT_EQ(0, my_completion2->get_return_value());
1973 ASSERT_EQ(sizeof(buf), psize);
11fdf7f2
TL
1974}
1975
1976TEST(LibRadosAioEC, SimpleStatPPNS) {
1e59de90 1977 SKIP_IF_CRIMSON();
11fdf7f2
TL
1978 AioTestDataECPP test_data;
1979 ASSERT_EQ("", test_data.init());
9f95a23c
TL
1980 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1981 ASSERT_TRUE(my_completion);
11fdf7f2
TL
1982 char buf[128];
1983 memset(buf, 0xcc, sizeof(buf));
1984 bufferlist bl1;
1985 bl1.append(buf, sizeof(buf));
1e59de90 1986 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
1987 bl1, sizeof(buf), 0));
1988 {
1989 TestAlarm alarm;
1990 ASSERT_EQ(0, my_completion->wait_for_complete());
1991 }
1992 ASSERT_EQ(0, my_completion->get_return_value());
1993 uint64_t psize;
1994 time_t pmtime;
9f95a23c
TL
1995 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1996 ASSERT_TRUE(my_completion2);
1e59de90 1997 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
1998 &psize, &pmtime));
1999 {
2000 TestAlarm alarm;
2001 ASSERT_EQ(0, my_completion2->wait_for_complete());
2002 }
2003 ASSERT_EQ(0, my_completion2->get_return_value());
2004 ASSERT_EQ(sizeof(buf), psize);
11fdf7f2
TL
2005}
2006
2007TEST(LibRadosAioEC, StatRemovePP) {
1e59de90 2008 SKIP_IF_CRIMSON();
11fdf7f2
TL
2009 AioTestDataECPP test_data;
2010 ASSERT_EQ("", test_data.init());
9f95a23c
TL
2011 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2012 ASSERT_TRUE(my_completion);
11fdf7f2
TL
2013 char buf[128];
2014 memset(buf, 0xcc, sizeof(buf));
2015 bufferlist bl1;
2016 bl1.append(buf, sizeof(buf));
1e59de90 2017 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
2018 bl1, sizeof(buf), 0));
2019 {
2020 TestAlarm alarm;
2021 ASSERT_EQ(0, my_completion->wait_for_complete());
2022 }
2023 ASSERT_EQ(0, my_completion->get_return_value());
2024 uint64_t psize;
2025 time_t pmtime;
9f95a23c
TL
2026 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2027 ASSERT_TRUE(my_completion2);
1e59de90 2028 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
2029 &psize, &pmtime));
2030 {
2031 TestAlarm alarm;
2032 ASSERT_EQ(0, my_completion2->wait_for_complete());
2033 }
2034 ASSERT_EQ(0, my_completion2->get_return_value());
2035 ASSERT_EQ(sizeof(buf), psize);
2036 uint64_t psize2;
2037 time_t pmtime2;
9f95a23c
TL
2038 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2039 ASSERT_TRUE(my_completion3);
1e59de90 2040 ASSERT_EQ(0, test_data.m_ioctx.aio_remove(test_data.m_oid, my_completion3.get()));
11fdf7f2
TL
2041 {
2042 TestAlarm alarm;
2043 ASSERT_EQ(0, my_completion3->wait_for_complete());
2044 }
2045 ASSERT_EQ(0, my_completion3->get_return_value());
2046
9f95a23c
TL
2047 auto my_completion4 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2048 ASSERT_TRUE(my_completion4);
1e59de90 2049 ASSERT_EQ(0, test_data.m_ioctx.aio_stat(test_data.m_oid, my_completion4.get(),
11fdf7f2
TL
2050 &psize2, &pmtime2));
2051 {
2052 TestAlarm alarm;
2053 ASSERT_EQ(0, my_completion4->wait_for_complete());
2054 }
2055 ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
11fdf7f2
TL
2056}
2057
2058TEST(LibRadosAioEC, ExecuteClassPP) {
1e59de90 2059 SKIP_IF_CRIMSON();
11fdf7f2
TL
2060 AioTestDataECPP test_data;
2061 ASSERT_EQ("", test_data.init());
9f95a23c
TL
2062 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2063 ASSERT_TRUE(my_completion);
11fdf7f2
TL
2064 char buf[128];
2065 memset(buf, 0xcc, sizeof(buf));
2066 bufferlist bl1;
2067 bl1.append(buf, sizeof(buf));
1e59de90 2068 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
2069 bl1, sizeof(buf), 0));
2070 {
2071 TestAlarm alarm;
2072 ASSERT_EQ(0, my_completion->wait_for_complete());
2073 }
2074 ASSERT_EQ(0, my_completion->get_return_value());
9f95a23c
TL
2075 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2076 ASSERT_TRUE(my_completion2);
11fdf7f2 2077 bufferlist in, out;
1e59de90 2078 ASSERT_EQ(0, test_data.m_ioctx.aio_exec(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
2079 "hello", "say_hello", in, &out));
2080 {
2081 TestAlarm alarm;
2082 ASSERT_EQ(0, my_completion2->wait_for_complete());
2083 }
2084 ASSERT_EQ(0, my_completion2->get_return_value());
2085 ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
11fdf7f2
TL
2086}
2087
2088TEST(LibRadosAioEC, OmapPP) {
1e59de90 2089 SKIP_IF_CRIMSON();
11fdf7f2 2090 Rados cluster;
1e59de90
TL
2091 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
2092 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
2093 ASSERT_EQ("", create_one_ec_pool_pp(pool_name, cluster));
2094 IoCtx ioctx;
2095 cluster.ioctx_create(pool_name.c_str(), ioctx);
2096
2097 string header_str = "baz";
2098 bufferptr bp(header_str.c_str(), header_str.size() + 1);
2099 bufferlist header_to_set;
2100 header_to_set.push_back(bp);
2101 map<string, bufferlist> to_set;
2102 {
9f95a23c 2103 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
2104 ObjectWriteOperation op;
2105 to_set["foo"] = header_to_set;
2106 to_set["foo2"] = header_to_set;
2107 to_set["qfoo3"] = header_to_set;
2108 op.omap_set(to_set);
2109
2110 op.omap_set_header(header_to_set);
2111
2112 ioctx.aio_operate("test_obj", my_completion.get(), &op);
2113 {
2114 TestAlarm alarm;
2115 ASSERT_EQ(0, my_completion->wait_for_complete());
2116 }
2117 EXPECT_EQ(-EOPNOTSUPP, my_completion->get_return_value());
2118 }
2119 ioctx.remove("test_obj");
9f95a23c 2120 destroy_one_ec_pool_pp(pool_name, cluster);
11fdf7f2
TL
2121}
2122
2123TEST(LibRadosAioEC, MultiWritePP) {
1e59de90 2124 SKIP_IF_CRIMSON();
11fdf7f2
TL
2125 AioTestDataECPP test_data;
2126 ASSERT_EQ("", test_data.init());
9f95a23c
TL
2127 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2128 ASSERT_TRUE(my_completion);
11fdf7f2
TL
2129 char buf[128];
2130 memset(buf, 0xcc, sizeof(buf));
2131 bufferlist bl1;
2132 bl1.append(buf, sizeof(buf));
1e59de90 2133 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
2134 bl1, sizeof(buf), 0));
2135 {
2136 TestAlarm alarm;
2137 ASSERT_EQ(0, my_completion->wait_for_complete());
2138 }
2139 ASSERT_EQ(0, my_completion->get_return_value());
2140
2141 char buf2[64];
2142 memset(buf2, 0xdd, sizeof(buf2));
2143 bufferlist bl2;
2144 bl2.append(buf2, sizeof(buf2));
9f95a23c
TL
2145 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2146 ASSERT_TRUE(my_completion2);
1e59de90 2147 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion2.get(),
11fdf7f2
TL
2148 bl2, sizeof(buf2), sizeof(buf)));
2149 {
2150 TestAlarm alarm;
2151 ASSERT_EQ(0, my_completion2->wait_for_complete());
2152 }
2153 ASSERT_EQ(-EOPNOTSUPP, my_completion2->get_return_value());
2154
2155 bufferlist bl3;
9f95a23c
TL
2156 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2157 ASSERT_TRUE(my_completion3);
1e59de90 2158 ASSERT_EQ(0, test_data.m_ioctx.aio_read(test_data.m_oid, my_completion3.get(),
11fdf7f2
TL
2159 &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
2160 {
2161 TestAlarm alarm;
2162 ASSERT_EQ(0, my_completion3->wait_for_complete());
2163 }
2164 ASSERT_EQ((int)sizeof(buf), my_completion3->get_return_value());
2165 ASSERT_EQ(sizeof(buf), bl3.length());
2166 ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
9f95a23c 2167
11fdf7f2
TL
2168}
2169
2170TEST(LibRadosAio, RacingRemovePP) {
2171 AioTestDataPP test_data;
2172 ASSERT_EQ("", test_data.init({{"objecter_retry_writes_after_first_reply", "true"}}));
9f95a23c
TL
2173 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2174 ASSERT_TRUE(my_completion);
11fdf7f2
TL
2175 char buf[128];
2176 memset(buf, 0xcc, sizeof(buf));
2177 bufferlist bl;
2178 bl.append(buf, sizeof(buf));
9f95a23c
TL
2179 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2180 ASSERT_TRUE(my_completion2);
1e59de90
TL
2181 ASSERT_EQ(0, test_data.m_ioctx.aio_remove(test_data.m_oid, my_completion2.get()));
2182 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
2183 bl, sizeof(buf), 0));
2184 {
2185 TestAlarm alarm;
2186 my_completion2->wait_for_complete();
2187 my_completion->wait_for_complete();
2188 }
2189 ASSERT_EQ(-ENOENT, my_completion2->get_return_value());
2190 ASSERT_EQ(0, my_completion->get_return_value());
1e59de90 2191 ASSERT_EQ(0, test_data.m_ioctx.stat(test_data.m_oid, nullptr, nullptr));
11fdf7f2
TL
2192}
2193
2194TEST(LibRadosAio, RoundTripCmpExtPP) {
2195 AioTestDataPP test_data;
2196 ASSERT_EQ("", test_data.init());
9f95a23c
TL
2197 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2198 ASSERT_TRUE(my_completion);
11fdf7f2
TL
2199 char full[128];
2200 memset(full, 0xcc, sizeof(full));
2201 bufferlist bl1;
2202 bl1.append(full, sizeof(full));
1e59de90 2203 ASSERT_EQ(0, test_data.m_ioctx.aio_write(test_data.m_oid, my_completion.get(),
11fdf7f2
TL
2204 bl1, sizeof(full), 0));
2205 {
2206 TestAlarm alarm;
2207 ASSERT_EQ(0, my_completion->wait_for_complete());
2208 }
2209 ASSERT_EQ(0, my_completion->get_return_value());
2210
2211 /* compare with match */
2212 bufferlist cbl;
2213 cbl.append(full, sizeof(full));
9f95a23c 2214 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 2215 ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext(test_data.m_oid, my_completion2.get(), 0, cbl));
11fdf7f2
TL
2216
2217 {
2218 TestAlarm alarm;
2219 ASSERT_EQ(0, my_completion2->wait_for_complete());
2220 }
2221 ASSERT_EQ(0, my_completion2->get_return_value());
2222
2223 /* compare with mismatch */
2224 memset(full, 0xdd, sizeof(full));
2225 cbl.clear();
2226 cbl.append(full, sizeof(full));
9f95a23c 2227 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1e59de90 2228 ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext(test_data.m_oid, my_completion3.get(), 0, cbl));
11fdf7f2
TL
2229 {
2230 TestAlarm alarm;
2231 ASSERT_EQ(0, my_completion3->wait_for_complete());
2232 }
2233 ASSERT_EQ(-MAX_ERRNO, my_completion3->get_return_value());
11fdf7f2
TL
2234}
2235
2236TEST(LibRadosAio, RoundTripCmpExtPP2)
2237{
2238 int ret;
2239 char buf[128];
2240 char miscmp_buf[128];
2241 bufferlist cbl;
2242 Rados cluster;
1e59de90
TL
2243 auto pool_prefix = fmt::format("{}_", ::testing::UnitTest::GetInstance()->current_test_info()->name());
2244 std::string pool_name = get_temp_pool_name(pool_prefix);
11fdf7f2
TL
2245 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
2246 IoCtx ioctx;
2247 cluster.ioctx_create(pool_name.c_str(), ioctx);
2248
9f95a23c 2249 auto wr_cmpl = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
2250 ObjectWriteOperation wr_op;
2251 memset(buf, 0xcc, sizeof(buf));
2252 memset(miscmp_buf, 0xdd, sizeof(miscmp_buf));
2253 bufferlist bl;
2254 bl.append(buf, sizeof(buf));
2255
2256 wr_op.write_full(bl);
2257 wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
2258 ioctx.aio_operate("test_obj", wr_cmpl.get(), &wr_op);
2259 {
2260 TestAlarm alarm;
2261 ASSERT_EQ(0, wr_cmpl->wait_for_complete());
2262 }
2263 EXPECT_EQ(0, wr_cmpl->get_return_value());
2264
2265 /* cmpext as write op. first match then mismatch */
9f95a23c 2266 auto wr_cmpext_cmpl = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
2267 cbl.append(buf, sizeof(buf));
2268 ret = 0;
2269
2270 wr_op.cmpext(0, cbl, &ret);
2271 wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
2272 ioctx.aio_operate("test_obj", wr_cmpext_cmpl.get(), &wr_op);
2273 {
2274 TestAlarm alarm;
2275 ASSERT_EQ(0, wr_cmpext_cmpl->wait_for_complete());
2276 }
2277 EXPECT_EQ(0, wr_cmpext_cmpl->get_return_value());
2278 EXPECT_EQ(0, ret);
2279
9f95a23c 2280 auto wr_cmpext_cmpl2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
2281 cbl.clear();
2282 cbl.append(miscmp_buf, sizeof(miscmp_buf));
2283 ret = 0;
2284
2285 wr_op.cmpext(0, cbl, &ret);
2286 wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
2287 ioctx.aio_operate("test_obj", wr_cmpext_cmpl2.get(), &wr_op);
2288 {
2289 TestAlarm alarm;
2290 ASSERT_EQ(0, wr_cmpext_cmpl2->wait_for_complete());
2291 }
2292 EXPECT_EQ(-MAX_ERRNO, wr_cmpext_cmpl2->get_return_value());
2293 EXPECT_EQ(-MAX_ERRNO, ret);
2294
2295 /* cmpext as read op */
9f95a23c 2296 auto rd_cmpext_cmpl = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
2297 ObjectReadOperation rd_op;
2298 cbl.clear();
2299 cbl.append(buf, sizeof(buf));
2300 ret = 0;
2301 rd_op.cmpext(0, cbl, &ret);
2302 rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
2303 ioctx.aio_operate("test_obj", rd_cmpext_cmpl.get(), &rd_op, 0);
2304 {
2305 TestAlarm alarm;
2306 ASSERT_EQ(0, rd_cmpext_cmpl->wait_for_complete());
2307 }
2308 EXPECT_EQ(0, rd_cmpext_cmpl->get_return_value());
2309 EXPECT_EQ(0, ret);
2310
9f95a23c 2311 auto rd_cmpext_cmpl2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
11fdf7f2
TL
2312 cbl.clear();
2313 cbl.append(miscmp_buf, sizeof(miscmp_buf));
2314 ret = 0;
2315
2316 rd_op.cmpext(0, cbl, &ret);
2317 rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
2318 ioctx.aio_operate("test_obj", rd_cmpext_cmpl2.get(), &rd_op, 0);
2319 {
2320 TestAlarm alarm;
2321 ASSERT_EQ(0, rd_cmpext_cmpl2->wait_for_complete());
2322 }
2323 EXPECT_EQ(-MAX_ERRNO, rd_cmpext_cmpl2->get_return_value());
2324 EXPECT_EQ(-MAX_ERRNO, ret);
2325
2326 ioctx.remove("test_obj");
2327 destroy_one_pool_pp(pool_name, cluster);
2328}
20effc67
TL
2329
2330ceph::mutex my_lock = ceph::make_mutex("my_lock");
2331set<unsigned> inflight;
2332unsigned max_success = 0;
2333unsigned min_failed = 0;
2334
2335struct io_info {
2336 unsigned i;
2337 AioCompletion *c;
2338};
2339
1e59de90 2340void pool_io_callback(completion_t cb, void *arg /* Actually AioCompletion* */)
20effc67 2341{
20effc67
TL
2342 io_info *info = (io_info *)arg;
2343 unsigned long i = info->i;
1e59de90
TL
2344 {
2345 TestAlarm alarm;
2346 ASSERT_EQ(0, info->c->wait_for_complete());
2347 }
20effc67
TL
2348 int r = info->c->get_return_value();
2349 //cout << "finish " << i << " r = " << r << std::endl;
2350
2351 std::scoped_lock l(my_lock);
2352 inflight.erase(i);
2353 if (r == 0) {
2354 if (i > max_success) {
2355 max_success = i;
2356 }
2357 } else {
2358 if (!min_failed || i < min_failed) {
2359 min_failed = i;
2360 }
2361 }
2362}
2363
2364TEST(LibRadosAio, PoolEIOFlag) {
2365 AioTestDataPP test_data;
2366 ASSERT_EQ("", test_data.init());
2367
2368 bufferlist bl;
2369 bl.append("some data");
2370 std::thread *t = nullptr;
2371
2372 unsigned max = 100;
1e59de90 2373 unsigned timeout = max * 10;
20effc67
TL
2374 unsigned long i = 1;
2375 my_lock.lock();
1e59de90 2376 for (; min_failed == 0 && i <= timeout; ++i) {
20effc67
TL
2377 io_info *info = new io_info;
2378 info->i = i;
2379 info->c = Rados::aio_create_completion();
2380 info->c->set_complete_callback((void*)info, pool_io_callback);
2381 inflight.insert(i);
2382 my_lock.unlock();
1e59de90 2383 int r = test_data.m_ioctx.aio_write(test_data.m_oid, info->c, bl, bl.length(), 0);
20effc67
TL
2384 //cout << "start " << i << " r = " << r << std::endl;
2385
2386 if (i == max / 2) {
2387 cout << "setting pool EIO" << std::endl;
2388 t = new std::thread(
2389 [&] {
2390 bufferlist empty;
1e59de90
TL
2391 ASSERT_EQ(0, test_data.m_cluster.mon_command(
2392 fmt::format(R"({{
2393 "prefix": "osd pool set",
2394 "pool": "{}",
2395 "var": "eio",
2396 "val": "true"
2397 }})", test_data.m_pool_name),
2398 empty, nullptr, nullptr));
20effc67
TL
2399 });
2400 }
2401
1e59de90 2402 std::this_thread::sleep_for(10ms);
20effc67
TL
2403 my_lock.lock();
2404 if (r < 0) {
2405 inflight.erase(i);
2406 break;
2407 }
2408 }
2409 t->join();
2410 delete t;
2411
2412 // wait for ios to finish
2413 for (; !inflight.empty(); ++i) {
1e59de90 2414 cout << "waiting for " << inflight.size() << std::endl;
20effc67
TL
2415 my_lock.unlock();
2416 sleep(1);
2417 my_lock.lock();
2418 }
2419
2420 cout << "max_success " << max_success << ", min_failed " << min_failed << std::endl;
2421 ASSERT_TRUE(max_success + 1 == min_failed);
2422 my_lock.unlock();
2423}
2a845540
TL
2424
2425// This test case reproduces https://tracker.ceph.com/issues/57152
2426TEST(LibRadosAio, MultiReads) {
2427
2428 // here we test multithreaded aio reads
2429
2430 AioTestDataPP test_data;
2431 ASSERT_EQ("", test_data.init());
2432 auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2433 ASSERT_TRUE(my_completion);
2434 char buf[128];
2435 memset(buf, 0xcc, sizeof(buf));
2436 bufferlist bl1;
2437 bl1.append(buf, sizeof(buf));
2438 ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion.get(),
2439 bl1, sizeof(buf), 0));
2440 {
2441 TestAlarm alarm;
2442 ASSERT_EQ(0, my_completion->wait_for_complete());
2443 }
2444 ASSERT_EQ(0, my_completion->get_return_value());
2445
2446 // Don't use std::vector to store bufferlists (e.g for parallelizing aio_reads),
2447 // as they are being moved whenever the vector resizes
2448 // and will cause invalidated references.
2449 std::deque<std::pair<bufferlist, std::unique_ptr<AioCompletion>>> reads;
2450 for (int i = 0; i < 100; i++) {
2451 // std::deque is appropriate here as emplace_back() is obliged to
2452 // preserve the referenced inserted element. (Unlike insert() or erase())
2453 auto& [bl, aiocp] = reads.emplace_back();
2454 aiocp = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2455 ASSERT_TRUE(aiocp);
2456 ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", aiocp.get(),
2457 &bl, sizeof(buf), 0));
2458 }
2459 for (auto& [bl, aiocp] : reads) {
2460 {
2461 TestAlarm alarm;
2462 ASSERT_EQ(0, aiocp->wait_for_complete());
2463 }
2464 ASSERT_EQ((int)sizeof(buf), aiocp->get_return_value());
2465 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
2466 }
2467}