]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librados/aio_cxx.cc
28360b3d93833f73e2ffb905d89d965fa221f018
[ceph.git] / ceph / src / test / librados / aio_cxx.cc
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <sstream>
4 #include <string>
5 #include <utility>
6 #include <boost/scoped_ptr.hpp>
7
8 #include "gtest/gtest.h"
9
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"
17
18 #include "test_cxx.h"
19
20 using namespace std;
21 using namespace librados;
22
23 class AioTestDataPP
24 {
25 public:
26 AioTestDataPP()
27 : m_init(false)
28 {
29 }
30
31 ~AioTestDataPP()
32 {
33 if (m_init) {
34 m_ioctx.close();
35 destroy_one_pool_pp(m_pool_name, m_cluster);
36 }
37 }
38
39 std::string init()
40 {
41 return init({});
42 }
43
44 std::string init(const std::map<std::string, std::string> &config)
45 {
46 int ret;
47
48 m_pool_name = get_temp_pool_name();
49 std::string err = create_one_pool_pp(m_pool_name, m_cluster, config);
50 if (!err.empty()) {
51 ostringstream oss;
52 oss << "create_one_pool(" << m_pool_name << ") failed: error " << err;
53 return oss.str();
54 }
55 ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
56 if (ret) {
57 destroy_one_pool_pp(m_pool_name, m_cluster);
58 ostringstream oss;
59 oss << "rados_ioctx_create failed: error " << ret;
60 return oss.str();
61 }
62 m_init = true;
63 return "";
64 }
65
66 Rados m_cluster;
67 IoCtx m_ioctx;
68 std::string m_pool_name;
69 bool m_init;
70 };
71
72 TEST(LibRadosAio, TooBigPP) {
73 AioTestDataPP test_data;
74 ASSERT_EQ("", test_data.init());
75
76 bufferlist bl;
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()
81 }
82
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()));
88 IoCtx ioctx;
89 ASSERT_EQ(0, test_data.m_cluster.ioctx_create(p.c_str(), ioctx));
90 ioctx.application_enable("rados", true);
91
92 bufferlist inbl;
93 ASSERT_EQ(0, test_data.m_cluster.mon_command(
94 "{\"prefix\": \"osd pool set-quota\", \"pool\": \"" + p +
95 "\", \"field\": \"max_bytes\", \"val\": \"4096\"}",
96 inbl, NULL, NULL));
97
98 bufferlist bl;
99 bufferptr z(4096);
100 bl.append(z);
101 int n;
102 for (n = 0; n < 1024; ++n) {
103 ObjectWriteOperation op;
104 op.write_full(bl);
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();
111 if (r == -EDQUOT)
112 break;
113 ASSERT_EQ(0, r);
114 sleep(1);
115 }
116 ASSERT_LT(n, 1024);
117
118 // make sure we have latest map that marked the pool full
119 test_data.m_cluster.wait_for_latest_osdmap();
120
121 // make sure we block without FULL_TRY
122 {
123 ObjectWriteOperation op;
124 op.write_full(bl);
125 auto completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
126 ASSERT_EQ(0, ioctx.aio_operate("bar", completion.get(), &op, 0));
127 sleep(5);
128 ASSERT_FALSE(completion->is_complete());
129 }
130
131 ioctx.close();
132 ASSERT_EQ(0, test_data.m_cluster.pool_delete(p.c_str()));
133 }
134
135 TEST(LibRadosAio, SimpleWritePP) {
136 char buf[128];
137 memset(buf, 0xcc, sizeof(buf));
138 bufferlist bl1;
139 bl1.append(buf, sizeof(buf));
140 {
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));
147 {
148 TestAlarm alarm;
149 ASSERT_EQ(0, my_completion->wait_for_complete());
150 }
151 ASSERT_EQ(0, my_completion->get_return_value());
152 }
153
154 {
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));
161 {
162 TestAlarm alarm;
163 ASSERT_EQ(0, my_completion->wait_for_complete());
164 }
165 ASSERT_EQ(0, my_completion->get_return_value());
166 }
167 }
168
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);
174 char buf[128];
175 memset(buf, 0xcc, sizeof(buf));
176 bufferlist bl1;
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));
180 TestAlarm alarm;
181 ASSERT_EQ(0, my_completion->wait_for_complete());
182 ASSERT_EQ(0, my_completion->get_return_value());
183 }
184
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);
190 char buf[128];
191 memset(buf, 0xcc, sizeof(buf));
192 bufferlist bl1;
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));
196 {
197 TestAlarm alarm;
198 ASSERT_EQ(0, my_completion->wait_for_complete());
199 }
200 ASSERT_EQ(0, my_completion->get_return_value());
201 bufferlist bl2;
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));
206 {
207 TestAlarm alarm;
208 ASSERT_EQ(0, my_completion2->wait_for_complete());
209 }
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)));
213 }
214
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);
220 char buf[128];
221 memset(buf, 0xcc, sizeof(buf));
222 bufferlist bl1;
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));
226 {
227 TestAlarm alarm;
228 ASSERT_EQ(0, my_completion->wait_for_complete());
229 }
230 ASSERT_EQ(0, my_completion->get_return_value());
231 bufferlist bl2;
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));
236 {
237 TestAlarm alarm;
238 ASSERT_EQ(0, my_completion2->wait_for_complete());
239 }
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)));
243 }
244
245 //using ObjectWriteOperation/ObjectReadOperation with iohint
246 TEST(LibRadosAio, RoundTripPP3)
247 {
248 Rados cluster;
249 std::string pool_name = get_temp_pool_name();
250 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
251 IoCtx ioctx;
252 cluster.ioctx_create(pool_name.c_str(), ioctx);
253
254 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
255 ObjectWriteOperation op;
256 char buf[128];
257 memset(buf, 0xcc, sizeof(buf));
258 bufferlist bl;
259 bl.append(buf, sizeof(buf));
260
261 op.write(0, bl);
262 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
263 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
264 {
265 TestAlarm alarm;
266 ASSERT_EQ(0, my_completion1->wait_for_complete());
267 }
268 EXPECT_EQ(0, my_completion1->get_return_value());
269
270 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
271 bl.clear();
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);
277 bufferlist csum_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);
281 {
282 TestAlarm alarm;
283 ASSERT_EQ(0, my_completion2->wait_for_complete());
284 }
285 EXPECT_EQ(0, my_completion2->get_return_value());
286 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
287
288 ASSERT_EQ(8U, csum_bl.length());
289 auto csum_bl_it = csum_bl.cbegin();
290 uint32_t csum_count;
291 uint32_t csum;
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);
298 }
299
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);
305 char buf[128];
306 memset(buf, 0xcc, sizeof(buf));
307 bufferlist bl1;
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));
311 {
312 TestAlarm alarm;
313 ASSERT_EQ(0, my_completion->wait_for_complete());
314 }
315 ASSERT_EQ(0, my_completion->get_return_value());
316 std::map<uint64_t, uint64_t> extents;
317 bufferlist bl2;
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));
322 {
323 TestAlarm alarm;
324 ASSERT_EQ(0, my_completion2->wait_for_complete());
325 }
326 ASSERT_EQ(0, my_completion2->get_return_value());
327 assert_eq_sparse(bl1, extents, bl2);
328 }
329
330 TEST(LibRadosAioPP, ReadIntoBufferlist) {
331
332 // here we test reading into a non-empty bufferlist referencing existing
333 // buffers
334
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);
339 char buf[128];
340 memset(buf, 0xcc, sizeof(buf));
341 bufferlist bl1;
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));
345 {
346 TestAlarm alarm;
347 ASSERT_EQ(0, my_completion->wait_for_complete());
348 }
349 ASSERT_EQ(0, my_completion->get_return_value());
350
351 bufferlist bl2;
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));
359 {
360 TestAlarm alarm;
361 ASSERT_EQ(0, my_completion2->wait_for_complete());
362 }
363 ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
364 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
365 }
366
367 TEST(LibRadosAioPP, XattrsRoundTripPP) {
368 char buf[128];
369 char attr1[] = "attr1";
370 char attr1_buf[] = "foo bar baz";
371 memset(buf, 0xaa, sizeof(buf));
372 bufferlist bl1;
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)));
377 bufferlist bl2;
378 // async getxattr
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));
381 {
382 TestAlarm alarm;
383 ASSERT_EQ(0, my_completion->wait_for_complete());
384 }
385 ASSERT_EQ(-ENODATA, my_completion->get_return_value());
386 // append
387 bufferlist bl3;
388 bl3.append(attr1_buf, sizeof(attr1_buf));
389 // async setxattr
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));
394 {
395 TestAlarm alarm;
396 ASSERT_EQ(0, my_completion2->wait_for_complete());
397 }
398 ASSERT_EQ(0, my_completion2->get_return_value());
399 // async getxattr
400 bufferlist bl4;
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));
405 {
406 TestAlarm alarm;
407 ASSERT_EQ(0, my_completion3->wait_for_complete());
408 }
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)));
412 }
413
414 TEST(LibRadosAioPP, RmXattrPP) {
415 char buf[128];
416 char attr1[] = "attr1";
417 char attr1_buf[] = "foo bar baz";
418 memset(buf, 0xaa, sizeof(buf));
419 bufferlist bl1;
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)));
424 // async setxattr
425 bufferlist bl2;
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));
429 {
430 TestAlarm alarm;
431 ASSERT_EQ(0, my_completion->wait_for_complete());
432 }
433 ASSERT_EQ(0, my_completion->get_return_value());
434 // async rmxattr
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));
439 {
440 TestAlarm alarm;
441 ASSERT_EQ(0, my_completion2->wait_for_complete());
442 }
443 ASSERT_EQ(0, my_completion2->get_return_value());
444 // async getxattr
445 AioTestDataPP test_data3;
446 ASSERT_EQ("", test_data3.init());
447 auto my_completion3 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
448 bufferlist bl3;
449 ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion3.get(), attr1, bl3));
450 {
451 TestAlarm alarm;
452 ASSERT_EQ(0, my_completion3->wait_for_complete());
453 }
454 ASSERT_EQ(-ENODATA, my_completion3->get_return_value());
455 // Test rmxattr on a removed object
456 char buf2[128];
457 char attr2[] = "attr2";
458 char attr2_buf[] = "foo bar baz";
459 memset(buf2, 0xbb, sizeof(buf2));
460 bufferlist bl21;
461 bl21.append(buf, sizeof(buf));
462 ASSERT_EQ(0, test_data.m_ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
463 bufferlist bl22;
464 bl22.append(attr2_buf, sizeof(attr2_buf));
465 // async setxattr
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));
470 {
471 TestAlarm alarm;
472 ASSERT_EQ(0, my_completion4->wait_for_complete());
473 }
474 ASSERT_EQ(0, my_completion4->get_return_value());
475 // remove object
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));
482 {
483 TestAlarm alarm;
484 ASSERT_EQ(0, my_completion5->wait_for_complete());
485 }
486 ASSERT_EQ(-ENOENT, my_completion5->get_return_value());
487 }
488
489 TEST(LibRadosIoPP, XattrListPP) {
490 AioTestDataPP test_data;
491 ASSERT_EQ("", test_data.init());
492 // create an object with 2 attributes
493 char buf[128];
494 char attr1[] = "attr1";
495 char attr1_buf[] = "foo bar baz";
496 char attr2[] = "attr2";
497 char attr2_buf[256];
498 for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
499 attr2_buf[j] = j % 0xff;
500 }
501 memset(buf, 0xaa, sizeof(buf));
502 bufferlist bl1;
503 bl1.append(buf, sizeof(buf));
504 ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
505 bufferlist bl2;
506 bl2.append(attr1_buf, sizeof(attr1_buf));
507 ASSERT_EQ(0, test_data.m_ioctx.setxattr("foo", attr1, bl2));
508 bufferlist bl3;
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));
515 {
516 TestAlarm alarm;
517 ASSERT_EQ(0, my_completion->wait_for_complete());
518 }
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)));
524 }
525 else if (i->first == string(attr2)) {
526 ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
527 }
528 else {
529 ASSERT_EQ(0, 1);
530 }
531 }
532 }
533
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);
539 char buf[128];
540 memset(buf, 0xcc, sizeof(buf));
541 bufferlist bl1;
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));
545 {
546 TestAlarm alarm;
547 ASSERT_EQ(0, my_completion->wait_for_complete());
548 }
549 ASSERT_EQ(0, my_completion->get_return_value());
550 bufferlist bl2;
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));
555 {
556 TestAlarm alarm;
557
558 // Busy-wait until the AIO completes.
559 // Normally we wouldn't do this, but we want to test is_complete.
560 while (true) {
561 int is_complete = my_completion2->is_complete();
562 if (is_complete)
563 break;
564 }
565 }
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)));
569 }
570
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);
576 char buf[128];
577 memset(buf, 0xcc, sizeof(buf));
578 bufferlist bl1;
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));
582 {
583 TestAlarm alarm;
584
585 // Busy-wait until the AIO completes.
586 // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
587 while (true) {
588 int is_complete = my_completion->is_complete();
589 if (is_complete)
590 break;
591 }
592 }
593 ASSERT_EQ(0, my_completion->get_return_value());
594 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
595 bufferlist bl2;
596 ASSERT_TRUE(my_completion2);
597 ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2.get(),
598 &bl2, sizeof(buf), 0));
599 {
600 TestAlarm alarm;
601 ASSERT_EQ(0, my_completion2->wait_for_complete());
602 }
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)));
606 }
607
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);
613 bufferlist bl1;
614 ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent", my_completion.get(),
615 &bl1, 128, 0));
616 {
617 TestAlarm alarm;
618 ASSERT_EQ(0, my_completion->wait_for_complete());
619 }
620 ASSERT_EQ(-ENOENT, my_completion->get_return_value());
621 }
622
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);
628 char buf[128];
629 memset(buf, 0xee, sizeof(buf));
630 bufferlist bl1;
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());
636 bufferlist bl2;
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));
641 {
642 TestAlarm alarm;
643 ASSERT_EQ(0, my_completion2->wait_for_complete());
644 }
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)));
648 }
649
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);
656 char buf[128];
657 memset(buf, 0xee, sizeof(buf));
658 bufferlist bl1;
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()));
663 {
664 TestAlarm alarm;
665 ASSERT_EQ(0, flush_completion->wait_for_complete());
666 }
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());
670 bufferlist bl2;
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));
675 {
676 TestAlarm alarm;
677 ASSERT_EQ(0, my_completion2->wait_for_complete());
678 }
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)));
682 }
683
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);
689 char buf[128];
690 memset(buf, 0xcc, sizeof(buf));
691 bufferlist bl1;
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));
695 {
696 TestAlarm alarm;
697 ASSERT_EQ(0, my_completion->wait_for_complete());
698 }
699 ASSERT_EQ(0, my_completion->get_return_value());
700 char buf2[64];
701 memset(buf2, 0xdd, sizeof(buf2));
702 bufferlist bl2;
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));
707 {
708 TestAlarm alarm;
709 ASSERT_EQ(0, my_completion2->wait_for_complete());
710 }
711 ASSERT_EQ(0, my_completion2->get_return_value());
712 bufferlist bl3;
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));
717 {
718 TestAlarm alarm;
719 ASSERT_EQ(0, my_completion3->wait_for_complete());
720 }
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)));
724 }
725
726 //using ObjectWriteOperation/ObjectReadOperation with iohint
727 TEST(LibRadosAio, RoundTripWriteFullPP2)
728 {
729 Rados cluster;
730 std::string pool_name = get_temp_pool_name();
731 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
732 IoCtx ioctx;
733 cluster.ioctx_create(pool_name.c_str(), ioctx);
734
735 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
736 ObjectWriteOperation op;
737 char buf[128];
738 memset(buf, 0xcc, sizeof(buf));
739 bufferlist bl;
740 bl.append(buf);
741
742 op.write_full(bl);
743 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
744 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
745 {
746 TestAlarm alarm;
747 ASSERT_EQ(0, my_completion1->wait_for_complete());
748 }
749 EXPECT_EQ(0, my_completion1->get_return_value());
750
751 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
752 bl.clear();
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);
757 {
758 TestAlarm alarm;
759 ASSERT_EQ(0, my_completion2->wait_for_complete());
760 }
761 EXPECT_EQ(0, my_completion2->get_return_value());
762 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
763
764 ioctx.remove("test_obj");
765 destroy_one_pool_pp(pool_name, cluster);
766 }
767
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);
773 char full[128];
774 memset(full, 0xcc, sizeof(full));
775 bufferlist bl1;
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));
779 {
780 TestAlarm alarm;
781 ASSERT_EQ(0, my_completion->wait_for_complete());
782 }
783 ASSERT_EQ(0, my_completion->get_return_value());
784 /* write the same buf four times */
785 char buf[32];
786 size_t ws_write_len = sizeof(full);
787 memset(buf, 0xdd, sizeof(buf));
788 bufferlist bl2;
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,
793 ws_write_len, 0));
794 {
795 TestAlarm alarm;
796 ASSERT_EQ(0, my_completion2->wait_for_complete());
797 }
798 ASSERT_EQ(0, my_completion2->get_return_value());
799 bufferlist bl3;
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));
804 {
805 TestAlarm alarm;
806 ASSERT_EQ(0, my_completion3->wait_for_complete());
807 }
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)));
813 }
814 }
815
816 TEST(LibRadosAio, RoundTripWriteSamePP2)
817 {
818 Rados cluster;
819 std::string pool_name = get_temp_pool_name();
820 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
821 IoCtx ioctx;
822 cluster.ioctx_create(pool_name.c_str(), ioctx);
823
824 auto wr_cmpl = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
825 ObjectWriteOperation op;
826 char buf[128];
827 memset(buf, 0xcc, sizeof(buf));
828 bufferlist bl;
829 bl.append(buf, sizeof(buf));
830
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);
834 {
835 TestAlarm alarm;
836 ASSERT_EQ(0, wr_cmpl->wait_for_complete());
837 }
838 EXPECT_EQ(0, wr_cmpl->get_return_value());
839
840 boost::scoped_ptr<AioCompletion>
841 rd_cmpl(cluster.aio_create_completion(0, 0));
842 char *cmp;
843 char full[sizeof(buf) * 4];
844 memset(full, 0, sizeof(full));
845 bufferlist fl;
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);
851 {
852 TestAlarm alarm;
853 ASSERT_EQ(0, rd_cmpl->wait_for_complete());
854 }
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)));
858 }
859
860 ioctx.remove("test_obj");
861 destroy_one_pool_pp(pool_name, cluster);
862 }
863
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);
869 char buf[128];
870 memset(buf, 0xcc, sizeof(buf));
871 bufferlist bl1;
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));
875 {
876 TestAlarm alarm;
877 ASSERT_EQ(0, my_completion->wait_for_complete());
878 }
879 ASSERT_EQ(0, my_completion->get_return_value());
880 uint64_t psize;
881 time_t pmtime;
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(),
885 &psize, &pmtime));
886 {
887 TestAlarm alarm;
888 ASSERT_EQ(0, my_completion2->wait_for_complete());
889 }
890 ASSERT_EQ(0, my_completion2->get_return_value());
891 ASSERT_EQ(sizeof(buf), psize);
892 }
893
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);
899 char buf[128];
900 memset(buf, 0xcc, sizeof(buf));
901 bufferlist bl1;
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));
905 {
906 TestAlarm alarm;
907 ASSERT_EQ(0, my_completion->wait_for_complete());
908 }
909 ASSERT_EQ(0, my_completion->get_return_value());
910 uint64_t psize;
911 time_t pmtime;
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(),
915 &psize, &pmtime));
916 {
917 TestAlarm alarm;
918 ASSERT_EQ(0, my_completion2->wait_for_complete());
919 }
920 ASSERT_EQ(0, my_completion2->get_return_value());
921 ASSERT_EQ(sizeof(buf), psize);
922 }
923
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);
929 char buf[128];
930 memset(buf, 0xcc, sizeof(buf));
931 bufferlist bl1;
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));
935 {
936 TestAlarm alarm;
937 ASSERT_EQ(0, my_completion->wait_for_complete());
938 }
939 ASSERT_EQ(0, my_completion->get_return_value());
940 uint64_t psize;
941 time_t pmtime;
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(),
945 &psize, &pmtime));
946 {
947 TestAlarm alarm;
948 ASSERT_EQ(0, my_completion2->wait_for_complete());
949 }
950 ASSERT_EQ(0, my_completion2->get_return_value());
951 ASSERT_EQ(sizeof(buf), psize);
952 uint64_t psize2;
953 time_t pmtime2;
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()));
957 {
958 TestAlarm alarm;
959 ASSERT_EQ(0, my_completion3->wait_for_complete());
960 }
961 ASSERT_EQ(0, my_completion3->get_return_value());
962
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(),
966 &psize2, &pmtime2));
967 {
968 TestAlarm alarm;
969 ASSERT_EQ(0, my_completion4->wait_for_complete());
970 }
971 ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
972 }
973
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);
979 char buf[128];
980 memset(buf, 0xcc, sizeof(buf));
981 bufferlist bl1;
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));
985 {
986 TestAlarm alarm;
987 ASSERT_EQ(0, my_completion->wait_for_complete());
988 }
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);
992 bufferlist in, out;
993 ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2.get(),
994 "hello", "say_hello", in, &out));
995 {
996 TestAlarm alarm;
997 ASSERT_EQ(0, my_completion2->wait_for_complete());
998 }
999 ASSERT_EQ(0, my_completion2->get_return_value());
1000 ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
1001 }
1002
1003 using std::string;
1004 using std::map;
1005 using std::set;
1006
1007 TEST(LibRadosAio, OmapPP) {
1008 Rados cluster;
1009 std::string pool_name = get_temp_pool_name();
1010 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1011 IoCtx ioctx;
1012 cluster.ioctx_create(pool_name.c_str(), ioctx);
1013
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;
1019 {
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);
1026
1027 op.omap_set_header(header_to_set);
1028
1029 ioctx.aio_operate("test_obj", my_completion.get(), &op);
1030 {
1031 TestAlarm alarm;
1032 ASSERT_EQ(0, my_completion->wait_for_complete());
1033 }
1034 EXPECT_EQ(0, my_completion->get_return_value());
1035 }
1036
1037 {
1038 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1039 ObjectReadOperation op;
1040 map<string, pair<bufferlist, int> > assertions;
1041 bufferlist val;
1042 val.append(string("bar"));
1043 assertions["foo"] = pair<bufferlist, int>(val, CEPH_OSD_CMPXATTR_OP_EQ);
1044
1045 int r;
1046 op.omap_cmp(assertions, &r);
1047
1048 ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
1049 {
1050 TestAlarm alarm;
1051 ASSERT_EQ(0, my_completion->wait_for_complete());
1052 }
1053 EXPECT_EQ(-ECANCELED, my_completion->get_return_value());
1054 ASSERT_EQ(-ECANCELED, r);
1055 }
1056
1057 {
1058 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1059 ObjectReadOperation op;
1060
1061 set<string> set_got;
1062 map<string, bufferlist> map_got;
1063
1064 set<string> to_get;
1065 map<string, bufferlist> got3;
1066
1067 map<string, bufferlist> got4;
1068
1069 bufferlist header;
1070
1071 op.omap_get_keys2("", 1, &set_got, nullptr, 0);
1072 op.omap_get_vals2("foo", 1, &map_got, nullptr, 0);
1073
1074 to_get.insert("foo");
1075 to_get.insert("qfoo3");
1076 op.omap_get_vals_by_keys(to_get, &got3, 0);
1077
1078 op.omap_get_header(&header, 0);
1079
1080 op.omap_get_vals2("foo2", "q", 1, &got4, nullptr, 0);
1081
1082 ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
1083 {
1084 TestAlarm alarm;
1085 ASSERT_EQ(0, my_completion->wait_for_complete());
1086 }
1087 EXPECT_EQ(0, my_completion->get_return_value());
1088
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");
1099 }
1100
1101 {
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);
1108 {
1109 TestAlarm alarm;
1110 ASSERT_EQ(0, my_completion->wait_for_complete());
1111 }
1112 EXPECT_EQ(0, my_completion->get_return_value());
1113 }
1114
1115 {
1116 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1117 ObjectReadOperation op;
1118
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);
1122 {
1123 TestAlarm alarm;
1124 ASSERT_EQ(0, my_completion->wait_for_complete());
1125 }
1126 EXPECT_EQ(0, my_completion->get_return_value());
1127 ASSERT_EQ(set_got.size(), (unsigned)2);
1128 }
1129
1130 {
1131 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1132 ObjectWriteOperation op;
1133 op.omap_clear();
1134 ioctx.aio_operate("test_obj", my_completion.get(), &op);
1135 {
1136 TestAlarm alarm;
1137 ASSERT_EQ(0, my_completion->wait_for_complete());
1138 }
1139 EXPECT_EQ(0, my_completion->get_return_value());
1140 }
1141
1142 {
1143 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1144 ObjectReadOperation op;
1145
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);
1149 {
1150 TestAlarm alarm;
1151 ASSERT_EQ(0, my_completion->wait_for_complete());
1152 }
1153 EXPECT_EQ(0, my_completion->get_return_value());
1154 ASSERT_EQ(set_got.size(), (unsigned)0);
1155 }
1156
1157 // omap_clear clears header *and* keys
1158 {
1159 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1160 ObjectWriteOperation op;
1161 bufferlist bl;
1162 bl.append("some data");
1163 map<string,bufferlist> to_set;
1164 to_set["foo"] = bl;
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);
1170 {
1171 TestAlarm alarm;
1172 ASSERT_EQ(0, my_completion->wait_for_complete());
1173 }
1174 EXPECT_EQ(0, my_completion->get_return_value());
1175 }
1176 {
1177 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1178 ObjectWriteOperation op;
1179 op.omap_clear();
1180 ioctx.aio_operate("foo3", my_completion.get(), &op);
1181 {
1182 TestAlarm alarm;
1183 ASSERT_EQ(0, my_completion->wait_for_complete());
1184 }
1185 EXPECT_EQ(0, my_completion->get_return_value());
1186 }
1187 {
1188 boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0));
1189 ObjectReadOperation op;
1190 set<string> set_got;
1191 bufferlist hdr;
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);
1195 {
1196 TestAlarm alarm;
1197 ASSERT_EQ(0, my_completion->wait_for_complete());
1198 }
1199 EXPECT_EQ(0, my_completion->get_return_value());
1200 ASSERT_EQ(set_got.size(), (unsigned)0);
1201 ASSERT_EQ(hdr.length(), 0u);
1202 }
1203
1204 ioctx.remove("test_obj");
1205 destroy_one_pool_pp(pool_name, cluster);
1206 }
1207
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);
1213 char buf[128];
1214 memset(buf, 0xcc, sizeof(buf));
1215 bufferlist bl1;
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));
1219 {
1220 TestAlarm alarm;
1221 ASSERT_EQ(0, my_completion->wait_for_complete());
1222 }
1223 ASSERT_EQ(0, my_completion->get_return_value());
1224
1225 char buf2[64];
1226 memset(buf2, 0xdd, sizeof(buf2));
1227 bufferlist bl2;
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)));
1233 {
1234 TestAlarm alarm;
1235 ASSERT_EQ(0, my_completion2->wait_for_complete());
1236 }
1237 ASSERT_EQ(0, my_completion2->get_return_value());
1238
1239 bufferlist bl3;
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));
1244 {
1245 TestAlarm alarm;
1246 ASSERT_EQ(0, my_completion3->wait_for_complete());
1247 }
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)));
1252 }
1253
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()));
1260 {
1261 TestAlarm alarm;
1262 ASSERT_EQ(0, my_completion->wait_for_complete());
1263 }
1264 ASSERT_EQ(0, my_completion->get_return_value());
1265 bufferlist bl2;
1266 ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
1267 }
1268
1269 class AioTestDataECPP
1270 {
1271 public:
1272 AioTestDataECPP()
1273 : m_init(false)
1274 {}
1275
1276 ~AioTestDataECPP()
1277 {
1278 if (m_init) {
1279 m_ioctx.close();
1280 destroy_one_ec_pool_pp(m_pool_name, m_cluster);
1281 }
1282 }
1283
1284 std::string init()
1285 {
1286 int ret;
1287 m_pool_name = get_temp_pool_name();
1288 std::string err = create_one_ec_pool_pp(m_pool_name, m_cluster);
1289 if (!err.empty()) {
1290 ostringstream oss;
1291 oss << "create_one_ec_pool(" << m_pool_name << ") failed: error " << err;
1292 return oss.str();
1293 }
1294 ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
1295 if (ret) {
1296 destroy_one_ec_pool_pp(m_pool_name, m_cluster);
1297 ostringstream oss;
1298 oss << "rados_ioctx_create failed: error " << ret;
1299 return oss.str();
1300 }
1301 m_init = true;
1302 return "";
1303 }
1304
1305 Rados m_cluster;
1306 IoCtx m_ioctx;
1307 std::string m_pool_name;
1308 bool m_init;
1309 };
1310
1311 // EC test cases
1312 TEST(LibRadosAioEC, SimpleWritePP) {
1313 char buf[128];
1314 memset(buf, 0xcc, sizeof(buf));
1315 bufferlist bl1;
1316 bl1.append(buf, sizeof(buf));
1317 {
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));
1324 {
1325 TestAlarm alarm;
1326 ASSERT_EQ(0, my_completion->wait_for_complete());
1327 }
1328 ASSERT_EQ(0, my_completion->get_return_value());
1329 }
1330
1331 {
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));
1338 {
1339 TestAlarm alarm;
1340 ASSERT_EQ(0, my_completion->wait_for_complete());
1341 }
1342 ASSERT_EQ(0, my_completion->get_return_value());
1343 }
1344 }
1345
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);
1351 char buf[128];
1352 memset(buf, 0xcc, sizeof(buf));
1353 bufferlist bl1;
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));
1357 TestAlarm alarm;
1358 ASSERT_EQ(0, my_completion->wait_for_complete());
1359 ASSERT_EQ(0, my_completion->get_return_value());
1360 }
1361
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);
1367 char buf[128];
1368 memset(buf, 0xcc, sizeof(buf));
1369 bufferlist bl1;
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));
1373 {
1374 TestAlarm alarm;
1375 ASSERT_EQ(0, my_completion->wait_for_complete());
1376 }
1377 ASSERT_EQ(0, my_completion->get_return_value());
1378 bufferlist bl2;
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));
1383 {
1384 TestAlarm alarm;
1385 ASSERT_EQ(0, my_completion2->wait_for_complete());
1386 }
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)));
1390 }
1391
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);
1397 char buf[128];
1398 memset(buf, 0xcc, sizeof(buf));
1399 bufferlist bl1;
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));
1403 {
1404 TestAlarm alarm;
1405 ASSERT_EQ(0, my_completion->wait_for_complete());
1406 }
1407 ASSERT_EQ(0, my_completion->get_return_value());
1408 bufferlist bl2;
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));
1413 {
1414 TestAlarm alarm;
1415 ASSERT_EQ(0, my_completion2->wait_for_complete());
1416 }
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)));
1420 }
1421
1422 //using ObjectWriteOperation/ObjectReadOperation with iohint
1423 TEST(LibRadosAioEC, RoundTripPP3)
1424 {
1425 Rados cluster;
1426 std::string pool_name = get_temp_pool_name();
1427 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1428 IoCtx ioctx;
1429 cluster.ioctx_create(pool_name.c_str(), ioctx);
1430
1431 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};;
1432 ObjectWriteOperation op;
1433 char buf[128];
1434 memset(buf, 0xcc, sizeof(buf));
1435 bufferlist bl;
1436 bl.append(buf);
1437
1438 op.write(0, bl);
1439 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
1440 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
1441 {
1442 TestAlarm alarm;
1443 ASSERT_EQ(0, my_completion1->wait_for_complete());
1444 }
1445 EXPECT_EQ(0, my_completion1->get_return_value());
1446
1447 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1448 bl.clear();
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);
1453 {
1454 TestAlarm alarm;
1455 ASSERT_EQ(0, my_completion2->wait_for_complete());
1456 }
1457 EXPECT_EQ(0, my_completion2->get_return_value());
1458 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
1459
1460 ioctx.remove("test_obj");
1461 destroy_one_pool_pp(pool_name, cluster);
1462 }
1463
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);
1469 char buf[128];
1470 memset(buf, 0xcc, sizeof(buf));
1471 bufferlist bl1;
1472 bl1.append(buf, sizeof(buf));
1473 ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion.get(),
1474 bl1, sizeof(buf)));
1475 {
1476 TestAlarm alarm;
1477 ASSERT_EQ(0, my_completion->wait_for_complete());
1478 }
1479 ASSERT_EQ(0, my_completion->get_return_value());
1480 char buf2[128];
1481 memset(buf2, 0xdd, sizeof(buf2));
1482 bufferlist bl2;
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)));
1488 {
1489 TestAlarm alarm;
1490 ASSERT_EQ(0, my_completion2->wait_for_complete());
1491 }
1492 ASSERT_EQ(0, my_completion2->get_return_value());
1493 bufferlist bl3;
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));
1498 {
1499 TestAlarm alarm;
1500 ASSERT_EQ(0, my_completion3->wait_for_complete());
1501 }
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)));
1506 }
1507
1508 TEST(LibRadosAioPP, RemoveTestPP) {
1509 char buf[128];
1510 memset(buf, 0xaa, sizeof(buf));
1511 bufferlist bl1;
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()));
1518 {
1519 TestAlarm alarm;
1520 ASSERT_EQ(0, my_completion->wait_for_complete());
1521 }
1522 ASSERT_EQ(0, my_completion->get_return_value());
1523 bufferlist bl2;
1524 ASSERT_EQ(-ENOENT, test_data.m_ioctx.read("foo", bl2, sizeof(buf), 0));
1525 }
1526
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);
1532 char buf[128];
1533 memset(buf, 0xcc, sizeof(buf));
1534 bufferlist bl1;
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));
1538 {
1539 TestAlarm alarm;
1540 ASSERT_EQ(0, my_completion->wait_for_complete());
1541 }
1542 ASSERT_EQ(0, my_completion->get_return_value());
1543
1544 map<uint64_t, uint64_t> extents;
1545 bufferlist bl2;
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));
1550 {
1551 TestAlarm alarm;
1552 ASSERT_EQ(0, my_completion2->wait_for_complete());
1553 }
1554 ASSERT_EQ(0, my_completion2->get_return_value());
1555 assert_eq_sparse(bl1, extents, bl2);
1556 }
1557
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);
1563 bool requires;
1564 ASSERT_EQ(0, test_data.m_ioctx.pool_requires_alignment2(&requires));
1565 ASSERT_TRUE(requires);
1566 uint64_t alignment;
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);
1572 bufferlist bl1;
1573 bl1.append(buf, bsize);
1574 ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion.get(),
1575 bl1, bsize));
1576 {
1577 TestAlarm alarm;
1578 ASSERT_EQ(0, my_completion->wait_for_complete());
1579 }
1580 ASSERT_EQ(0, my_completion->get_return_value());
1581
1582 int hbsize = bsize / 2;
1583 char *buf2 = (char *)new char[hbsize];
1584 memset(buf2, 0xdd, hbsize);
1585 bufferlist bl2;
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(),
1590 bl2, hbsize));
1591 {
1592 TestAlarm alarm;
1593 ASSERT_EQ(0, my_completion2->wait_for_complete());
1594 }
1595 ASSERT_EQ(0, my_completion2->get_return_value());
1596
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(),
1600 bl2, hbsize));
1601 {
1602 TestAlarm alarm;
1603 ASSERT_EQ(0, my_completion3->wait_for_complete());
1604 }
1605 EXPECT_EQ(-EOPNOTSUPP, my_completion3->get_return_value());
1606
1607 bufferlist bl3;
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));
1612 {
1613 TestAlarm alarm;
1614 ASSERT_EQ(0, my_completion4->wait_for_complete());
1615 }
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));
1621 delete[] buf;
1622 delete[] buf2;
1623 }
1624
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);
1630 char buf[128];
1631 memset(buf, 0xcc, sizeof(buf));
1632 bufferlist bl1;
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));
1636 {
1637 TestAlarm alarm;
1638 ASSERT_EQ(0, my_completion->wait_for_complete());
1639 }
1640 ASSERT_EQ(0, my_completion->get_return_value());
1641 bufferlist bl2;
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));
1646 {
1647 TestAlarm alarm;
1648
1649 // Busy-wait until the AIO completes.
1650 // Normally we wouldn't do this, but we want to test is_complete.
1651 while (true) {
1652 int is_complete = my_completion2->is_complete();
1653 if (is_complete)
1654 break;
1655 }
1656 }
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)));
1660 }
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);
1666 char buf[128];
1667 memset(buf, 0xcc, sizeof(buf));
1668 bufferlist bl1;
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));
1672 {
1673 TestAlarm alarm;
1674
1675 // Busy-wait until the AIO completes.
1676 // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
1677 while (true) {
1678 int is_complete = my_completion->is_complete();
1679 if (is_complete)
1680 break;
1681 }
1682 }
1683 ASSERT_EQ(0, my_completion->get_return_value());
1684 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1685 bufferlist bl2;
1686 ASSERT_TRUE(my_completion2);
1687 ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2.get(),
1688 &bl2, sizeof(buf), 0));
1689 {
1690 TestAlarm alarm;
1691 ASSERT_EQ(0, my_completion2->wait_for_complete());
1692 }
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)));
1696 }
1697
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);
1703 bufferlist bl1;
1704 ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent", my_completion.get(),
1705 &bl1, 128, 0));
1706 {
1707 TestAlarm alarm;
1708 ASSERT_EQ(0, my_completion->wait_for_complete());
1709 }
1710 ASSERT_EQ(-ENOENT, my_completion->get_return_value());
1711 }
1712
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);
1718 char buf[128];
1719 memset(buf, 0xee, sizeof(buf));
1720 bufferlist bl1;
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());
1726 bufferlist bl2;
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));
1731 {
1732 TestAlarm alarm;
1733 ASSERT_EQ(0, my_completion2->wait_for_complete());
1734 }
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)));
1738 }
1739
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);
1746 char buf[128];
1747 memset(buf, 0xee, sizeof(buf));
1748 bufferlist bl1;
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()));
1753 {
1754 TestAlarm alarm;
1755 ASSERT_EQ(0, flush_completion->wait_for_complete());
1756 }
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());
1760 bufferlist bl2;
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));
1765 {
1766 TestAlarm alarm;
1767 ASSERT_EQ(0, my_completion2->wait_for_complete());
1768 }
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)));
1772 }
1773
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);
1779 char buf[128];
1780 memset(buf, 0xcc, sizeof(buf));
1781 bufferlist bl1;
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));
1785 {
1786 TestAlarm alarm;
1787 ASSERT_EQ(0, my_completion->wait_for_complete());
1788 }
1789 ASSERT_EQ(0, my_completion->get_return_value());
1790 char buf2[64];
1791 memset(buf2, 0xdd, sizeof(buf2));
1792 bufferlist bl2;
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));
1797 {
1798 TestAlarm alarm;
1799 ASSERT_EQ(0, my_completion2->wait_for_complete());
1800 }
1801 ASSERT_EQ(0, my_completion2->get_return_value());
1802 bufferlist bl3;
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));
1807 {
1808 TestAlarm alarm;
1809 ASSERT_EQ(0, my_completion3->wait_for_complete());
1810 }
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)));
1814 }
1815
1816 //using ObjectWriteOperation/ObjectReadOperation with iohint
1817 TEST(LibRadosAioEC, RoundTripWriteFullPP2)
1818 {
1819 Rados cluster;
1820 std::string pool_name = get_temp_pool_name();
1821 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1822 IoCtx ioctx;
1823 cluster.ioctx_create(pool_name.c_str(), ioctx);
1824
1825 auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1826 ObjectWriteOperation op;
1827 char buf[128];
1828 memset(buf, 0xcc, sizeof(buf));
1829 bufferlist bl;
1830 bl.append(buf);
1831
1832 op.write_full(bl);
1833 op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
1834 ioctx.aio_operate("test_obj", my_completion1.get(), &op);
1835 {
1836 TestAlarm alarm;
1837 ASSERT_EQ(0, my_completion1->wait_for_complete());
1838 }
1839 EXPECT_EQ(0, my_completion1->get_return_value());
1840
1841 auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
1842 bl.clear();
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);
1847 {
1848 TestAlarm alarm;
1849 ASSERT_EQ(0, my_completion2->wait_for_complete());
1850 }
1851 EXPECT_EQ(0, my_completion2->get_return_value());
1852 ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
1853
1854 ioctx.remove("test_obj");
1855 destroy_one_pool_pp(pool_name, cluster);
1856 }
1857
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);
1863 char buf[128];
1864 memset(buf, 0xcc, sizeof(buf));
1865 bufferlist bl1;
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));
1869 {
1870 TestAlarm alarm;
1871 ASSERT_EQ(0, my_completion->wait_for_complete());
1872 }
1873 ASSERT_EQ(0, my_completion->get_return_value());
1874 uint64_t psize;
1875 time_t pmtime;
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(),
1879 &psize, &pmtime));
1880 {
1881 TestAlarm alarm;
1882 ASSERT_EQ(0, my_completion2->wait_for_complete());
1883 }
1884 ASSERT_EQ(0, my_completion2->get_return_value());
1885 ASSERT_EQ(sizeof(buf), psize);
1886 }
1887
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);
1893 char buf[128];
1894 memset(buf, 0xcc, sizeof(buf));
1895 bufferlist bl1;
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));
1899 {
1900 TestAlarm alarm;
1901 ASSERT_EQ(0, my_completion->wait_for_complete());
1902 }
1903 ASSERT_EQ(0, my_completion->get_return_value());
1904 uint64_t psize;
1905 time_t pmtime;
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(),
1909 &psize, &pmtime));
1910 {
1911 TestAlarm alarm;
1912 ASSERT_EQ(0, my_completion2->wait_for_complete());
1913 }
1914 ASSERT_EQ(0, my_completion2->get_return_value());
1915 ASSERT_EQ(sizeof(buf), psize);
1916 }
1917
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);
1923 char buf[128];
1924 memset(buf, 0xcc, sizeof(buf));
1925 bufferlist bl1;
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));
1929 {
1930 TestAlarm alarm;
1931 ASSERT_EQ(0, my_completion->wait_for_complete());
1932 }
1933 ASSERT_EQ(0, my_completion->get_return_value());
1934 uint64_t psize;
1935 time_t pmtime;
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(),
1939 &psize, &pmtime));
1940 {
1941 TestAlarm alarm;
1942 ASSERT_EQ(0, my_completion2->wait_for_complete());
1943 }
1944 ASSERT_EQ(0, my_completion2->get_return_value());
1945 ASSERT_EQ(sizeof(buf), psize);
1946 uint64_t psize2;
1947 time_t pmtime2;
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()));
1951 {
1952 TestAlarm alarm;
1953 ASSERT_EQ(0, my_completion3->wait_for_complete());
1954 }
1955 ASSERT_EQ(0, my_completion3->get_return_value());
1956
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));
1961 {
1962 TestAlarm alarm;
1963 ASSERT_EQ(0, my_completion4->wait_for_complete());
1964 }
1965 ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
1966 }
1967
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);
1973 char buf[128];
1974 memset(buf, 0xcc, sizeof(buf));
1975 bufferlist bl1;
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));
1979 {
1980 TestAlarm alarm;
1981 ASSERT_EQ(0, my_completion->wait_for_complete());
1982 }
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);
1986 bufferlist in, out;
1987 ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2.get(),
1988 "hello", "say_hello", in, &out));
1989 {
1990 TestAlarm alarm;
1991 ASSERT_EQ(0, my_completion2->wait_for_complete());
1992 }
1993 ASSERT_EQ(0, my_completion2->get_return_value());
1994 ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
1995 }
1996
1997 TEST(LibRadosAioEC, OmapPP) {
1998 Rados cluster;
1999 std::string pool_name = get_temp_pool_name();
2000 ASSERT_EQ("", create_one_ec_pool_pp(pool_name, cluster));
2001 IoCtx ioctx;
2002 cluster.ioctx_create(pool_name.c_str(), ioctx);
2003
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;
2009 {
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);
2016
2017 op.omap_set_header(header_to_set);
2018
2019 ioctx.aio_operate("test_obj", my_completion.get(), &op);
2020 {
2021 TestAlarm alarm;
2022 ASSERT_EQ(0, my_completion->wait_for_complete());
2023 }
2024 EXPECT_EQ(-EOPNOTSUPP, my_completion->get_return_value());
2025 }
2026 ioctx.remove("test_obj");
2027 destroy_one_ec_pool_pp(pool_name, cluster);
2028 }
2029
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);
2035 char buf[128];
2036 memset(buf, 0xcc, sizeof(buf));
2037 bufferlist bl1;
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));
2041 {
2042 TestAlarm alarm;
2043 ASSERT_EQ(0, my_completion->wait_for_complete());
2044 }
2045 ASSERT_EQ(0, my_completion->get_return_value());
2046
2047 char buf2[64];
2048 memset(buf2, 0xdd, sizeof(buf2));
2049 bufferlist bl2;
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)));
2055 {
2056 TestAlarm alarm;
2057 ASSERT_EQ(0, my_completion2->wait_for_complete());
2058 }
2059 ASSERT_EQ(-EOPNOTSUPP, my_completion2->get_return_value());
2060
2061 bufferlist bl3;
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));
2066 {
2067 TestAlarm alarm;
2068 ASSERT_EQ(0, my_completion3->wait_for_complete());
2069 }
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)));
2073
2074 }
2075
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);
2081 char buf[128];
2082 memset(buf, 0xcc, sizeof(buf));
2083 bufferlist bl;
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));
2090 {
2091 TestAlarm alarm;
2092 my_completion2->wait_for_complete();
2093 my_completion->wait_for_complete();
2094 }
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));
2098 }
2099
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);
2105 char full[128];
2106 memset(full, 0xcc, sizeof(full));
2107 bufferlist bl1;
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));
2111 {
2112 TestAlarm alarm;
2113 ASSERT_EQ(0, my_completion->wait_for_complete());
2114 }
2115 ASSERT_EQ(0, my_completion->get_return_value());
2116
2117 /* compare with match */
2118 bufferlist cbl;
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));
2122
2123 {
2124 TestAlarm alarm;
2125 ASSERT_EQ(0, my_completion2->wait_for_complete());
2126 }
2127 ASSERT_EQ(0, my_completion2->get_return_value());
2128
2129 /* compare with mismatch */
2130 memset(full, 0xdd, sizeof(full));
2131 cbl.clear();
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));
2135 {
2136 TestAlarm alarm;
2137 ASSERT_EQ(0, my_completion3->wait_for_complete());
2138 }
2139 ASSERT_EQ(-MAX_ERRNO, my_completion3->get_return_value());
2140 }
2141
2142 TEST(LibRadosAio, RoundTripCmpExtPP2)
2143 {
2144 int ret;
2145 char buf[128];
2146 char miscmp_buf[128];
2147 bufferlist cbl;
2148 Rados cluster;
2149 std::string pool_name = get_temp_pool_name();
2150 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
2151 IoCtx ioctx;
2152 cluster.ioctx_create(pool_name.c_str(), ioctx);
2153
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));
2158 bufferlist bl;
2159 bl.append(buf, sizeof(buf));
2160
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);
2164 {
2165 TestAlarm alarm;
2166 ASSERT_EQ(0, wr_cmpl->wait_for_complete());
2167 }
2168 EXPECT_EQ(0, wr_cmpl->get_return_value());
2169
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));
2173 ret = 0;
2174
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);
2178 {
2179 TestAlarm alarm;
2180 ASSERT_EQ(0, wr_cmpext_cmpl->wait_for_complete());
2181 }
2182 EXPECT_EQ(0, wr_cmpext_cmpl->get_return_value());
2183 EXPECT_EQ(0, ret);
2184
2185 auto wr_cmpext_cmpl2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2186 cbl.clear();
2187 cbl.append(miscmp_buf, sizeof(miscmp_buf));
2188 ret = 0;
2189
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);
2193 {
2194 TestAlarm alarm;
2195 ASSERT_EQ(0, wr_cmpext_cmpl2->wait_for_complete());
2196 }
2197 EXPECT_EQ(-MAX_ERRNO, wr_cmpext_cmpl2->get_return_value());
2198 EXPECT_EQ(-MAX_ERRNO, ret);
2199
2200 /* cmpext as read op */
2201 auto rd_cmpext_cmpl = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2202 ObjectReadOperation rd_op;
2203 cbl.clear();
2204 cbl.append(buf, sizeof(buf));
2205 ret = 0;
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);
2209 {
2210 TestAlarm alarm;
2211 ASSERT_EQ(0, rd_cmpext_cmpl->wait_for_complete());
2212 }
2213 EXPECT_EQ(0, rd_cmpext_cmpl->get_return_value());
2214 EXPECT_EQ(0, ret);
2215
2216 auto rd_cmpext_cmpl2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
2217 cbl.clear();
2218 cbl.append(miscmp_buf, sizeof(miscmp_buf));
2219 ret = 0;
2220
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);
2224 {
2225 TestAlarm alarm;
2226 ASSERT_EQ(0, rd_cmpext_cmpl2->wait_for_complete());
2227 }
2228 EXPECT_EQ(-MAX_ERRNO, rd_cmpext_cmpl2->get_return_value());
2229 EXPECT_EQ(-MAX_ERRNO, ret);
2230
2231 ioctx.remove("test_obj");
2232 destroy_one_pool_pp(pool_name, cluster);
2233 }
2234
2235 ceph::mutex my_lock = ceph::make_mutex("my_lock");
2236 set<unsigned> inflight;
2237 unsigned max_success = 0;
2238 unsigned min_failed = 0;
2239
2240 struct io_info {
2241 unsigned i;
2242 AioCompletion *c;
2243 };
2244
2245 void pool_io_callback(completion_t cb, void *arg)
2246 {
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;
2252
2253 std::scoped_lock l(my_lock);
2254 inflight.erase(i);
2255 if (r == 0) {
2256 if (i > max_success) {
2257 max_success = i;
2258 }
2259 } else {
2260 if (!min_failed || i < min_failed) {
2261 min_failed = i;
2262 }
2263 }
2264 }
2265
2266 TEST(LibRadosAio, PoolEIOFlag) {
2267 AioTestDataPP test_data;
2268 ASSERT_EQ("", test_data.init());
2269
2270 bufferlist bl;
2271 bl.append("some data");
2272 std::thread *t = nullptr;
2273
2274 unsigned max = 100;
2275 unsigned long i = 1;
2276 my_lock.lock();
2277 for (; min_failed == 0; ++i) {
2278 io_info *info = new io_info;
2279 info->i = i;
2280 info->c = Rados::aio_create_completion();
2281 info->c->set_complete_callback((void*)info, pool_io_callback);
2282 inflight.insert(i);
2283 my_lock.unlock();
2284 int r = test_data.m_ioctx.aio_write("foo", info->c, bl, bl.length(), 0);
2285 //cout << "start " << i << " r = " << r << std::endl;
2286
2287 if (i == max / 2) {
2288 cout << "setting pool EIO" << std::endl;
2289 t = new std::thread(
2290 [&] {
2291 bufferlist empty;
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);
2296 });
2297 }
2298
2299 sleep(.01);
2300 my_lock.lock();
2301 if (r < 0) {
2302 inflight.erase(i);
2303 break;
2304 }
2305 }
2306 t->join();
2307 delete t;
2308
2309 // wait for ios to finish
2310 for (; !inflight.empty(); ++i) {
2311 cout << "waiting for " << inflight << std::endl;
2312 my_lock.unlock();
2313 sleep(1);
2314 my_lock.lock();
2315 }
2316
2317 cout << "max_success " << max_success << ", min_failed " << min_failed << std::endl;
2318 ASSERT_TRUE(max_success + 1 == min_failed);
2319 my_lock.unlock();
2320 }