6 #include <boost/scoped_ptr.hpp>
8 #include "gtest/gtest.h"
10 #include "common/errno.h"
11 #include "include/err.h"
12 #include "include/rados/librados.hpp"
13 #include "include/types.h"
14 #include "include/stringify.h"
15 #include "include/scope_guard.h"
16 #include "common/ceph_mutex.h"
21 using namespace librados
;
35 destroy_one_pool_pp(m_pool_name
, m_cluster
);
44 std::string
init(const std::map
<std::string
, std::string
> &config
)
48 m_pool_name
= get_temp_pool_name();
49 std::string err
= create_one_pool_pp(m_pool_name
, m_cluster
, config
);
52 oss
<< "create_one_pool(" << m_pool_name
<< ") failed: error " << err
;
55 ret
= m_cluster
.ioctx_create(m_pool_name
.c_str(), m_ioctx
);
57 destroy_one_pool_pp(m_pool_name
, m_cluster
);
59 oss
<< "rados_ioctx_create failed: error " << ret
;
68 std::string m_pool_name
;
72 TEST(LibRadosAio
, TooBigPP
) {
73 AioTestDataPP test_data
;
74 ASSERT_EQ("", test_data
.init());
77 auto aio_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
78 ASSERT_EQ(-E2BIG
, test_data
.m_ioctx
.aio_write("foo", aio_completion
.get(), bl
, UINT_MAX
, 0));
79 ASSERT_EQ(-E2BIG
, test_data
.m_ioctx
.aio_append("foo", aio_completion
.get(), bl
, UINT_MAX
));
80 // ioctx.aio_write_full no way to overflow bl.length()
83 TEST(LibRadosAio
, PoolQuotaPP
) {
84 AioTestDataPP test_data
;
85 ASSERT_EQ("", test_data
.init());
86 string p
= get_temp_pool_name();
87 ASSERT_EQ(0, test_data
.m_cluster
.pool_create(p
.c_str()));
89 ASSERT_EQ(0, test_data
.m_cluster
.ioctx_create(p
.c_str(), ioctx
));
90 ioctx
.application_enable("rados", true);
93 ASSERT_EQ(0, test_data
.m_cluster
.mon_command(
94 "{\"prefix\": \"osd pool set-quota\", \"pool\": \"" + p
+
95 "\", \"field\": \"max_bytes\", \"val\": \"4096\"}",
102 for (n
= 0; n
< 1024; ++n
) {
103 ObjectWriteOperation op
;
105 auto completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
106 ASSERT_EQ(0, ioctx
.aio_operate("foo" + stringify(n
),
107 completion
.get(), &op
,
108 librados::OPERATION_FULL_TRY
));
109 completion
->wait_for_complete();
110 int r
= completion
->get_return_value();
118 // make sure we have latest map that marked the pool full
119 test_data
.m_cluster
.wait_for_latest_osdmap();
121 // make sure we block without FULL_TRY
123 ObjectWriteOperation op
;
125 auto completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
126 ASSERT_EQ(0, ioctx
.aio_operate("bar", completion
.get(), &op
, 0));
128 ASSERT_FALSE(completion
->is_complete());
132 ASSERT_EQ(0, test_data
.m_cluster
.pool_delete(p
.c_str()));
135 TEST(LibRadosAio
, SimpleWritePP
) {
137 memset(buf
, 0xcc, sizeof(buf
));
139 bl1
.append(buf
, sizeof(buf
));
141 AioTestDataPP test_data
;
142 ASSERT_EQ("", test_data
.init());
143 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
144 ASSERT_TRUE(my_completion
);
145 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
146 bl1
, sizeof(buf
), 0));
149 ASSERT_EQ(0, my_completion
->wait_for_complete());
151 ASSERT_EQ(0, my_completion
->get_return_value());
155 AioTestDataPP test_data
;
156 ASSERT_EQ("", test_data
.init());
157 test_data
.m_ioctx
.set_namespace("nspace");
158 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
159 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
160 bl1
, sizeof(buf
), 0));
163 ASSERT_EQ(0, my_completion
->wait_for_complete());
165 ASSERT_EQ(0, my_completion
->get_return_value());
169 TEST(LibRadosAio
, WaitForSafePP
) {
170 AioTestDataPP test_data
;
171 ASSERT_EQ("", test_data
.init());
172 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
173 ASSERT_TRUE(my_completion
);
175 memset(buf
, 0xcc, sizeof(buf
));
177 bl1
.append(buf
, sizeof(buf
));
178 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
179 bl1
, sizeof(buf
), 0));
181 ASSERT_EQ(0, my_completion
->wait_for_complete());
182 ASSERT_EQ(0, my_completion
->get_return_value());
185 TEST(LibRadosAio
, RoundTripPP
) {
186 AioTestDataPP test_data
;
187 ASSERT_EQ("", test_data
.init());
188 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
189 ASSERT_TRUE(my_completion
);
191 memset(buf
, 0xcc, sizeof(buf
));
193 bl1
.append(buf
, sizeof(buf
));
194 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
195 bl1
, sizeof(buf
), 0));
198 ASSERT_EQ(0, my_completion
->wait_for_complete());
200 ASSERT_EQ(0, my_completion
->get_return_value());
202 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
203 ASSERT_TRUE(my_completion2
);
204 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
205 &bl2
, sizeof(buf
), 0));
208 ASSERT_EQ(0, my_completion2
->wait_for_complete());
210 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
211 ASSERT_EQ(sizeof(buf
), bl2
.length());
212 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
215 TEST(LibRadosAio
, RoundTripPP2
) {
216 AioTestDataPP test_data
;
217 ASSERT_EQ("", test_data
.init());
218 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
219 ASSERT_TRUE(my_completion
);
221 memset(buf
, 0xcc, sizeof(buf
));
223 bl1
.append(buf
, sizeof(buf
));
224 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
225 bl1
, sizeof(buf
), 0));
228 ASSERT_EQ(0, my_completion
->wait_for_complete());
230 ASSERT_EQ(0, my_completion
->get_return_value());
232 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
233 ASSERT_TRUE(my_completion2
);
234 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
235 &bl2
, sizeof(buf
), 0));
238 ASSERT_EQ(0, my_completion2
->wait_for_complete());
240 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
241 ASSERT_EQ(sizeof(buf
), bl2
.length());
242 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
245 //using ObjectWriteOperation/ObjectReadOperation with iohint
246 TEST(LibRadosAio
, RoundTripPP3
)
249 std::string pool_name
= get_temp_pool_name();
250 ASSERT_EQ("", create_one_pool_pp(pool_name
, cluster
));
252 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
254 auto my_completion1
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
255 ObjectWriteOperation op
;
257 memset(buf
, 0xcc, sizeof(buf
));
259 bl
.append(buf
, sizeof(buf
));
262 op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
263 ioctx
.aio_operate("test_obj", my_completion1
.get(), &op
);
266 ASSERT_EQ(0, my_completion1
->wait_for_complete());
268 EXPECT_EQ(0, my_completion1
->get_return_value());
270 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
272 ObjectReadOperation op1
;
273 op1
.read(0, sizeof(buf
), &bl
, NULL
);
274 op1
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
|LIBRADOS_OP_FLAG_FADVISE_RANDOM
);
275 bufferlist init_value_bl
;
276 encode(static_cast<int32_t>(-1), init_value_bl
);
278 op1
.checksum(LIBRADOS_CHECKSUM_TYPE_CRC32C
, init_value_bl
,
279 0, 0, 0, &csum_bl
, nullptr);
280 ioctx
.aio_operate("test_obj", my_completion2
.get(), &op1
, 0);
283 ASSERT_EQ(0, my_completion2
->wait_for_complete());
285 EXPECT_EQ(0, my_completion2
->get_return_value());
286 ASSERT_EQ(0, memcmp(buf
, bl
.c_str(), sizeof(buf
)));
288 ASSERT_EQ(8U, csum_bl
.length());
289 auto csum_bl_it
= csum_bl
.cbegin();
292 decode(csum_count
, csum_bl_it
);
293 ASSERT_EQ(1U, csum_count
);
294 decode(csum
, csum_bl_it
);
295 ASSERT_EQ(bl
.crc32c(-1), csum
);
296 ioctx
.remove("test_obj");
297 destroy_one_pool_pp(pool_name
, cluster
);
300 TEST(LibRadosAio
, RoundTripSparseReadPP
) {
301 AioTestDataPP test_data
;
302 ASSERT_EQ("", test_data
.init());
303 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
304 ASSERT_TRUE(my_completion
);
306 memset(buf
, 0xcc, sizeof(buf
));
308 bl1
.append(buf
, sizeof(buf
));
309 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
310 bl1
, sizeof(buf
), 0));
313 ASSERT_EQ(0, my_completion
->wait_for_complete());
315 ASSERT_EQ(0, my_completion
->get_return_value());
316 std::map
<uint64_t, uint64_t> extents
;
318 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
319 ASSERT_TRUE(my_completion2
);
320 ASSERT_EQ(0, test_data
.m_ioctx
.aio_sparse_read("foo", my_completion2
.get(),
321 &extents
, &bl2
, sizeof(buf
), 0));
324 ASSERT_EQ(0, my_completion2
->wait_for_complete());
326 ASSERT_EQ(0, my_completion2
->get_return_value());
327 assert_eq_sparse(bl1
, extents
, bl2
);
330 TEST(LibRadosAioPP
, ReadIntoBufferlist
) {
332 // here we test reading into a non-empty bufferlist referencing existing
335 AioTestDataPP test_data
;
336 ASSERT_EQ("", test_data
.init());
337 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
338 ASSERT_TRUE(my_completion
);
340 memset(buf
, 0xcc, sizeof(buf
));
342 bl1
.append(buf
, sizeof(buf
));
343 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
344 bl1
, sizeof(buf
), 0));
347 ASSERT_EQ(0, my_completion
->wait_for_complete());
349 ASSERT_EQ(0, my_completion
->get_return_value());
352 char buf2
[sizeof(buf
)];
353 memset(buf2
, 0xbb, sizeof(buf2
));
354 bl2
.append(buffer::create_static(sizeof(buf2
), buf2
));
355 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
356 ASSERT_TRUE(my_completion2
);
357 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
358 &bl2
, sizeof(buf
), 0));
361 ASSERT_EQ(0, my_completion2
->wait_for_complete());
363 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
364 ASSERT_EQ(0, memcmp(buf
, buf2
, sizeof(buf
)));
367 TEST(LibRadosAioPP
, XattrsRoundTripPP
) {
369 char attr1
[] = "attr1";
370 char attr1_buf
[] = "foo bar baz";
371 memset(buf
, 0xaa, sizeof(buf
));
373 bl1
.append(buf
, sizeof(buf
));
374 AioTestDataPP test_data
;
375 ASSERT_EQ("", test_data
.init());
376 ASSERT_EQ(0, test_data
.m_ioctx
.append("foo", bl1
, sizeof(buf
)));
379 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
380 ASSERT_EQ(0, test_data
.m_ioctx
.aio_getxattr("foo", my_completion
.get(), attr1
, bl2
));
383 ASSERT_EQ(0, my_completion
->wait_for_complete());
385 ASSERT_EQ(-ENODATA
, my_completion
->get_return_value());
388 bl3
.append(attr1_buf
, sizeof(attr1_buf
));
390 AioTestDataPP test_data2
;
391 ASSERT_EQ("", test_data2
.init());
392 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
393 ASSERT_EQ(0, test_data
.m_ioctx
.aio_setxattr("foo", my_completion2
.get(), attr1
, bl3
));
396 ASSERT_EQ(0, my_completion2
->wait_for_complete());
398 ASSERT_EQ(0, my_completion2
->get_return_value());
401 AioTestDataPP test_data3
;
402 ASSERT_EQ("", test_data3
.init());
403 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
404 ASSERT_EQ(0, test_data
.m_ioctx
.aio_getxattr("foo", my_completion3
.get(), attr1
, bl4
));
407 ASSERT_EQ(0, my_completion3
->wait_for_complete());
409 ASSERT_EQ((int)sizeof(attr1_buf
), my_completion3
->get_return_value());
410 // check content of attribute
411 ASSERT_EQ(0, memcmp(bl4
.c_str(), attr1_buf
, sizeof(attr1_buf
)));
414 TEST(LibRadosAioPP
, RmXattrPP
) {
416 char attr1
[] = "attr1";
417 char attr1_buf
[] = "foo bar baz";
418 memset(buf
, 0xaa, sizeof(buf
));
420 bl1
.append(buf
, sizeof(buf
));
421 AioTestDataPP test_data
;
422 ASSERT_EQ("", test_data
.init());
423 ASSERT_EQ(0, test_data
.m_ioctx
.append("foo", bl1
, sizeof(buf
)));
426 bl2
.append(attr1_buf
, sizeof(attr1_buf
));
427 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
428 ASSERT_EQ(0, test_data
.m_ioctx
.aio_setxattr("foo", my_completion
.get(), attr1
, bl2
));
431 ASSERT_EQ(0, my_completion
->wait_for_complete());
433 ASSERT_EQ(0, my_completion
->get_return_value());
435 AioTestDataPP test_data2
;
436 ASSERT_EQ("", test_data2
.init());
437 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
438 ASSERT_EQ(0, test_data
.m_ioctx
.aio_rmxattr("foo", my_completion2
.get(), attr1
));
441 ASSERT_EQ(0, my_completion2
->wait_for_complete());
443 ASSERT_EQ(0, my_completion2
->get_return_value());
445 AioTestDataPP test_data3
;
446 ASSERT_EQ("", test_data3
.init());
447 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
449 ASSERT_EQ(0, test_data
.m_ioctx
.aio_getxattr("foo", my_completion3
.get(), attr1
, bl3
));
452 ASSERT_EQ(0, my_completion3
->wait_for_complete());
454 ASSERT_EQ(-ENODATA
, my_completion3
->get_return_value());
455 // Test rmxattr on a removed object
457 char attr2
[] = "attr2";
458 char attr2_buf
[] = "foo bar baz";
459 memset(buf2
, 0xbb, sizeof(buf2
));
461 bl21
.append(buf
, sizeof(buf
));
462 ASSERT_EQ(0, test_data
.m_ioctx
.write("foo_rmxattr", bl21
, sizeof(buf2
), 0));
464 bl22
.append(attr2_buf
, sizeof(attr2_buf
));
466 AioTestDataPP test_data4
;
467 ASSERT_EQ("", test_data4
.init());
468 auto my_completion4
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
469 ASSERT_EQ(0, test_data
.m_ioctx
.aio_setxattr("foo_rmxattr", my_completion4
.get(), attr2
, bl22
));
472 ASSERT_EQ(0, my_completion4
->wait_for_complete());
474 ASSERT_EQ(0, my_completion4
->get_return_value());
476 ASSERT_EQ(0, test_data
.m_ioctx
.remove("foo_rmxattr"));
477 // async rmxattr on non existing object
478 AioTestDataPP test_data5
;
479 ASSERT_EQ("", test_data5
.init());
480 auto my_completion5
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
481 ASSERT_EQ(0, test_data
.m_ioctx
.aio_rmxattr("foo_rmxattr", my_completion5
.get(), attr2
));
484 ASSERT_EQ(0, my_completion5
->wait_for_complete());
486 ASSERT_EQ(-ENOENT
, my_completion5
->get_return_value());
489 TEST(LibRadosIoPP
, XattrListPP
) {
490 AioTestDataPP test_data
;
491 ASSERT_EQ("", test_data
.init());
492 // create an object with 2 attributes
494 char attr1
[] = "attr1";
495 char attr1_buf
[] = "foo bar baz";
496 char attr2
[] = "attr2";
498 for (size_t j
= 0; j
< sizeof(attr2_buf
); ++j
) {
499 attr2_buf
[j
] = j
% 0xff;
501 memset(buf
, 0xaa, sizeof(buf
));
503 bl1
.append(buf
, sizeof(buf
));
504 ASSERT_EQ(0, test_data
.m_ioctx
.append("foo", bl1
, sizeof(buf
)));
506 bl2
.append(attr1_buf
, sizeof(attr1_buf
));
507 ASSERT_EQ(0, test_data
.m_ioctx
.setxattr("foo", attr1
, bl2
));
509 bl3
.append(attr2_buf
, sizeof(attr2_buf
));
510 ASSERT_EQ(0, test_data
.m_ioctx
.setxattr("foo", attr2
, bl3
));
511 // call async version of getxattrs
512 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
513 std::map
<std::string
, bufferlist
> attrset
;
514 ASSERT_EQ(0, test_data
.m_ioctx
.aio_getxattrs("foo", my_completion
.get(), attrset
));
517 ASSERT_EQ(0, my_completion
->wait_for_complete());
519 ASSERT_EQ(0, my_completion
->get_return_value());
520 for (std::map
<std::string
, bufferlist
>::iterator i
= attrset
.begin();
521 i
!= attrset
.end(); ++i
) {
522 if (i
->first
== string(attr1
)) {
523 ASSERT_EQ(0, memcmp(i
->second
.c_str(), attr1_buf
, sizeof(attr1_buf
)));
525 else if (i
->first
== string(attr2
)) {
526 ASSERT_EQ(0, memcmp(i
->second
.c_str(), attr2_buf
, sizeof(attr2_buf
)));
534 TEST(LibRadosAio
, IsCompletePP
) {
535 AioTestDataPP test_data
;
536 ASSERT_EQ("", test_data
.init());
537 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
538 ASSERT_TRUE(my_completion
);
540 memset(buf
, 0xcc, sizeof(buf
));
542 bl1
.append(buf
, sizeof(buf
));
543 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
544 bl1
, sizeof(buf
), 0));
547 ASSERT_EQ(0, my_completion
->wait_for_complete());
549 ASSERT_EQ(0, my_completion
->get_return_value());
551 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
552 ASSERT_TRUE(my_completion2
);
553 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
554 &bl2
, sizeof(buf
), 0));
558 // Busy-wait until the AIO completes.
559 // Normally we wouldn't do this, but we want to test is_complete.
561 int is_complete
= my_completion2
->is_complete();
566 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
567 ASSERT_EQ(sizeof(buf
), bl2
.length());
568 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
571 TEST(LibRadosAio
, IsSafePP
) {
572 AioTestDataPP test_data
;
573 ASSERT_EQ("", test_data
.init());
574 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
575 ASSERT_TRUE(my_completion
);
577 memset(buf
, 0xcc, sizeof(buf
));
579 bl1
.append(buf
, sizeof(buf
));
580 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
581 bl1
, sizeof(buf
), 0));
585 // Busy-wait until the AIO completes.
586 // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
588 int is_complete
= my_completion
->is_complete();
593 ASSERT_EQ(0, my_completion
->get_return_value());
594 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
596 ASSERT_TRUE(my_completion2
);
597 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
598 &bl2
, sizeof(buf
), 0));
601 ASSERT_EQ(0, my_completion2
->wait_for_complete());
603 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
604 ASSERT_EQ(sizeof(buf
), bl2
.length());
605 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
608 TEST(LibRadosAio
, ReturnValuePP
) {
609 AioTestDataPP test_data
;
610 ASSERT_EQ("", test_data
.init());
611 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
612 ASSERT_TRUE(my_completion
);
614 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("nonexistent", my_completion
.get(),
618 ASSERT_EQ(0, my_completion
->wait_for_complete());
620 ASSERT_EQ(-ENOENT
, my_completion
->get_return_value());
623 TEST(LibRadosAio
, FlushPP
) {
624 AioTestDataPP test_data
;
625 ASSERT_EQ("", test_data
.init());
626 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
627 ASSERT_TRUE(my_completion
);
629 memset(buf
, 0xee, sizeof(buf
));
631 bl1
.append(buf
, sizeof(buf
));
632 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
633 bl1
, sizeof(buf
), 0));
634 ASSERT_EQ(0, test_data
.m_ioctx
.aio_flush());
635 ASSERT_EQ(0, my_completion
->get_return_value());
637 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
638 ASSERT_TRUE(my_completion2
);
639 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
640 &bl2
, sizeof(buf
), 0));
643 ASSERT_EQ(0, my_completion2
->wait_for_complete());
645 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
646 ASSERT_EQ(sizeof(buf
), bl2
.length());
647 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
650 TEST(LibRadosAio
, FlushAsyncPP
) {
651 AioTestDataPP test_data
;
652 ASSERT_EQ("", test_data
.init());
653 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
654 auto flush_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
655 ASSERT_TRUE(my_completion
);
657 memset(buf
, 0xee, sizeof(buf
));
659 bl1
.append(buf
, sizeof(buf
));
660 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
661 bl1
, sizeof(buf
), 0));
662 ASSERT_EQ(0, test_data
.m_ioctx
.aio_flush_async(flush_completion
.get()));
665 ASSERT_EQ(0, flush_completion
->wait_for_complete());
667 ASSERT_EQ(1, my_completion
->is_complete());
668 ASSERT_EQ(1, flush_completion
->is_complete());
669 ASSERT_EQ(0, my_completion
->get_return_value());
671 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
672 ASSERT_TRUE(my_completion2
);
673 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
674 &bl2
, sizeof(buf
), 0));
677 ASSERT_EQ(0, my_completion2
->wait_for_complete());
679 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
680 ASSERT_EQ(sizeof(buf
), bl2
.length());
681 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
684 TEST(LibRadosAio
, RoundTripWriteFullPP
) {
685 AioTestDataPP test_data
;
686 ASSERT_EQ("", test_data
.init());
687 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
688 ASSERT_TRUE(my_completion
);
690 memset(buf
, 0xcc, sizeof(buf
));
692 bl1
.append(buf
, sizeof(buf
));
693 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
694 bl1
, sizeof(buf
), 0));
697 ASSERT_EQ(0, my_completion
->wait_for_complete());
699 ASSERT_EQ(0, my_completion
->get_return_value());
701 memset(buf2
, 0xdd, sizeof(buf2
));
703 bl2
.append(buf2
, sizeof(buf2
));
704 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
705 ASSERT_TRUE(my_completion2
);
706 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write_full("foo", my_completion2
.get(), bl2
));
709 ASSERT_EQ(0, my_completion2
->wait_for_complete());
711 ASSERT_EQ(0, my_completion2
->get_return_value());
713 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
714 ASSERT_TRUE(my_completion3
);
715 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion3
.get(),
716 &bl3
, sizeof(buf
), 0));
719 ASSERT_EQ(0, my_completion3
->wait_for_complete());
721 ASSERT_EQ((int)sizeof(buf2
), my_completion3
->get_return_value());
722 ASSERT_EQ(sizeof(buf2
), bl3
.length());
723 ASSERT_EQ(0, memcmp(bl3
.c_str(), buf2
, sizeof(buf2
)));
726 //using ObjectWriteOperation/ObjectReadOperation with iohint
727 TEST(LibRadosAio
, RoundTripWriteFullPP2
)
730 std::string pool_name
= get_temp_pool_name();
731 ASSERT_EQ("", create_one_pool_pp(pool_name
, cluster
));
733 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
735 auto my_completion1
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
736 ObjectWriteOperation op
;
738 memset(buf
, 0xcc, sizeof(buf
));
743 op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
744 ioctx
.aio_operate("test_obj", my_completion1
.get(), &op
);
747 ASSERT_EQ(0, my_completion1
->wait_for_complete());
749 EXPECT_EQ(0, my_completion1
->get_return_value());
751 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
753 ObjectReadOperation op1
;
754 op1
.read(0, sizeof(buf
), &bl
, NULL
);
755 op1
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
|LIBRADOS_OP_FLAG_FADVISE_RANDOM
);
756 ioctx
.aio_operate("test_obj", my_completion2
.get(), &op1
, 0);
759 ASSERT_EQ(0, my_completion2
->wait_for_complete());
761 EXPECT_EQ(0, my_completion2
->get_return_value());
762 ASSERT_EQ(0, memcmp(buf
, bl
.c_str(), sizeof(buf
)));
764 ioctx
.remove("test_obj");
765 destroy_one_pool_pp(pool_name
, cluster
);
768 TEST(LibRadosAio
, RoundTripWriteSamePP
) {
769 AioTestDataPP test_data
;
770 ASSERT_EQ("", test_data
.init());
771 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
772 ASSERT_TRUE(my_completion
);
774 memset(full
, 0xcc, sizeof(full
));
776 bl1
.append(full
, sizeof(full
));
777 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
778 bl1
, sizeof(full
), 0));
781 ASSERT_EQ(0, my_completion
->wait_for_complete());
783 ASSERT_EQ(0, my_completion
->get_return_value());
784 /* write the same buf four times */
786 size_t ws_write_len
= sizeof(full
);
787 memset(buf
, 0xdd, sizeof(buf
));
789 bl2
.append(buf
, sizeof(buf
));
790 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
791 ASSERT_TRUE(my_completion2
);
792 ASSERT_EQ(0, test_data
.m_ioctx
.aio_writesame("foo", my_completion2
.get(), bl2
,
796 ASSERT_EQ(0, my_completion2
->wait_for_complete());
798 ASSERT_EQ(0, my_completion2
->get_return_value());
800 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
801 ASSERT_TRUE(my_completion3
);
802 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion3
.get(),
803 &bl3
, sizeof(full
), 0));
806 ASSERT_EQ(0, my_completion3
->wait_for_complete());
808 ASSERT_EQ((int)sizeof(full
), my_completion3
->get_return_value());
809 ASSERT_EQ(sizeof(full
), bl3
.length());
810 for (char *cmp
= bl3
.c_str(); cmp
< bl3
.c_str() + bl3
.length();
811 cmp
+= sizeof(buf
)) {
812 ASSERT_EQ(0, memcmp(cmp
, buf
, sizeof(buf
)));
816 TEST(LibRadosAio
, RoundTripWriteSamePP2
)
819 std::string pool_name
= get_temp_pool_name();
820 ASSERT_EQ("", create_one_pool_pp(pool_name
, cluster
));
822 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
824 auto wr_cmpl
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
825 ObjectWriteOperation op
;
827 memset(buf
, 0xcc, sizeof(buf
));
829 bl
.append(buf
, sizeof(buf
));
831 op
.writesame(0, sizeof(buf
) * 4, bl
);
832 op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
833 ioctx
.aio_operate("test_obj", wr_cmpl
.get(), &op
);
836 ASSERT_EQ(0, wr_cmpl
->wait_for_complete());
838 EXPECT_EQ(0, wr_cmpl
->get_return_value());
840 boost::scoped_ptr
<AioCompletion
>
841 rd_cmpl(cluster
.aio_create_completion(0, 0));
843 char full
[sizeof(buf
) * 4];
844 memset(full
, 0, sizeof(full
));
846 fl
.append(full
, sizeof(full
));
847 ObjectReadOperation op1
;
848 op1
.read(0, sizeof(full
), &fl
, NULL
);
849 op1
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
850 ioctx
.aio_operate("test_obj", rd_cmpl
.get(), &op1
, 0);
853 ASSERT_EQ(0, rd_cmpl
->wait_for_complete());
855 EXPECT_EQ(0, rd_cmpl
->get_return_value());
856 for (cmp
= fl
.c_str(); cmp
< fl
.c_str() + fl
.length(); cmp
+= sizeof(buf
)) {
857 ASSERT_EQ(0, memcmp(cmp
, buf
, sizeof(buf
)));
860 ioctx
.remove("test_obj");
861 destroy_one_pool_pp(pool_name
, cluster
);
864 TEST(LibRadosAio
, SimpleStatPPNS
) {
865 AioTestDataPP test_data
;
866 ASSERT_EQ("", test_data
.init());
867 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
868 ASSERT_TRUE(my_completion
);
870 memset(buf
, 0xcc, sizeof(buf
));
872 bl1
.append(buf
, sizeof(buf
));
873 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
874 bl1
, sizeof(buf
), 0));
877 ASSERT_EQ(0, my_completion
->wait_for_complete());
879 ASSERT_EQ(0, my_completion
->get_return_value());
882 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
883 ASSERT_TRUE(my_completion2
);
884 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion2
.get(),
888 ASSERT_EQ(0, my_completion2
->wait_for_complete());
890 ASSERT_EQ(0, my_completion2
->get_return_value());
891 ASSERT_EQ(sizeof(buf
), psize
);
894 TEST(LibRadosAio
, SimpleStatPP
) {
895 AioTestDataPP test_data
;
896 ASSERT_EQ("", test_data
.init());
897 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
898 ASSERT_TRUE(my_completion
);
900 memset(buf
, 0xcc, sizeof(buf
));
902 bl1
.append(buf
, sizeof(buf
));
903 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
904 bl1
, sizeof(buf
), 0));
907 ASSERT_EQ(0, my_completion
->wait_for_complete());
909 ASSERT_EQ(0, my_completion
->get_return_value());
912 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
913 ASSERT_TRUE(my_completion2
);
914 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion2
.get(),
918 ASSERT_EQ(0, my_completion2
->wait_for_complete());
920 ASSERT_EQ(0, my_completion2
->get_return_value());
921 ASSERT_EQ(sizeof(buf
), psize
);
924 TEST(LibRadosAio
, StatRemovePP
) {
925 AioTestDataPP test_data
;
926 ASSERT_EQ("", test_data
.init());
927 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
928 ASSERT_TRUE(my_completion
);
930 memset(buf
, 0xcc, sizeof(buf
));
932 bl1
.append(buf
, sizeof(buf
));
933 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
934 bl1
, sizeof(buf
), 0));
937 ASSERT_EQ(0, my_completion
->wait_for_complete());
939 ASSERT_EQ(0, my_completion
->get_return_value());
942 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
943 ASSERT_TRUE(my_completion2
);
944 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion2
.get(),
948 ASSERT_EQ(0, my_completion2
->wait_for_complete());
950 ASSERT_EQ(0, my_completion2
->get_return_value());
951 ASSERT_EQ(sizeof(buf
), psize
);
954 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
955 ASSERT_TRUE(my_completion3
);
956 ASSERT_EQ(0, test_data
.m_ioctx
.aio_remove("foo", my_completion3
.get()));
959 ASSERT_EQ(0, my_completion3
->wait_for_complete());
961 ASSERT_EQ(0, my_completion3
->get_return_value());
963 auto my_completion4
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
964 ASSERT_TRUE(my_completion4
);
965 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion4
.get(),
969 ASSERT_EQ(0, my_completion4
->wait_for_complete());
971 ASSERT_EQ(-ENOENT
, my_completion4
->get_return_value());
974 TEST(LibRadosAio
, ExecuteClassPP
) {
975 AioTestDataPP test_data
;
976 ASSERT_EQ("", test_data
.init());
977 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
978 ASSERT_TRUE(my_completion
);
980 memset(buf
, 0xcc, sizeof(buf
));
982 bl1
.append(buf
, sizeof(buf
));
983 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
984 bl1
, sizeof(buf
), 0));
987 ASSERT_EQ(0, my_completion
->wait_for_complete());
989 ASSERT_EQ(0, my_completion
->get_return_value());
990 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
991 ASSERT_TRUE(my_completion2
);
993 ASSERT_EQ(0, test_data
.m_ioctx
.aio_exec("foo", my_completion2
.get(),
994 "hello", "say_hello", in
, &out
));
997 ASSERT_EQ(0, my_completion2
->wait_for_complete());
999 ASSERT_EQ(0, my_completion2
->get_return_value());
1000 ASSERT_EQ(std::string("Hello, world!"), std::string(out
.c_str(), out
.length()));
1007 TEST(LibRadosAio
, OmapPP
) {
1009 std::string pool_name
= get_temp_pool_name();
1010 ASSERT_EQ("", create_one_pool_pp(pool_name
, cluster
));
1012 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
1014 string header_str
= "baz";
1015 bufferptr
bp(header_str
.c_str(), header_str
.size() + 1);
1016 bufferlist header_to_set
;
1017 header_to_set
.push_back(bp
);
1018 map
<string
, bufferlist
> to_set
;
1020 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1021 ObjectWriteOperation op
;
1022 to_set
["foo"] = header_to_set
;
1023 to_set
["foo2"] = header_to_set
;
1024 to_set
["qfoo3"] = header_to_set
;
1025 op
.omap_set(to_set
);
1027 op
.omap_set_header(header_to_set
);
1029 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
);
1032 ASSERT_EQ(0, my_completion
->wait_for_complete());
1034 EXPECT_EQ(0, my_completion
->get_return_value());
1038 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1039 ObjectReadOperation op
;
1040 map
<string
, pair
<bufferlist
, int> > assertions
;
1042 val
.append(string("bar"));
1043 assertions
["foo"] = pair
<bufferlist
, int>(val
, CEPH_OSD_CMPXATTR_OP_EQ
);
1046 op
.omap_cmp(assertions
, &r
);
1048 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
, 0);
1051 ASSERT_EQ(0, my_completion
->wait_for_complete());
1053 EXPECT_EQ(-ECANCELED
, my_completion
->get_return_value());
1054 ASSERT_EQ(-ECANCELED
, r
);
1058 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1059 ObjectReadOperation op
;
1061 set
<string
> set_got
;
1062 map
<string
, bufferlist
> map_got
;
1065 map
<string
, bufferlist
> got3
;
1067 map
<string
, bufferlist
> got4
;
1071 op
.omap_get_keys2("", 1, &set_got
, nullptr, 0);
1072 op
.omap_get_vals2("foo", 1, &map_got
, nullptr, 0);
1074 to_get
.insert("foo");
1075 to_get
.insert("qfoo3");
1076 op
.omap_get_vals_by_keys(to_get
, &got3
, 0);
1078 op
.omap_get_header(&header
, 0);
1080 op
.omap_get_vals2("foo2", "q", 1, &got4
, nullptr, 0);
1082 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
, 0);
1085 ASSERT_EQ(0, my_completion
->wait_for_complete());
1087 EXPECT_EQ(0, my_completion
->get_return_value());
1089 ASSERT_EQ(header
.length(), header_to_set
.length());
1090 ASSERT_EQ(set_got
.size(), (unsigned)1);
1091 ASSERT_EQ(*set_got
.begin(), "foo");
1092 ASSERT_EQ(map_got
.size(), (unsigned)1);
1093 ASSERT_EQ(map_got
.begin()->first
, "foo2");
1094 ASSERT_EQ(got3
.size(), (unsigned)2);
1095 ASSERT_EQ(got3
.begin()->first
, "foo");
1096 ASSERT_EQ(got3
.rbegin()->first
, "qfoo3");
1097 ASSERT_EQ(got4
.size(), (unsigned)1);
1098 ASSERT_EQ(got4
.begin()->first
, "qfoo3");
1102 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1103 ObjectWriteOperation op
;
1104 set
<string
> to_remove
;
1105 to_remove
.insert("foo2");
1106 op
.omap_rm_keys(to_remove
);
1107 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
);
1110 ASSERT_EQ(0, my_completion
->wait_for_complete());
1112 EXPECT_EQ(0, my_completion
->get_return_value());
1116 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1117 ObjectReadOperation op
;
1119 set
<string
> set_got
;
1120 op
.omap_get_keys2("", -1, &set_got
, nullptr, 0);
1121 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
, 0);
1124 ASSERT_EQ(0, my_completion
->wait_for_complete());
1126 EXPECT_EQ(0, my_completion
->get_return_value());
1127 ASSERT_EQ(set_got
.size(), (unsigned)2);
1131 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1132 ObjectWriteOperation op
;
1134 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
);
1137 ASSERT_EQ(0, my_completion
->wait_for_complete());
1139 EXPECT_EQ(0, my_completion
->get_return_value());
1143 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1144 ObjectReadOperation op
;
1146 set
<string
> set_got
;
1147 op
.omap_get_keys2("", -1, &set_got
, nullptr, 0);
1148 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
, 0);
1151 ASSERT_EQ(0, my_completion
->wait_for_complete());
1153 EXPECT_EQ(0, my_completion
->get_return_value());
1154 ASSERT_EQ(set_got
.size(), (unsigned)0);
1157 // omap_clear clears header *and* keys
1159 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1160 ObjectWriteOperation op
;
1162 bl
.append("some data");
1163 map
<string
,bufferlist
> to_set
;
1165 to_set
["foo2"] = bl
;
1166 to_set
["qfoo3"] = bl
;
1167 op
.omap_set(to_set
);
1168 op
.omap_set_header(bl
);
1169 ioctx
.aio_operate("foo3", my_completion
.get(), &op
);
1172 ASSERT_EQ(0, my_completion
->wait_for_complete());
1174 EXPECT_EQ(0, my_completion
->get_return_value());
1177 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1178 ObjectWriteOperation op
;
1180 ioctx
.aio_operate("foo3", my_completion
.get(), &op
);
1183 ASSERT_EQ(0, my_completion
->wait_for_complete());
1185 EXPECT_EQ(0, my_completion
->get_return_value());
1188 boost::scoped_ptr
<AioCompletion
> my_completion(cluster
.aio_create_completion(0, 0));
1189 ObjectReadOperation op
;
1190 set
<string
> set_got
;
1192 op
.omap_get_keys2("", -1, &set_got
, nullptr, 0);
1193 op
.omap_get_header(&hdr
, NULL
);
1194 ioctx
.aio_operate("foo3", my_completion
.get(), &op
, 0);
1197 ASSERT_EQ(0, my_completion
->wait_for_complete());
1199 EXPECT_EQ(0, my_completion
->get_return_value());
1200 ASSERT_EQ(set_got
.size(), (unsigned)0);
1201 ASSERT_EQ(hdr
.length(), 0u);
1204 ioctx
.remove("test_obj");
1205 destroy_one_pool_pp(pool_name
, cluster
);
1208 TEST(LibRadosAio
, MultiWritePP
) {
1209 AioTestDataPP test_data
;
1210 ASSERT_EQ("", test_data
.init());
1211 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1212 ASSERT_TRUE(my_completion
);
1214 memset(buf
, 0xcc, sizeof(buf
));
1216 bl1
.append(buf
, sizeof(buf
));
1217 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1218 bl1
, sizeof(buf
), 0));
1221 ASSERT_EQ(0, my_completion
->wait_for_complete());
1223 ASSERT_EQ(0, my_completion
->get_return_value());
1226 memset(buf2
, 0xdd, sizeof(buf2
));
1228 bl2
.append(buf2
, sizeof(buf2
));
1229 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1230 ASSERT_TRUE(my_completion2
);
1231 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion2
.get(),
1232 bl2
, sizeof(buf2
), sizeof(buf
)));
1235 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1237 ASSERT_EQ(0, my_completion2
->get_return_value());
1240 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1241 ASSERT_TRUE(my_completion3
);
1242 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion3
.get(),
1243 &bl3
, (sizeof(buf
) + sizeof(buf2
) * 3), 0));
1246 ASSERT_EQ(0, my_completion3
->wait_for_complete());
1248 ASSERT_EQ((int)(sizeof(buf
) + sizeof(buf2
)), my_completion3
->get_return_value());
1249 ASSERT_EQ(sizeof(buf
) + sizeof(buf2
), bl3
.length());
1250 ASSERT_EQ(0, memcmp(bl3
.c_str(), buf
, sizeof(buf
)));
1251 ASSERT_EQ(0, memcmp(bl3
.c_str() + sizeof(buf
), buf2
, sizeof(buf2
)));
1254 TEST(LibRadosAio
, AioUnlockPP
) {
1255 AioTestDataPP test_data
;
1256 ASSERT_EQ("", test_data
.init());
1257 ASSERT_EQ(0, test_data
.m_ioctx
.lock_exclusive("foo", "TestLock", "Cookie", "", NULL
, 0));
1258 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1259 ASSERT_EQ(0, test_data
.m_ioctx
.aio_unlock("foo", "TestLock", "Cookie", my_completion
.get()));
1262 ASSERT_EQ(0, my_completion
->wait_for_complete());
1264 ASSERT_EQ(0, my_completion
->get_return_value());
1266 ASSERT_EQ(0, test_data
.m_ioctx
.lock_exclusive("foo", "TestLock", "Cookie", "", NULL
, 0));
1269 class AioTestDataECPP
1280 destroy_one_ec_pool_pp(m_pool_name
, m_cluster
);
1287 m_pool_name
= get_temp_pool_name();
1288 std::string err
= create_one_ec_pool_pp(m_pool_name
, m_cluster
);
1291 oss
<< "create_one_ec_pool(" << m_pool_name
<< ") failed: error " << err
;
1294 ret
= m_cluster
.ioctx_create(m_pool_name
.c_str(), m_ioctx
);
1296 destroy_one_ec_pool_pp(m_pool_name
, m_cluster
);
1298 oss
<< "rados_ioctx_create failed: error " << ret
;
1307 std::string m_pool_name
;
1312 TEST(LibRadosAioEC
, SimpleWritePP
) {
1314 memset(buf
, 0xcc, sizeof(buf
));
1316 bl1
.append(buf
, sizeof(buf
));
1318 AioTestDataECPP test_data
;
1319 ASSERT_EQ("", test_data
.init());
1320 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1321 ASSERT_TRUE(my_completion
);
1322 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1323 bl1
, sizeof(buf
), 0));
1326 ASSERT_EQ(0, my_completion
->wait_for_complete());
1328 ASSERT_EQ(0, my_completion
->get_return_value());
1332 AioTestDataECPP test_data
;
1333 ASSERT_EQ("", test_data
.init());
1334 test_data
.m_ioctx
.set_namespace("nspace");
1335 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1336 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1337 bl1
, sizeof(buf
), 0));
1340 ASSERT_EQ(0, my_completion
->wait_for_complete());
1342 ASSERT_EQ(0, my_completion
->get_return_value());
1346 TEST(LibRadosAioEC
, WaitForSafePP
) {
1347 AioTestDataECPP test_data
;
1348 ASSERT_EQ("", test_data
.init());
1349 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1350 ASSERT_TRUE(my_completion
);
1352 memset(buf
, 0xcc, sizeof(buf
));
1354 bl1
.append(buf
, sizeof(buf
));
1355 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1356 bl1
, sizeof(buf
), 0));
1358 ASSERT_EQ(0, my_completion
->wait_for_complete());
1359 ASSERT_EQ(0, my_completion
->get_return_value());
1362 TEST(LibRadosAioEC
, RoundTripPP
) {
1363 AioTestDataECPP test_data
;
1364 ASSERT_EQ("", test_data
.init());
1365 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1366 ASSERT_TRUE(my_completion
);
1368 memset(buf
, 0xcc, sizeof(buf
));
1370 bl1
.append(buf
, sizeof(buf
));
1371 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1372 bl1
, sizeof(buf
), 0));
1375 ASSERT_EQ(0, my_completion
->wait_for_complete());
1377 ASSERT_EQ(0, my_completion
->get_return_value());
1379 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1380 ASSERT_TRUE(my_completion2
);
1381 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
1382 &bl2
, sizeof(buf
), 0));
1385 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1387 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
1388 ASSERT_EQ(sizeof(buf
), bl2
.length());
1389 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
1392 TEST(LibRadosAioEC
, RoundTripPP2
) {
1393 AioTestDataECPP test_data
;
1394 ASSERT_EQ("", test_data
.init());
1395 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1396 ASSERT_TRUE(my_completion
);
1398 memset(buf
, 0xcc, sizeof(buf
));
1400 bl1
.append(buf
, sizeof(buf
));
1401 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1402 bl1
, sizeof(buf
), 0));
1405 ASSERT_EQ(0, my_completion
->wait_for_complete());
1407 ASSERT_EQ(0, my_completion
->get_return_value());
1409 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1410 ASSERT_TRUE(my_completion2
);
1411 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
1412 &bl2
, sizeof(buf
), 0));
1415 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1417 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
1418 ASSERT_EQ(sizeof(buf
), bl2
.length());
1419 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
1422 //using ObjectWriteOperation/ObjectReadOperation with iohint
1423 TEST(LibRadosAioEC
, RoundTripPP3
)
1426 std::string pool_name
= get_temp_pool_name();
1427 ASSERT_EQ("", create_one_pool_pp(pool_name
, cluster
));
1429 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
1431 auto my_completion1
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};;
1432 ObjectWriteOperation op
;
1434 memset(buf
, 0xcc, sizeof(buf
));
1439 op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1440 ioctx
.aio_operate("test_obj", my_completion1
.get(), &op
);
1443 ASSERT_EQ(0, my_completion1
->wait_for_complete());
1445 EXPECT_EQ(0, my_completion1
->get_return_value());
1447 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1449 ObjectReadOperation op1
;
1450 op1
.read(0, sizeof(buf
), &bl
, NULL
);
1451 op1
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
|LIBRADOS_OP_FLAG_FADVISE_RANDOM
);
1452 ioctx
.aio_operate("test_obj", my_completion2
.get(), &op1
, 0);
1455 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1457 EXPECT_EQ(0, my_completion2
->get_return_value());
1458 ASSERT_EQ(0, memcmp(buf
, bl
.c_str(), sizeof(buf
)));
1460 ioctx
.remove("test_obj");
1461 destroy_one_pool_pp(pool_name
, cluster
);
1464 TEST(LibRadosAio
, RoundTripAppendPP
) {
1465 AioTestDataPP test_data
;
1466 ASSERT_EQ("", test_data
.init());
1467 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1468 ASSERT_TRUE(my_completion
);
1470 memset(buf
, 0xcc, sizeof(buf
));
1472 bl1
.append(buf
, sizeof(buf
));
1473 ASSERT_EQ(0, test_data
.m_ioctx
.aio_append("foo", my_completion
.get(),
1477 ASSERT_EQ(0, my_completion
->wait_for_complete());
1479 ASSERT_EQ(0, my_completion
->get_return_value());
1481 memset(buf2
, 0xdd, sizeof(buf2
));
1483 bl2
.append(buf2
, sizeof(buf2
));
1484 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1485 ASSERT_TRUE(my_completion2
);
1486 ASSERT_EQ(0, test_data
.m_ioctx
.aio_append("foo", my_completion2
.get(),
1487 bl2
, sizeof(buf2
)));
1490 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1492 ASSERT_EQ(0, my_completion2
->get_return_value());
1494 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1495 ASSERT_TRUE(my_completion3
);
1496 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion3
.get(),
1497 &bl3
, 2 * sizeof(buf
), 0));
1500 ASSERT_EQ(0, my_completion3
->wait_for_complete());
1502 ASSERT_EQ((int)(sizeof(buf
) * 2), my_completion3
->get_return_value());
1503 ASSERT_EQ(sizeof(buf
) * 2, bl3
.length());
1504 ASSERT_EQ(0, memcmp(bl3
.c_str(), buf
, sizeof(buf
)));
1505 ASSERT_EQ(0, memcmp(bl3
.c_str() + sizeof(buf
), buf2
, sizeof(buf2
)));
1508 TEST(LibRadosAioPP
, RemoveTestPP
) {
1510 memset(buf
, 0xaa, sizeof(buf
));
1512 bl1
.append(buf
, sizeof(buf
));
1513 AioTestDataPP test_data
;
1514 ASSERT_EQ("", test_data
.init());
1515 ASSERT_EQ(0, test_data
.m_ioctx
.append("foo", bl1
, sizeof(buf
)));
1516 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1517 ASSERT_EQ(0, test_data
.m_ioctx
.aio_remove("foo", my_completion
.get()));
1520 ASSERT_EQ(0, my_completion
->wait_for_complete());
1522 ASSERT_EQ(0, my_completion
->get_return_value());
1524 ASSERT_EQ(-ENOENT
, test_data
.m_ioctx
.read("foo", bl2
, sizeof(buf
), 0));
1527 TEST(LibRadosAioEC
, RoundTripSparseReadPP
) {
1528 AioTestDataECPP test_data
;
1529 ASSERT_EQ("", test_data
.init());
1530 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1531 ASSERT_TRUE(my_completion
);
1533 memset(buf
, 0xcc, sizeof(buf
));
1535 bl1
.append(buf
, sizeof(buf
));
1536 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1537 bl1
, sizeof(buf
), 0));
1540 ASSERT_EQ(0, my_completion
->wait_for_complete());
1542 ASSERT_EQ(0, my_completion
->get_return_value());
1544 map
<uint64_t, uint64_t> extents
;
1546 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1547 ASSERT_TRUE(my_completion2
);
1548 ASSERT_EQ(0, test_data
.m_ioctx
.aio_sparse_read("foo", my_completion2
.get(),
1549 &extents
, &bl2
, sizeof(buf
), 0));
1552 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1554 ASSERT_EQ(0, my_completion2
->get_return_value());
1555 assert_eq_sparse(bl1
, extents
, bl2
);
1558 TEST(LibRadosAioEC
, RoundTripAppendPP
) {
1559 AioTestDataECPP test_data
;
1560 ASSERT_EQ("", test_data
.init());
1561 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1562 ASSERT_TRUE(my_completion
);
1564 ASSERT_EQ(0, test_data
.m_ioctx
.pool_requires_alignment2(&requires
));
1565 ASSERT_TRUE(requires
);
1567 ASSERT_EQ(0, test_data
.m_ioctx
.pool_required_alignment2(&alignment
));
1568 ASSERT_NE((unsigned)0, alignment
);
1569 int bsize
= alignment
;
1570 char *buf
= (char *)new char[bsize
];
1571 memset(buf
, 0xcc, bsize
);
1573 bl1
.append(buf
, bsize
);
1574 ASSERT_EQ(0, test_data
.m_ioctx
.aio_append("foo", my_completion
.get(),
1578 ASSERT_EQ(0, my_completion
->wait_for_complete());
1580 ASSERT_EQ(0, my_completion
->get_return_value());
1582 int hbsize
= bsize
/ 2;
1583 char *buf2
= (char *)new char[hbsize
];
1584 memset(buf2
, 0xdd, hbsize
);
1586 bl2
.append(buf2
, hbsize
);
1587 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1588 ASSERT_TRUE(my_completion2
);
1589 ASSERT_EQ(0, test_data
.m_ioctx
.aio_append("foo", my_completion2
.get(),
1593 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1595 ASSERT_EQ(0, my_completion2
->get_return_value());
1597 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1598 ASSERT_TRUE(my_completion3
);
1599 ASSERT_EQ(0, test_data
.m_ioctx
.aio_append("foo", my_completion3
.get(),
1603 ASSERT_EQ(0, my_completion3
->wait_for_complete());
1605 EXPECT_EQ(-EOPNOTSUPP
, my_completion3
->get_return_value());
1608 auto my_completion4
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1609 ASSERT_TRUE(my_completion4
);
1610 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion4
.get(),
1611 &bl3
, bsize
* 3, 0));
1614 ASSERT_EQ(0, my_completion4
->wait_for_complete());
1616 int tbsize
= bsize
+ hbsize
;
1617 ASSERT_EQ(tbsize
, my_completion4
->get_return_value());
1618 ASSERT_EQ((unsigned)tbsize
, bl3
.length());
1619 ASSERT_EQ(0, memcmp(bl3
.c_str(), buf
, bsize
));
1620 ASSERT_EQ(0, memcmp(bl3
.c_str() + bsize
, buf2
, hbsize
));
1625 TEST(LibRadosAioEC
, IsCompletePP
) {
1626 AioTestDataECPP test_data
;
1627 ASSERT_EQ("", test_data
.init());
1628 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1629 ASSERT_TRUE(my_completion
);
1631 memset(buf
, 0xcc, sizeof(buf
));
1633 bl1
.append(buf
, sizeof(buf
));
1634 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1635 bl1
, sizeof(buf
), 0));
1638 ASSERT_EQ(0, my_completion
->wait_for_complete());
1640 ASSERT_EQ(0, my_completion
->get_return_value());
1642 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1643 ASSERT_TRUE(my_completion2
);
1644 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
1645 &bl2
, sizeof(buf
), 0));
1649 // Busy-wait until the AIO completes.
1650 // Normally we wouldn't do this, but we want to test is_complete.
1652 int is_complete
= my_completion2
->is_complete();
1657 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
1658 ASSERT_EQ(sizeof(buf
), bl2
.length());
1659 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
1661 TEST(LibRadosAioEC
, IsSafePP
) {
1662 AioTestDataECPP test_data
;
1663 ASSERT_EQ("", test_data
.init());
1664 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1665 ASSERT_TRUE(my_completion
);
1667 memset(buf
, 0xcc, sizeof(buf
));
1669 bl1
.append(buf
, sizeof(buf
));
1670 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1671 bl1
, sizeof(buf
), 0));
1675 // Busy-wait until the AIO completes.
1676 // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
1678 int is_complete
= my_completion
->is_complete();
1683 ASSERT_EQ(0, my_completion
->get_return_value());
1684 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1686 ASSERT_TRUE(my_completion2
);
1687 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
1688 &bl2
, sizeof(buf
), 0));
1691 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1693 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
1694 ASSERT_EQ(sizeof(buf
), bl2
.length());
1695 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
1698 TEST(LibRadosAioEC
, ReturnValuePP
) {
1699 AioTestDataECPP test_data
;
1700 ASSERT_EQ("", test_data
.init());
1701 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1702 ASSERT_TRUE(my_completion
);
1704 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("nonexistent", my_completion
.get(),
1708 ASSERT_EQ(0, my_completion
->wait_for_complete());
1710 ASSERT_EQ(-ENOENT
, my_completion
->get_return_value());
1713 TEST(LibRadosAioEC
, FlushPP
) {
1714 AioTestDataECPP test_data
;
1715 ASSERT_EQ("", test_data
.init());
1716 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1717 ASSERT_TRUE(my_completion
);
1719 memset(buf
, 0xee, sizeof(buf
));
1721 bl1
.append(buf
, sizeof(buf
));
1722 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1723 bl1
, sizeof(buf
), 0));
1724 ASSERT_EQ(0, test_data
.m_ioctx
.aio_flush());
1725 ASSERT_EQ(0, my_completion
->get_return_value());
1727 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1728 ASSERT_TRUE(my_completion2
);
1729 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
1730 &bl2
, sizeof(buf
), 0));
1733 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1735 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
1736 ASSERT_EQ(sizeof(buf
), bl2
.length());
1737 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
1740 TEST(LibRadosAioEC
, FlushAsyncPP
) {
1741 AioTestDataECPP test_data
;
1742 ASSERT_EQ("", test_data
.init());
1743 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1744 auto flush_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1745 ASSERT_TRUE(my_completion
);
1747 memset(buf
, 0xee, sizeof(buf
));
1749 bl1
.append(buf
, sizeof(buf
));
1750 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1751 bl1
, sizeof(buf
), 0));
1752 ASSERT_EQ(0, test_data
.m_ioctx
.aio_flush_async(flush_completion
.get()));
1755 ASSERT_EQ(0, flush_completion
->wait_for_complete());
1757 ASSERT_EQ(1, my_completion
->is_complete());
1758 ASSERT_EQ(1, flush_completion
->is_complete());
1759 ASSERT_EQ(0, my_completion
->get_return_value());
1761 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1762 ASSERT_TRUE(my_completion2
);
1763 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion2
.get(),
1764 &bl2
, sizeof(buf
), 0));
1767 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1769 ASSERT_EQ((int)sizeof(buf
), my_completion2
->get_return_value());
1770 ASSERT_EQ(sizeof(buf
), bl2
.length());
1771 ASSERT_EQ(0, memcmp(buf
, bl2
.c_str(), sizeof(buf
)));
1774 TEST(LibRadosAioEC
, RoundTripWriteFullPP
) {
1775 AioTestDataECPP test_data
;
1776 ASSERT_EQ("", test_data
.init());
1777 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1778 ASSERT_TRUE(my_completion
);
1780 memset(buf
, 0xcc, sizeof(buf
));
1782 bl1
.append(buf
, sizeof(buf
));
1783 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1784 bl1
, sizeof(buf
), 0));
1787 ASSERT_EQ(0, my_completion
->wait_for_complete());
1789 ASSERT_EQ(0, my_completion
->get_return_value());
1791 memset(buf2
, 0xdd, sizeof(buf2
));
1793 bl2
.append(buf2
, sizeof(buf2
));
1794 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1795 ASSERT_TRUE(my_completion2
);
1796 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write_full("foo", my_completion2
.get(), bl2
));
1799 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1801 ASSERT_EQ(0, my_completion2
->get_return_value());
1803 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1804 ASSERT_TRUE(my_completion3
);
1805 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion3
.get(),
1806 &bl3
, sizeof(buf
), 0));
1809 ASSERT_EQ(0, my_completion3
->wait_for_complete());
1811 ASSERT_EQ((int)sizeof(buf2
), my_completion3
->get_return_value());
1812 ASSERT_EQ(sizeof(buf2
), bl3
.length());
1813 ASSERT_EQ(0, memcmp(bl3
.c_str(), buf2
, sizeof(buf2
)));
1816 //using ObjectWriteOperation/ObjectReadOperation with iohint
1817 TEST(LibRadosAioEC
, RoundTripWriteFullPP2
)
1820 std::string pool_name
= get_temp_pool_name();
1821 ASSERT_EQ("", create_one_pool_pp(pool_name
, cluster
));
1823 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
1825 auto my_completion1
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1826 ObjectWriteOperation op
;
1828 memset(buf
, 0xcc, sizeof(buf
));
1833 op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1834 ioctx
.aio_operate("test_obj", my_completion1
.get(), &op
);
1837 ASSERT_EQ(0, my_completion1
->wait_for_complete());
1839 EXPECT_EQ(0, my_completion1
->get_return_value());
1841 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1843 ObjectReadOperation op1
;
1844 op1
.read(0, sizeof(buf
), &bl
, NULL
);
1845 op1
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE
|LIBRADOS_OP_FLAG_FADVISE_RANDOM
);
1846 ioctx
.aio_operate("test_obj", my_completion2
.get(), &op1
, 0);
1849 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1851 EXPECT_EQ(0, my_completion2
->get_return_value());
1852 ASSERT_EQ(0, memcmp(buf
, bl
.c_str(), sizeof(buf
)));
1854 ioctx
.remove("test_obj");
1855 destroy_one_pool_pp(pool_name
, cluster
);
1858 TEST(LibRadosAioEC
, SimpleStatPP
) {
1859 AioTestDataECPP test_data
;
1860 ASSERT_EQ("", test_data
.init());
1861 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1862 ASSERT_TRUE(my_completion
);
1864 memset(buf
, 0xcc, sizeof(buf
));
1866 bl1
.append(buf
, sizeof(buf
));
1867 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1868 bl1
, sizeof(buf
), 0));
1871 ASSERT_EQ(0, my_completion
->wait_for_complete());
1873 ASSERT_EQ(0, my_completion
->get_return_value());
1876 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1877 ASSERT_TRUE(my_completion2
);
1878 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion2
.get(),
1882 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1884 ASSERT_EQ(0, my_completion2
->get_return_value());
1885 ASSERT_EQ(sizeof(buf
), psize
);
1888 TEST(LibRadosAioEC
, SimpleStatPPNS
) {
1889 AioTestDataECPP test_data
;
1890 ASSERT_EQ("", test_data
.init());
1891 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1892 ASSERT_TRUE(my_completion
);
1894 memset(buf
, 0xcc, sizeof(buf
));
1896 bl1
.append(buf
, sizeof(buf
));
1897 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1898 bl1
, sizeof(buf
), 0));
1901 ASSERT_EQ(0, my_completion
->wait_for_complete());
1903 ASSERT_EQ(0, my_completion
->get_return_value());
1906 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1907 ASSERT_TRUE(my_completion2
);
1908 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion2
.get(),
1912 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1914 ASSERT_EQ(0, my_completion2
->get_return_value());
1915 ASSERT_EQ(sizeof(buf
), psize
);
1918 TEST(LibRadosAioEC
, StatRemovePP
) {
1919 AioTestDataECPP test_data
;
1920 ASSERT_EQ("", test_data
.init());
1921 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1922 ASSERT_TRUE(my_completion
);
1924 memset(buf
, 0xcc, sizeof(buf
));
1926 bl1
.append(buf
, sizeof(buf
));
1927 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1928 bl1
, sizeof(buf
), 0));
1931 ASSERT_EQ(0, my_completion
->wait_for_complete());
1933 ASSERT_EQ(0, my_completion
->get_return_value());
1936 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1937 ASSERT_TRUE(my_completion2
);
1938 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion2
.get(),
1942 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1944 ASSERT_EQ(0, my_completion2
->get_return_value());
1945 ASSERT_EQ(sizeof(buf
), psize
);
1948 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1949 ASSERT_TRUE(my_completion3
);
1950 ASSERT_EQ(0, test_data
.m_ioctx
.aio_remove("foo", my_completion3
.get()));
1953 ASSERT_EQ(0, my_completion3
->wait_for_complete());
1955 ASSERT_EQ(0, my_completion3
->get_return_value());
1957 auto my_completion4
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1958 ASSERT_TRUE(my_completion4
);
1959 ASSERT_EQ(0, test_data
.m_ioctx
.aio_stat("foo", my_completion4
.get(),
1960 &psize2
, &pmtime2
));
1963 ASSERT_EQ(0, my_completion4
->wait_for_complete());
1965 ASSERT_EQ(-ENOENT
, my_completion4
->get_return_value());
1968 TEST(LibRadosAioEC
, ExecuteClassPP
) {
1969 AioTestDataECPP test_data
;
1970 ASSERT_EQ("", test_data
.init());
1971 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1972 ASSERT_TRUE(my_completion
);
1974 memset(buf
, 0xcc, sizeof(buf
));
1976 bl1
.append(buf
, sizeof(buf
));
1977 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
1978 bl1
, sizeof(buf
), 0));
1981 ASSERT_EQ(0, my_completion
->wait_for_complete());
1983 ASSERT_EQ(0, my_completion
->get_return_value());
1984 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
1985 ASSERT_TRUE(my_completion2
);
1987 ASSERT_EQ(0, test_data
.m_ioctx
.aio_exec("foo", my_completion2
.get(),
1988 "hello", "say_hello", in
, &out
));
1991 ASSERT_EQ(0, my_completion2
->wait_for_complete());
1993 ASSERT_EQ(0, my_completion2
->get_return_value());
1994 ASSERT_EQ(std::string("Hello, world!"), std::string(out
.c_str(), out
.length()));
1997 TEST(LibRadosAioEC
, OmapPP
) {
1999 std::string pool_name
= get_temp_pool_name();
2000 ASSERT_EQ("", create_one_ec_pool_pp(pool_name
, cluster
));
2002 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
2004 string header_str
= "baz";
2005 bufferptr
bp(header_str
.c_str(), header_str
.size() + 1);
2006 bufferlist header_to_set
;
2007 header_to_set
.push_back(bp
);
2008 map
<string
, bufferlist
> to_set
;
2010 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2011 ObjectWriteOperation op
;
2012 to_set
["foo"] = header_to_set
;
2013 to_set
["foo2"] = header_to_set
;
2014 to_set
["qfoo3"] = header_to_set
;
2015 op
.omap_set(to_set
);
2017 op
.omap_set_header(header_to_set
);
2019 ioctx
.aio_operate("test_obj", my_completion
.get(), &op
);
2022 ASSERT_EQ(0, my_completion
->wait_for_complete());
2024 EXPECT_EQ(-EOPNOTSUPP
, my_completion
->get_return_value());
2026 ioctx
.remove("test_obj");
2027 destroy_one_ec_pool_pp(pool_name
, cluster
);
2030 TEST(LibRadosAioEC
, MultiWritePP
) {
2031 AioTestDataECPP test_data
;
2032 ASSERT_EQ("", test_data
.init());
2033 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2034 ASSERT_TRUE(my_completion
);
2036 memset(buf
, 0xcc, sizeof(buf
));
2038 bl1
.append(buf
, sizeof(buf
));
2039 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
2040 bl1
, sizeof(buf
), 0));
2043 ASSERT_EQ(0, my_completion
->wait_for_complete());
2045 ASSERT_EQ(0, my_completion
->get_return_value());
2048 memset(buf2
, 0xdd, sizeof(buf2
));
2050 bl2
.append(buf2
, sizeof(buf2
));
2051 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2052 ASSERT_TRUE(my_completion2
);
2053 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion2
.get(),
2054 bl2
, sizeof(buf2
), sizeof(buf
)));
2057 ASSERT_EQ(0, my_completion2
->wait_for_complete());
2059 ASSERT_EQ(-EOPNOTSUPP
, my_completion2
->get_return_value());
2062 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2063 ASSERT_TRUE(my_completion3
);
2064 ASSERT_EQ(0, test_data
.m_ioctx
.aio_read("foo", my_completion3
.get(),
2065 &bl3
, (sizeof(buf
) + sizeof(buf2
) * 3), 0));
2068 ASSERT_EQ(0, my_completion3
->wait_for_complete());
2070 ASSERT_EQ((int)sizeof(buf
), my_completion3
->get_return_value());
2071 ASSERT_EQ(sizeof(buf
), bl3
.length());
2072 ASSERT_EQ(0, memcmp(bl3
.c_str(), buf
, sizeof(buf
)));
2076 TEST(LibRadosAio
, RacingRemovePP
) {
2077 AioTestDataPP test_data
;
2078 ASSERT_EQ("", test_data
.init({{"objecter_retry_writes_after_first_reply", "true"}}));
2079 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2080 ASSERT_TRUE(my_completion
);
2082 memset(buf
, 0xcc, sizeof(buf
));
2084 bl
.append(buf
, sizeof(buf
));
2085 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2086 ASSERT_TRUE(my_completion2
);
2087 ASSERT_EQ(0, test_data
.m_ioctx
.aio_remove("foo", my_completion2
.get()));
2088 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
2089 bl
, sizeof(buf
), 0));
2092 my_completion2
->wait_for_complete();
2093 my_completion
->wait_for_complete();
2095 ASSERT_EQ(-ENOENT
, my_completion2
->get_return_value());
2096 ASSERT_EQ(0, my_completion
->get_return_value());
2097 ASSERT_EQ(0, test_data
.m_ioctx
.stat("foo", nullptr, nullptr));
2100 TEST(LibRadosAio
, RoundTripCmpExtPP
) {
2101 AioTestDataPP test_data
;
2102 ASSERT_EQ("", test_data
.init());
2103 auto my_completion
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2104 ASSERT_TRUE(my_completion
);
2106 memset(full
, 0xcc, sizeof(full
));
2108 bl1
.append(full
, sizeof(full
));
2109 ASSERT_EQ(0, test_data
.m_ioctx
.aio_write("foo", my_completion
.get(),
2110 bl1
, sizeof(full
), 0));
2113 ASSERT_EQ(0, my_completion
->wait_for_complete());
2115 ASSERT_EQ(0, my_completion
->get_return_value());
2117 /* compare with match */
2119 cbl
.append(full
, sizeof(full
));
2120 auto my_completion2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2121 ASSERT_EQ(0, test_data
.m_ioctx
.aio_cmpext("foo", my_completion2
.get(), 0, cbl
));
2125 ASSERT_EQ(0, my_completion2
->wait_for_complete());
2127 ASSERT_EQ(0, my_completion2
->get_return_value());
2129 /* compare with mismatch */
2130 memset(full
, 0xdd, sizeof(full
));
2132 cbl
.append(full
, sizeof(full
));
2133 auto my_completion3
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2134 ASSERT_EQ(0, test_data
.m_ioctx
.aio_cmpext("foo", my_completion3
.get(), 0, cbl
));
2137 ASSERT_EQ(0, my_completion3
->wait_for_complete());
2139 ASSERT_EQ(-MAX_ERRNO
, my_completion3
->get_return_value());
2142 TEST(LibRadosAio
, RoundTripCmpExtPP2
)
2146 char miscmp_buf
[128];
2149 std::string pool_name
= get_temp_pool_name();
2150 ASSERT_EQ("", create_one_pool_pp(pool_name
, cluster
));
2152 cluster
.ioctx_create(pool_name
.c_str(), ioctx
);
2154 auto wr_cmpl
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2155 ObjectWriteOperation wr_op
;
2156 memset(buf
, 0xcc, sizeof(buf
));
2157 memset(miscmp_buf
, 0xdd, sizeof(miscmp_buf
));
2159 bl
.append(buf
, sizeof(buf
));
2161 wr_op
.write_full(bl
);
2162 wr_op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2163 ioctx
.aio_operate("test_obj", wr_cmpl
.get(), &wr_op
);
2166 ASSERT_EQ(0, wr_cmpl
->wait_for_complete());
2168 EXPECT_EQ(0, wr_cmpl
->get_return_value());
2170 /* cmpext as write op. first match then mismatch */
2171 auto wr_cmpext_cmpl
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2172 cbl
.append(buf
, sizeof(buf
));
2175 wr_op
.cmpext(0, cbl
, &ret
);
2176 wr_op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2177 ioctx
.aio_operate("test_obj", wr_cmpext_cmpl
.get(), &wr_op
);
2180 ASSERT_EQ(0, wr_cmpext_cmpl
->wait_for_complete());
2182 EXPECT_EQ(0, wr_cmpext_cmpl
->get_return_value());
2185 auto wr_cmpext_cmpl2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2187 cbl
.append(miscmp_buf
, sizeof(miscmp_buf
));
2190 wr_op
.cmpext(0, cbl
, &ret
);
2191 wr_op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2192 ioctx
.aio_operate("test_obj", wr_cmpext_cmpl2
.get(), &wr_op
);
2195 ASSERT_EQ(0, wr_cmpext_cmpl2
->wait_for_complete());
2197 EXPECT_EQ(-MAX_ERRNO
, wr_cmpext_cmpl2
->get_return_value());
2198 EXPECT_EQ(-MAX_ERRNO
, ret
);
2200 /* cmpext as read op */
2201 auto rd_cmpext_cmpl
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2202 ObjectReadOperation rd_op
;
2204 cbl
.append(buf
, sizeof(buf
));
2206 rd_op
.cmpext(0, cbl
, &ret
);
2207 rd_op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2208 ioctx
.aio_operate("test_obj", rd_cmpext_cmpl
.get(), &rd_op
, 0);
2211 ASSERT_EQ(0, rd_cmpext_cmpl
->wait_for_complete());
2213 EXPECT_EQ(0, rd_cmpext_cmpl
->get_return_value());
2216 auto rd_cmpext_cmpl2
= std::unique_ptr
<AioCompletion
>{Rados::aio_create_completion()};
2218 cbl
.append(miscmp_buf
, sizeof(miscmp_buf
));
2221 rd_op
.cmpext(0, cbl
, &ret
);
2222 rd_op
.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2223 ioctx
.aio_operate("test_obj", rd_cmpext_cmpl2
.get(), &rd_op
, 0);
2226 ASSERT_EQ(0, rd_cmpext_cmpl2
->wait_for_complete());
2228 EXPECT_EQ(-MAX_ERRNO
, rd_cmpext_cmpl2
->get_return_value());
2229 EXPECT_EQ(-MAX_ERRNO
, ret
);
2231 ioctx
.remove("test_obj");
2232 destroy_one_pool_pp(pool_name
, cluster
);
2235 ceph::mutex my_lock
= ceph::make_mutex("my_lock");
2236 set
<unsigned> inflight
;
2237 unsigned max_success
= 0;
2238 unsigned min_failed
= 0;
2245 void pool_io_callback(completion_t cb
, void *arg
)
2247 AioCompletion
*c
= (AioCompletion
*)cb
;
2248 io_info
*info
= (io_info
*)arg
;
2249 unsigned long i
= info
->i
;
2250 int r
= info
->c
->get_return_value();
2251 //cout << "finish " << i << " r = " << r << std::endl;
2253 std::scoped_lock
l(my_lock
);
2256 if (i
> max_success
) {
2260 if (!min_failed
|| i
< min_failed
) {
2266 TEST(LibRadosAio
, PoolEIOFlag
) {
2267 AioTestDataPP test_data
;
2268 ASSERT_EQ("", test_data
.init());
2271 bl
.append("some data");
2272 std::thread
*t
= nullptr;
2275 unsigned long i
= 1;
2277 for (; min_failed
== 0; ++i
) {
2278 io_info
*info
= new io_info
;
2280 info
->c
= Rados::aio_create_completion();
2281 info
->c
->set_complete_callback((void*)info
, pool_io_callback
);
2284 int r
= test_data
.m_ioctx
.aio_write("foo", info
->c
, bl
, bl
.length(), 0);
2285 //cout << "start " << i << " r = " << r << std::endl;
2288 cout
<< "setting pool EIO" << std::endl
;
2289 t
= new std::thread(
2292 int r
= test_data
.m_cluster
.mon_command(
2293 "{\"prefix\": \"osd pool set\", \"pool\": \"" + test_data
.m_pool_name
+
2294 "\", \"var\": \"eio\", \"val\": \"true\"}", empty
, nullptr, nullptr);
2295 ceph_assert(r
== 0);
2309 // wait for ios to finish
2310 for (; !inflight
.empty(); ++i
) {
2311 cout
<< "waiting for " << inflight
<< std::endl
;
2317 cout
<< "max_success " << max_success
<< ", min_failed " << min_failed
<< std::endl
;
2318 ASSERT_TRUE(max_success
+ 1 == min_failed
);