Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librados / aio.cc
1 #include "common/errno.h"
2 #include "include/err.h"
3 #include "include/rados/librados.h"
4 #include "test/librados/test.h"
5 #include "include/types.h"
6 #include "include/stringify.h"
7
8 #include "gtest/gtest.h"
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <semaphore.h>
12 #include <sstream>
13 #include <string>
14 #include <boost/scoped_ptr.hpp>
15 #include <utility>
16
17 using std::ostringstream;
18 using namespace librados;
19 using std::pair;
20
21 class AioTestData
22 {
23 public:
24   AioTestData()
25     : m_cluster(NULL),
26       m_ioctx(NULL),
27       m_init(false),
28       m_complete(false),
29       m_safe(false)
30   {
31   }
32
33   ~AioTestData()
34   {
35     if (m_init) {
36       rados_ioctx_destroy(m_ioctx);
37       destroy_one_pool(m_pool_name, &m_cluster);
38       sem_close(m_sem);
39     }
40   }
41
42   std::string init()
43   {
44     int ret;
45     if (SEM_FAILED == (m_sem = sem_open("/test_aio_sem", O_CREAT, 0644, 0))) {
46       int err = errno;
47       ostringstream oss;
48       oss << "sem_open failed: " << cpp_strerror(err);
49       return oss.str();
50     }
51     m_pool_name = get_temp_pool_name();
52     std::string err = create_one_pool(m_pool_name, &m_cluster);
53     if (!err.empty()) {
54       sem_close(m_sem);
55       ostringstream oss;
56       oss << "create_one_pool(" << m_pool_name << ") failed: error " << err;
57       return oss.str();
58     }
59     ret = rados_ioctx_create(m_cluster, m_pool_name.c_str(), &m_ioctx);
60     if (ret) {
61       sem_close(m_sem);
62       destroy_one_pool(m_pool_name, &m_cluster);
63       ostringstream oss;
64       oss << "rados_ioctx_create failed: error " << ret;
65       return oss.str();
66     }
67     m_init = true;
68     return "";
69   }
70
71   sem_t *m_sem = nullptr;
72   rados_t m_cluster;
73   rados_ioctx_t m_ioctx;
74   std::string m_pool_name;
75   bool m_init;
76   bool m_complete;
77   bool m_safe;
78 };
79
80 class AioTestDataPP
81 {
82 public:
83   AioTestDataPP()
84     : m_init(false),
85       m_complete(false),
86       m_safe(false)
87   {
88   }
89
90   ~AioTestDataPP()
91   {
92     if (m_init) {
93       m_ioctx.close();
94       destroy_one_pool_pp(m_pool_name, m_cluster);
95       sem_close(m_sem);
96     }
97   }
98
99   std::string init()
100   {
101       return init({});
102   }
103
104   std::string init(const std::map<std::string, std::string> &config)
105   {
106     int ret;
107
108     if (SEM_FAILED == (m_sem = sem_open("/test_aio_sem", O_CREAT, 0644, 0))) {
109       int err = errno;
110       ostringstream oss;
111       oss << "sem_open failed: " << cpp_strerror(err);
112       return oss.str();
113     }
114     m_pool_name = get_temp_pool_name();
115     std::string err = create_one_pool_pp(m_pool_name, m_cluster, config);
116     if (!err.empty()) {
117       sem_close(m_sem);
118       ostringstream oss;
119       oss << "create_one_pool(" << m_pool_name << ") failed: error " << err;
120       return oss.str();
121     }
122     ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
123     if (ret) {
124       sem_close(m_sem);
125       destroy_one_pool_pp(m_pool_name, m_cluster);
126       ostringstream oss;
127       oss << "rados_ioctx_create failed: error " << ret;
128       return oss.str();
129     }
130     m_init = true;
131     return "";
132   }
133
134   sem_t *m_sem = nullptr;
135   Rados m_cluster;
136   IoCtx m_ioctx;
137   std::string m_pool_name;
138   bool m_init;
139   bool m_complete;
140   bool m_safe;
141 };
142
143 void set_completion_complete(rados_completion_t cb, void *arg)
144 {
145   AioTestData *test = static_cast<AioTestData*>(arg);
146   test->m_complete = true;
147   sem_post(test->m_sem);
148 }
149
150 void set_completion_safe(rados_completion_t cb, void *arg)
151 {
152   AioTestData *test = static_cast<AioTestData*>(arg);
153   test->m_safe = true;
154   sem_post(test->m_sem);
155 }
156
157 void set_completion_completePP(rados_completion_t cb, void *arg)
158 {
159   AioTestDataPP *test = static_cast<AioTestDataPP*>(arg);
160   test->m_complete = true;
161   sem_post(test->m_sem);
162 }
163
164 void set_completion_safePP(rados_completion_t cb, void *arg)
165 {
166   AioTestDataPP *test = static_cast<AioTestDataPP*>(arg);
167   test->m_safe = true;
168   sem_post(test->m_sem);
169 }
170
171 TEST(LibRadosAio, TooBig) {
172   AioTestData test_data;
173   rados_completion_t my_completion;
174   ASSERT_EQ("", test_data.init());
175   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
176               set_completion_complete, set_completion_safe, &my_completion));
177   char buf[128];
178   memset(buf, 0xcc, sizeof(buf));
179   ASSERT_EQ(-E2BIG, rados_aio_write(test_data.m_ioctx, "foo",
180                                     my_completion, buf, UINT_MAX, 0));
181   ASSERT_EQ(-E2BIG, rados_aio_write_full(test_data.m_ioctx, "foo",
182                                          my_completion, buf, UINT_MAX));
183   ASSERT_EQ(-E2BIG, rados_aio_append(test_data.m_ioctx, "foo",
184                                      my_completion, buf, UINT_MAX));
185   rados_aio_release(my_completion);
186 }
187
188 TEST(LibRadosAio, TooBigPP) {
189   AioTestDataPP test_data;
190   ASSERT_EQ("", test_data.init());
191
192   bufferlist bl;
193   AioCompletion *aio_completion = test_data.m_cluster.aio_create_completion(
194                                                                             (void*)&test_data, NULL, NULL);
195   ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_write("foo", aio_completion, bl, UINT_MAX, 0));
196   ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_append("foo", aio_completion, bl, UINT_MAX));
197   // ioctx.aio_write_full no way to overflow bl.length()
198   delete aio_completion;
199 }
200
201 TEST(LibRadosAio, PoolQuotaPP) {
202   AioTestDataPP test_data;
203   ASSERT_EQ("", test_data.init());
204   string p = get_temp_pool_name();
205   ASSERT_EQ(0, test_data.m_cluster.pool_create(p.c_str()));
206   IoCtx ioctx;
207   ASSERT_EQ(0, test_data.m_cluster.ioctx_create(p.c_str(), ioctx));
208   ioctx.application_enable("rados", true);
209
210   bufferlist inbl;
211   ASSERT_EQ(0, test_data.m_cluster.mon_command(
212       "{\"prefix\": \"osd pool set-quota\", \"pool\": \"" + p +
213       "\", \"field\": \"max_bytes\", \"val\": \"4096\"}",
214       inbl, NULL, NULL));
215
216   bufferlist bl;
217   bufferptr z(4096);
218   bl.append(z);
219   int n;
220   for (n = 0; n < 1024; ++n) {
221     ObjectWriteOperation op;
222     op.write_full(bl);
223     librados::AioCompletion *completion =
224       test_data.m_cluster.aio_create_completion();
225     ASSERT_EQ(0, ioctx.aio_operate(
226         "foo" + stringify(n), completion, &op,
227         librados::OPERATION_FULL_TRY));
228     completion->wait_for_safe();
229     int r = completion->get_return_value();
230     completion->release();
231     if (r == -EDQUOT)
232       break;
233     ASSERT_EQ(0, r);
234     sleep(1);
235   }
236   ASSERT_LT(n, 1024);
237
238   // make sure we block without FULL_TRY
239   {
240     ObjectWriteOperation op;
241     op.write_full(bl);
242     librados::AioCompletion *completion =
243       test_data.m_cluster.aio_create_completion();
244     ASSERT_EQ(0, ioctx.aio_operate("bar", completion, &op, 0));
245     sleep(5);
246     ASSERT_FALSE(completion->is_safe());
247     completion->release();
248   }
249
250   ioctx.close();
251   ASSERT_EQ(0, test_data.m_cluster.pool_delete(p.c_str()));
252 }
253
254 TEST(LibRadosAio, SimpleWrite) {
255   AioTestData test_data;
256   rados_completion_t my_completion;
257   ASSERT_EQ("", test_data.init());
258   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
259               set_completion_complete, set_completion_safe, &my_completion));
260   char buf[128];
261   memset(buf, 0xcc, sizeof(buf));
262   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
263                                my_completion, buf, sizeof(buf), 0));
264   {
265     TestAlarm alarm;
266     sem_wait(test_data.m_sem);
267     sem_wait(test_data.m_sem);
268   }
269   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
270
271   rados_ioctx_set_namespace(test_data.m_ioctx, "nspace");
272   rados_completion_t my_completion2;
273   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
274               set_completion_complete, set_completion_safe, &my_completion2));
275   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
276                                my_completion2, buf, sizeof(buf), 0));
277   {
278     TestAlarm alarm;
279     sem_wait(test_data.m_sem);
280     sem_wait(test_data.m_sem);
281   }
282   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
283   rados_aio_release(my_completion);
284   rados_aio_release(my_completion2);
285 }
286
287 TEST(LibRadosAio, SimpleWritePP) {
288   char buf[128];
289   memset(buf, 0xcc, sizeof(buf));
290   bufferlist bl1;
291   bl1.append(buf, sizeof(buf));
292   {
293   AioTestDataPP test_data;
294   ASSERT_EQ("", test_data.init());
295   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
296           (void*)&test_data, set_completion_completePP, set_completion_safePP);
297   AioCompletion *my_completion_null = NULL;
298   ASSERT_NE(my_completion, my_completion_null);
299   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
300                                my_completion, bl1, sizeof(buf), 0));
301   {
302     TestAlarm alarm;
303     sem_wait(test_data.m_sem);
304     sem_wait(test_data.m_sem);
305   }
306   ASSERT_EQ(0, my_completion->get_return_value());
307   delete my_completion;
308   }
309
310   {
311   AioTestDataPP test_data;
312   ASSERT_EQ("", test_data.init());
313   test_data.m_ioctx.set_namespace("nspace");
314   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
315           (void*)&test_data, set_completion_completePP, set_completion_safePP);
316   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
317                                my_completion, bl1, sizeof(buf), 0));
318   {
319     TestAlarm alarm;
320     sem_wait(test_data.m_sem);
321     sem_wait(test_data.m_sem);
322   }
323   ASSERT_EQ(0, my_completion->get_return_value());
324   delete my_completion;
325   }
326 }
327
328 TEST(LibRadosAio, WaitForSafe) {
329   AioTestData test_data;
330   rados_completion_t my_completion;
331   ASSERT_EQ("", test_data.init());
332   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
333               set_completion_complete, set_completion_safe, &my_completion));
334   char buf[128];
335   memset(buf, 0xcc, sizeof(buf));
336   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
337                                my_completion, buf, sizeof(buf), 0));
338   TestAlarm alarm;
339   ASSERT_EQ(0, rados_aio_wait_for_safe(my_completion));
340   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
341   rados_aio_release(my_completion);
342 }
343
344 TEST(LibRadosAio, WaitForSafePP) {
345   AioTestDataPP test_data;
346   ASSERT_EQ("", test_data.init());
347   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
348           (void*)&test_data, set_completion_completePP, set_completion_safePP);
349   AioCompletion *my_completion_null = NULL;
350   ASSERT_NE(my_completion, my_completion_null);
351   char buf[128];
352   memset(buf, 0xcc, sizeof(buf));
353   bufferlist bl1;
354   bl1.append(buf, sizeof(buf));
355   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
356                                my_completion, bl1, sizeof(buf), 0));
357   TestAlarm alarm;
358   ASSERT_EQ(0, my_completion->wait_for_safe());
359   ASSERT_EQ(0, my_completion->get_return_value());
360   delete my_completion;
361 }
362
363 TEST(LibRadosAio, RoundTrip) {
364   AioTestData test_data;
365   rados_completion_t my_completion;
366   ASSERT_EQ("", test_data.init());
367   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
368               set_completion_complete, set_completion_safe, &my_completion));
369   char buf[128];
370   memset(buf, 0xcc, sizeof(buf));
371   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
372                                my_completion, buf, sizeof(buf), 0));
373   {
374     TestAlarm alarm;
375     sem_wait(test_data.m_sem);
376     sem_wait(test_data.m_sem);
377   }
378   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
379   char buf2[256];
380   memset(buf2, 0, sizeof(buf2));
381   rados_completion_t my_completion2;
382   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
383               set_completion_complete, set_completion_safe, &my_completion2));
384   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
385                               my_completion2, buf2, sizeof(buf2), 0));
386   {
387     TestAlarm alarm;
388     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
389   }
390   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
391   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
392   rados_aio_release(my_completion);
393   rados_aio_release(my_completion2);
394 }
395
396 TEST(LibRadosAio, RoundTrip2) {
397   AioTestData test_data;
398   rados_completion_t my_completion;
399   ASSERT_EQ("", test_data.init());
400   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
401               set_completion_complete, set_completion_safe, &my_completion));
402   char buf[128];
403   memset(buf, 0xcc, sizeof(buf));
404   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
405                                my_completion, buf, sizeof(buf), 0));
406   {
407     TestAlarm alarm;
408     sem_wait(test_data.m_sem);
409     sem_wait(test_data.m_sem);
410   }
411   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
412   char buf2[128];
413   memset(buf2, 0, sizeof(buf2));
414   rados_completion_t my_completion2;
415   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
416               set_completion_complete, set_completion_safe, &my_completion2));
417   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
418                               my_completion2, buf2, sizeof(buf2), 0));
419   {
420     TestAlarm alarm;
421     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
422   }
423   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
424   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
425   rados_aio_release(my_completion);
426   rados_aio_release(my_completion2);
427 }
428
429 TEST(LibRadosAio, RoundTrip3) {
430   AioTestData test_data;
431   rados_completion_t my_completion;
432   ASSERT_EQ("", test_data.init());
433   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
434               set_completion_complete, set_completion_safe, &my_completion));
435   char buf[128];
436   memset(buf, 0xcc, sizeof(buf));
437
438   rados_write_op_t op1 = rados_create_write_op();
439   rados_write_op_write(op1, buf, sizeof(buf), 0);
440   rados_write_op_set_alloc_hint2(op1, 0, 0, LIBRADOS_OP_FLAG_FADVISE_DONTNEED); 
441   ASSERT_EQ(0, rados_aio_write_op_operate(op1, test_data.m_ioctx, my_completion,
442                                           "foo", NULL, 0));
443   rados_release_write_op(op1);
444
445   {
446     TestAlarm alarm;
447     sem_wait(test_data.m_sem);
448     sem_wait(test_data.m_sem);
449   }
450
451   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
452   rados_aio_release(my_completion);
453
454   char buf2[128];
455   memset(buf2, 0, sizeof(buf2));
456   rados_completion_t my_completion2;
457   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
458               set_completion_complete, set_completion_safe, &my_completion2));
459
460   rados_read_op_t op2 = rados_create_read_op();
461   rados_read_op_read(op2, 0, sizeof(buf2), buf2, NULL, NULL);
462   rados_read_op_set_flags(op2, LIBRADOS_OP_FLAG_FADVISE_NOCACHE |
463                                LIBRADOS_OP_FLAG_FADVISE_RANDOM);
464   __le32 init_value = -1;
465   __le32 checksum[2];
466   rados_read_op_checksum(op2, LIBRADOS_CHECKSUM_TYPE_CRC32C,
467                          reinterpret_cast<char *>(&init_value),
468                          sizeof(init_value), 0, 0, 0,
469                          reinterpret_cast<char *>(&checksum),
470                          sizeof(checksum), NULL);
471   ASSERT_EQ(0, rados_aio_read_op_operate(op2, test_data.m_ioctx, my_completion2,
472                                          "foo", 0));
473   rados_release_read_op(op2);
474   
475   {
476     TestAlarm alarm;
477     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
478   }
479   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
480   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
481   rados_aio_release(my_completion2);
482
483   bufferlist bl;
484   bl.append(buf, sizeof(buf));
485   ASSERT_EQ(1U, checksum[0]);
486   ASSERT_EQ(bl.crc32c(-1), checksum[1]);
487 }
488
489 TEST(LibRadosAio, RoundTripPP) {
490   AioTestDataPP test_data;
491   ASSERT_EQ("", test_data.init());
492   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
493           (void*)&test_data, set_completion_completePP, set_completion_safePP);
494   AioCompletion *my_completion_null = NULL;
495   ASSERT_NE(my_completion, my_completion_null);
496   char buf[128];
497   memset(buf, 0xcc, sizeof(buf));
498   bufferlist bl1;
499   bl1.append(buf, sizeof(buf));
500   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
501                                            bl1, sizeof(buf), 0));
502   {
503     TestAlarm alarm;
504     sem_wait(test_data.m_sem);
505     sem_wait(test_data.m_sem);
506   }
507   ASSERT_EQ(0, my_completion->get_return_value());
508   bufferlist bl2;
509   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
510           (void*)&test_data, set_completion_completePP, set_completion_safePP);
511   ASSERT_NE(my_completion2, my_completion_null);
512   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
513                               my_completion2, &bl2, sizeof(buf), 0));
514   {
515     TestAlarm alarm;
516     ASSERT_EQ(0, my_completion2->wait_for_complete());
517   }
518   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
519   ASSERT_EQ(sizeof(buf), bl2.length());
520   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
521   delete my_completion;
522   delete my_completion2;
523 }
524
525 TEST(LibRadosAio, RoundTripPP2) {
526   AioTestDataPP test_data;
527   ASSERT_EQ("", test_data.init());
528   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
529           (void*)&test_data, set_completion_completePP, set_completion_safePP);
530   AioCompletion *my_completion_null = NULL;
531   ASSERT_NE(my_completion, my_completion_null);
532   char buf[128];
533   memset(buf, 0xcc, sizeof(buf));
534   bufferlist bl1;
535   bl1.append(buf, sizeof(buf));
536   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
537                                            bl1, sizeof(buf), 0));
538   {
539     TestAlarm alarm;
540     sem_wait(test_data.m_sem);
541     sem_wait(test_data.m_sem);
542   }
543   ASSERT_EQ(0, my_completion->get_return_value());
544   bufferlist bl2;
545   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
546           (void*)&test_data, set_completion_completePP, set_completion_safePP);
547   ASSERT_NE(my_completion2, my_completion_null);
548   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
549                               my_completion2, &bl2, sizeof(buf), 0));
550   {
551     TestAlarm alarm;
552     ASSERT_EQ(0, my_completion2->wait_for_safe());
553     ASSERT_EQ(0, my_completion2->wait_for_complete());
554   }
555   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
556   ASSERT_EQ(sizeof(buf), bl2.length());
557   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
558   delete my_completion;
559   delete my_completion2;
560 }
561
562 //using ObjectWriteOperation/ObjectReadOperation with iohint
563 TEST(LibRadosAio, RoundTripPP3)
564 {
565   Rados cluster;
566   std::string pool_name = get_temp_pool_name();
567   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
568   IoCtx ioctx;
569   cluster.ioctx_create(pool_name.c_str(), ioctx);
570
571   boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
572   ObjectWriteOperation op;
573   char buf[128];
574   memset(buf, 0xcc, sizeof(buf));
575   bufferlist bl;
576   bl.append(buf, sizeof(buf));
577
578   op.write(0, bl);
579   op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
580   ioctx.aio_operate("test_obj", my_completion1.get(), &op);
581   {
582     TestAlarm alarm;
583     ASSERT_EQ(0, my_completion1->wait_for_complete());
584   }
585   EXPECT_EQ(0, my_completion1->get_return_value());
586
587   boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
588   bl.clear();
589   ObjectReadOperation op1;
590   op1.read(0, sizeof(buf), &bl, NULL);
591   op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
592   bufferlist init_value_bl;
593   ::encode(static_cast<int32_t>(-1), init_value_bl);
594   bufferlist csum_bl;
595   op1.checksum(LIBRADOS_CHECKSUM_TYPE_CRC32C, init_value_bl,
596                0, 0, 0, &csum_bl, nullptr);
597   ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
598   {
599     TestAlarm alarm;
600     ASSERT_EQ(0, my_completion2->wait_for_complete());
601   }
602   EXPECT_EQ(0, my_completion2->get_return_value());
603   ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
604
605   ASSERT_EQ(8U, csum_bl.length());
606   auto csum_bl_it = csum_bl.begin();
607   uint32_t csum_count;
608   uint32_t csum;
609   ::decode(csum_count, csum_bl_it);
610   ASSERT_EQ(1U, csum_count);
611   ::decode(csum, csum_bl_it);
612   ASSERT_EQ(bl.crc32c(-1), csum);
613   ioctx.remove("test_obj");
614   destroy_one_pool_pp(pool_name, cluster);
615 }
616
617 TEST(LibRadosAio, RoundTripSparseReadPP) {
618   AioTestDataPP test_data;
619   ASSERT_EQ("", test_data.init());
620   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
621           (void*)&test_data, set_completion_completePP, set_completion_safePP);
622   AioCompletion *my_completion_null = NULL;
623   ASSERT_NE(my_completion, my_completion_null);
624   char buf[128];
625   memset(buf, 0xcc, sizeof(buf));
626   bufferlist bl1;
627   bl1.append(buf, sizeof(buf));
628   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
629                                            bl1, sizeof(buf), 0));
630   {
631     TestAlarm alarm;
632     sem_wait(test_data.m_sem);
633     sem_wait(test_data.m_sem);
634   }
635   ASSERT_EQ(0, my_completion->get_return_value());
636   std::map<uint64_t, uint64_t> extents;
637   bufferlist bl2;
638   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
639           (void*)&test_data, set_completion_completePP, set_completion_safePP);
640   ASSERT_NE(my_completion2, my_completion_null);
641   ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read("foo",
642                               my_completion2, &extents, &bl2, sizeof(buf), 0));
643   {
644     TestAlarm alarm;
645     ASSERT_EQ(0, my_completion2->wait_for_complete());
646   }
647   ASSERT_EQ(0, my_completion2->get_return_value());
648   assert_eq_sparse(bl1, extents, bl2);
649   delete my_completion;
650   delete my_completion2;
651 }
652
653 TEST(LibRadosAio, RoundTripAppend) {
654   AioTestData test_data;
655   rados_completion_t my_completion, my_completion2, my_completion3;
656   ASSERT_EQ("", test_data.init());
657   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
658               set_completion_complete, set_completion_safe, &my_completion));
659   char buf[128];
660   memset(buf, 0xcc, sizeof(buf));
661   ASSERT_EQ(0, rados_aio_append(test_data.m_ioctx, "foo",
662                                my_completion, buf, sizeof(buf)));
663   {
664     TestAlarm alarm;
665     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
666   }
667   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
668   char buf2[128];
669   memset(buf2, 0xdd, sizeof(buf2));
670   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
671               set_completion_complete, set_completion_safe, &my_completion2));
672   ASSERT_EQ(0, rados_aio_append(test_data.m_ioctx, "foo",
673                                my_completion2, buf2, sizeof(buf2)));
674   {
675     TestAlarm alarm;
676     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
677   }
678   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
679   char buf3[sizeof(buf) + sizeof(buf2)];
680   memset(buf3, 0, sizeof(buf3));
681   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
682               set_completion_complete, set_completion_safe, &my_completion3));
683   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
684                               my_completion3, buf3, sizeof(buf3), 0));
685   {
686     TestAlarm alarm;
687     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
688   }
689   ASSERT_EQ((int)sizeof(buf3), rados_aio_get_return_value(my_completion3));
690   ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
691   ASSERT_EQ(0, memcmp(buf3 + sizeof(buf), buf2, sizeof(buf2)));
692   rados_aio_release(my_completion);
693   rados_aio_release(my_completion2);
694   rados_aio_release(my_completion3);
695 }
696
697 TEST(LibRadosAio, RoundTripAppendPP) {
698   AioTestDataPP test_data;
699   ASSERT_EQ("", test_data.init());
700   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
701           (void*)&test_data, set_completion_complete, set_completion_safe);
702   AioCompletion *my_completion_null = NULL;
703   ASSERT_NE(my_completion, my_completion_null);
704   char buf[128];
705   memset(buf, 0xcc, sizeof(buf));
706   bufferlist bl1;
707   bl1.append(buf, sizeof(buf));
708   ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion,
709                                             bl1, sizeof(buf)));
710   {
711     TestAlarm alarm;
712     ASSERT_EQ(0, my_completion->wait_for_complete());
713   }
714   ASSERT_EQ(0, my_completion->get_return_value());
715   char buf2[128];
716   memset(buf2, 0xdd, sizeof(buf2));
717   bufferlist bl2;
718   bl2.append(buf2, sizeof(buf2));
719   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
720           (void*)&test_data, set_completion_complete, set_completion_safe);
721   ASSERT_NE(my_completion2, my_completion_null);
722   ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion2,
723                                             bl2, sizeof(buf2)));
724   {
725     TestAlarm alarm;
726     ASSERT_EQ(0, my_completion2->wait_for_complete());
727   }
728   ASSERT_EQ(0, my_completion2->get_return_value());
729   bufferlist bl3;
730   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
731           (void*)&test_data, set_completion_complete, set_completion_safe);
732   ASSERT_NE(my_completion3, my_completion_null);
733   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
734                               my_completion3, &bl3, 2 * sizeof(buf), 0));
735   {
736     TestAlarm alarm;
737     ASSERT_EQ(0, my_completion3->wait_for_complete());
738   }
739   ASSERT_EQ((int)(sizeof(buf) * 2), my_completion3->get_return_value());
740   ASSERT_EQ(sizeof(buf) * 2, bl3.length());
741   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
742   ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
743   delete my_completion;
744   delete my_completion2;
745   delete my_completion3;
746 }
747
748 TEST(LibRadosAio, RemoveTest) {
749   char buf[128];
750   char buf2[sizeof(buf)];
751   rados_completion_t my_completion;
752   AioTestData test_data;
753   ASSERT_EQ("", test_data.init());
754   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
755               set_completion_complete, set_completion_safe, &my_completion));
756   memset(buf, 0xaa, sizeof(buf));
757   ASSERT_EQ(0, rados_append(test_data.m_ioctx, "foo", buf, sizeof(buf)));
758   ASSERT_EQ(0, rados_aio_remove(test_data.m_ioctx, "foo", my_completion));
759   {
760     TestAlarm alarm;
761     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
762   }
763   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
764   memset(buf2, 0, sizeof(buf2));
765   ASSERT_EQ(-ENOENT, rados_read(test_data.m_ioctx, "foo", buf2, sizeof(buf2), 0));
766   rados_aio_release(my_completion);
767 }
768
769 TEST(LibRadosAioPP, RemoveTestPP) {
770   char buf[128];
771   memset(buf, 0xaa, sizeof(buf));
772   bufferlist bl1;
773   bl1.append(buf, sizeof(buf));
774   AioTestDataPP test_data;
775   ASSERT_EQ("", test_data.init());
776   ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
777   boost::scoped_ptr<AioCompletion> my_completion
778     (test_data.m_cluster.aio_create_completion
779      ((void*)&test_data, set_completion_completePP, set_completion_safePP));
780   ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion.get()));
781   {
782     TestAlarm alarm;
783     ASSERT_EQ(0, my_completion->wait_for_complete());
784   }
785   ASSERT_EQ(0, my_completion->get_return_value());
786   bufferlist bl2;
787   ASSERT_EQ(-ENOENT, test_data.m_ioctx.read("foo", bl2, sizeof(buf), 0));
788 }
789
790 TEST(LibRadosAio, XattrsRoundTrip) {
791   char buf[128];
792   char attr1[] = "attr1";
793   char attr1_buf[] = "foo bar baz";
794   // append
795   AioTestData test_data;
796   ASSERT_EQ("", test_data.init());
797   memset(buf, 0xaa, sizeof(buf));
798   ASSERT_EQ(0, rados_append(test_data.m_ioctx, "foo", buf, sizeof(buf)));
799   // async getxattr
800   rados_completion_t my_completion;
801   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
802               set_completion_complete, set_completion_safe, &my_completion));
803   ASSERT_EQ(0, rados_aio_getxattr(test_data.m_ioctx, "foo", my_completion, attr1, buf, sizeof(buf)));
804   {
805     TestAlarm alarm;
806     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
807   }
808   ASSERT_EQ(-ENODATA, rados_aio_get_return_value(my_completion));
809   rados_aio_release(my_completion);
810   // async setxattr
811   rados_completion_t my_completion2;
812   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
813               set_completion_complete, set_completion_safe, &my_completion2));
814   ASSERT_EQ(0, rados_aio_setxattr(test_data.m_ioctx, "foo", my_completion2, attr1, attr1_buf, sizeof(attr1_buf)));
815   {
816     TestAlarm alarm;
817     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
818   }
819   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
820   rados_aio_release(my_completion2);
821   // async getxattr
822   rados_completion_t my_completion3;
823   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
824               set_completion_complete, set_completion_safe, &my_completion3));
825   ASSERT_EQ(0, rados_aio_getxattr(test_data.m_ioctx, "foo", my_completion3, attr1, buf, sizeof(buf)));
826   {
827     TestAlarm alarm;
828     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
829   }
830   ASSERT_EQ((int)sizeof(attr1_buf), rados_aio_get_return_value(my_completion3));
831   rados_aio_release(my_completion3);
832   // check content of attribute
833   ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
834 }
835
836 TEST(LibRadosAioPP, XattrsRoundTripPP) {
837   char buf[128];
838   char attr1[] = "attr1";
839   char attr1_buf[] = "foo bar baz";
840   memset(buf, 0xaa, sizeof(buf));
841   bufferlist bl1;
842   bl1.append(buf, sizeof(buf));
843   AioTestDataPP test_data;
844   ASSERT_EQ("", test_data.init());
845   ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
846   bufferlist bl2;
847   // async getxattr
848   boost::scoped_ptr<AioCompletion> my_completion
849     (test_data.m_cluster.aio_create_completion
850      ((void*)&test_data, set_completion_completePP, set_completion_safePP));
851   ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion.get(), attr1, bl2));
852   {
853     TestAlarm alarm;
854     ASSERT_EQ(0, my_completion->wait_for_complete());
855   }
856   ASSERT_EQ(-ENODATA, my_completion->get_return_value());
857   // append
858   bufferlist bl3;
859   bl3.append(attr1_buf, sizeof(attr1_buf));
860   // async setxattr
861   AioTestDataPP test_data2;
862   ASSERT_EQ("", test_data2.init());
863   boost::scoped_ptr<AioCompletion> my_completion2
864     (test_data.m_cluster.aio_create_completion
865      ((void*)&test_data2, set_completion_completePP, set_completion_safePP));
866   ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo", my_completion2.get(), attr1, bl3));
867   {
868     TestAlarm alarm;
869     ASSERT_EQ(0, my_completion2->wait_for_complete());
870   }
871   ASSERT_EQ(0, my_completion2->get_return_value());
872   // async getxattr
873   bufferlist bl4;
874   AioTestDataPP test_data3;
875   ASSERT_EQ("", test_data3.init());
876   boost::scoped_ptr<AioCompletion> my_completion3
877     (test_data.m_cluster.aio_create_completion
878      ((void*)&test_data3, set_completion_completePP, set_completion_safePP));
879   ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion3.get(), attr1, bl4));
880   {
881     TestAlarm alarm;
882     ASSERT_EQ(0, my_completion3->wait_for_complete());
883   }
884   ASSERT_EQ((int)sizeof(attr1_buf), my_completion3->get_return_value());
885   // check content of attribute
886   ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
887 }
888
889 TEST(LibRadosAio, RmXattr) {
890   char buf[128];
891   char attr1[] = "attr1";
892   char attr1_buf[] = "foo bar baz";
893   // append
894   memset(buf, 0xaa, sizeof(buf));
895   AioTestData test_data;
896   ASSERT_EQ("", test_data.init());
897   ASSERT_EQ(0, rados_append(test_data.m_ioctx, "foo", buf, sizeof(buf)));  
898   // async setxattr
899   rados_completion_t my_completion;
900   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
901               set_completion_complete, set_completion_safe, &my_completion));
902   ASSERT_EQ(0, rados_aio_setxattr(test_data.m_ioctx, "foo", my_completion, attr1, attr1_buf, sizeof(attr1_buf)));
903   {
904     TestAlarm alarm;
905     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
906   }
907   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
908   rados_aio_release(my_completion);
909   // async rmxattr
910   rados_completion_t my_completion2;
911   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
912             set_completion_complete, set_completion_safe, &my_completion2));
913   ASSERT_EQ(0, rados_aio_rmxattr(test_data.m_ioctx, "foo", my_completion2, attr1));
914   {
915     TestAlarm alarm;
916     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
917   }
918   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
919   rados_aio_release(my_completion2);
920   // async getxattr after deletion
921   rados_completion_t my_completion3;
922   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
923             set_completion_complete, set_completion_safe, &my_completion3));
924   ASSERT_EQ(0, rados_aio_getxattr(test_data.m_ioctx, "foo", my_completion3, attr1, buf, sizeof(buf)));
925   {
926     TestAlarm alarm;
927     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
928   }
929   ASSERT_EQ(-ENODATA, rados_aio_get_return_value(my_completion3));
930   rados_aio_release(my_completion3);
931   // Test rmxattr on a removed object
932   char buf2[128];
933   char attr2[] = "attr2";
934   char attr2_buf[] = "foo bar baz";
935   memset(buf2, 0xbb, sizeof(buf2));
936   ASSERT_EQ(0, rados_write(test_data.m_ioctx, "foo_rmxattr", buf2, sizeof(buf2), 0));
937   // asynx setxattr
938   rados_completion_t my_completion4;
939   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
940             set_completion_complete, set_completion_safe, &my_completion4));
941   ASSERT_EQ(0, rados_aio_setxattr(test_data.m_ioctx, "foo_rmxattr", my_completion4, attr2, attr2_buf, sizeof(attr2_buf)));
942   {
943     TestAlarm alarm;
944     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion4));
945   }
946   ASSERT_EQ(0, rados_aio_get_return_value(my_completion4));
947   rados_aio_release(my_completion4);
948   // remove object
949   ASSERT_EQ(0, rados_remove(test_data.m_ioctx, "foo_rmxattr"));
950   // async rmxattr on non existing object
951   rados_completion_t my_completion5;
952   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
953             set_completion_complete, set_completion_safe, &my_completion5));
954   ASSERT_EQ(0, rados_aio_rmxattr(test_data.m_ioctx, "foo_rmxattr", my_completion5, attr2));
955   {
956     TestAlarm alarm;
957     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion5));
958   }
959   ASSERT_EQ(-ENOENT, rados_aio_get_return_value(my_completion5));
960   rados_aio_release(my_completion5);
961 }
962
963 TEST(LibRadosAioPP, RmXattrPP) {
964   char buf[128];
965   char attr1[] = "attr1";
966   char attr1_buf[] = "foo bar baz";
967   memset(buf, 0xaa, sizeof(buf));
968   bufferlist bl1;
969   bl1.append(buf, sizeof(buf));
970   AioTestDataPP test_data;
971   ASSERT_EQ("", test_data.init());
972   ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
973   // async setxattr
974   bufferlist bl2;
975   bl2.append(attr1_buf, sizeof(attr1_buf));
976   boost::scoped_ptr<AioCompletion> my_completion
977     (test_data.m_cluster.aio_create_completion
978      ((void*)&test_data, set_completion_completePP, set_completion_safePP));
979   ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo", my_completion.get(), attr1, bl2));
980   {
981     TestAlarm alarm;
982     ASSERT_EQ(0, my_completion->wait_for_complete());
983   }
984   ASSERT_EQ(0, my_completion->get_return_value());
985   // async rmxattr
986   AioTestDataPP test_data2;
987   ASSERT_EQ("", test_data2.init());
988   boost::scoped_ptr<AioCompletion> my_completion2
989     (test_data.m_cluster.aio_create_completion
990      ((void*)&test_data2, set_completion_completePP, set_completion_safePP));
991   ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr("foo", my_completion2.get(), attr1));
992   {
993     TestAlarm alarm;
994     ASSERT_EQ(0, my_completion2->wait_for_complete());
995   }
996   ASSERT_EQ(0, my_completion2->get_return_value());
997   // async getxattr
998   AioTestDataPP test_data3;
999   ASSERT_EQ("", test_data3.init());
1000   boost::scoped_ptr<AioCompletion> my_completion3
1001     (test_data.m_cluster.aio_create_completion
1002      ((void*)&test_data3, set_completion_completePP, set_completion_safePP));
1003   bufferlist bl3;
1004   ASSERT_EQ(0, test_data.m_ioctx.aio_getxattr("foo", my_completion3.get(), attr1, bl3));
1005   {
1006     TestAlarm alarm;
1007     ASSERT_EQ(0, my_completion3->wait_for_complete());
1008   }
1009   ASSERT_EQ(-ENODATA, my_completion3->get_return_value());
1010   // Test rmxattr on a removed object
1011   char buf2[128];
1012   char attr2[] = "attr2";
1013   char attr2_buf[] = "foo bar baz";
1014   memset(buf2, 0xbb, sizeof(buf2));
1015   bufferlist bl21;
1016   bl21.append(buf, sizeof(buf));
1017   ASSERT_EQ(0, test_data.m_ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
1018   bufferlist bl22;
1019   bl22.append(attr2_buf, sizeof(attr2_buf));
1020   // async setxattr
1021   AioTestDataPP test_data4;
1022   ASSERT_EQ("", test_data4.init());
1023   boost::scoped_ptr<AioCompletion> my_completion4
1024     (test_data.m_cluster.aio_create_completion
1025      ((void*)&test_data4, set_completion_completePP, set_completion_safePP));
1026   ASSERT_EQ(0, test_data.m_ioctx.aio_setxattr("foo_rmxattr", my_completion4.get(), attr2, bl22));
1027   {
1028     TestAlarm alarm;
1029     ASSERT_EQ(0, my_completion4->wait_for_complete());
1030   }
1031   ASSERT_EQ(0, my_completion4->get_return_value());
1032   // remove object
1033   ASSERT_EQ(0, test_data.m_ioctx.remove("foo_rmxattr"));
1034   // async rmxattr on non existing object
1035   AioTestDataPP test_data5;
1036   ASSERT_EQ("", test_data5.init());
1037   boost::scoped_ptr<AioCompletion> my_completion5
1038     (test_data.m_cluster.aio_create_completion
1039      ((void*)&test_data5, set_completion_completePP, set_completion_safePP));
1040   ASSERT_EQ(0, test_data.m_ioctx.aio_rmxattr("foo_rmxattr", my_completion5.get(), attr2));
1041   {
1042     TestAlarm alarm;
1043     ASSERT_EQ(0, my_completion5->wait_for_complete());
1044   }
1045   ASSERT_EQ(-ENOENT, my_completion5->get_return_value());
1046 }
1047
1048 TEST(LibRadosAio, XattrIter) {
1049   AioTestData test_data;
1050   ASSERT_EQ("", test_data.init());
1051   // Create an object with 2 attributes
1052   char buf[128];
1053   char attr1[] = "attr1";
1054   char attr1_buf[] = "foo bar baz";
1055   char attr2[] = "attr2";
1056   char attr2_buf[256];
1057   for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
1058     attr2_buf[j] = j % 0xff;
1059   }
1060   memset(buf, 0xaa, sizeof(buf));
1061   ASSERT_EQ(0, rados_append(test_data.m_ioctx, "foo", buf, sizeof(buf)));
1062   ASSERT_EQ(0, rados_setxattr(test_data.m_ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
1063   ASSERT_EQ(0, rados_setxattr(test_data.m_ioctx, "foo", attr2, attr2_buf, sizeof(attr2_buf)));
1064   // call async version of getxattrs and wait for completion
1065   rados_completion_t my_completion;
1066   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1067             set_completion_complete, set_completion_safe, &my_completion));
1068   rados_xattrs_iter_t iter;
1069   ASSERT_EQ(0, rados_aio_getxattrs(test_data.m_ioctx, "foo", my_completion, &iter));
1070   {
1071     TestAlarm alarm;
1072     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
1073   }
1074   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1075   // loop over attributes
1076   int num_seen = 0;
1077   while (true) {
1078     const char *name;
1079     const char *val;
1080     size_t len;
1081     ASSERT_EQ(0, rados_getxattrs_next(iter, &name, &val, &len));
1082     if (name == NULL) {
1083       break;
1084     }
1085     ASSERT_LT(num_seen, 2);
1086     if ((strcmp(name, attr1) == 0) && (val != NULL) && (memcmp(val, attr1_buf, len) == 0)) {
1087       num_seen++;
1088       continue;
1089     }
1090     else if ((strcmp(name, attr2) == 0) && (val != NULL) && (memcmp(val, attr2_buf, len) == 0)) {
1091       num_seen++;
1092       continue;
1093     }
1094     else {
1095       ASSERT_EQ(0, 1);
1096     }
1097   }
1098   rados_getxattrs_end(iter);
1099 }
1100
1101 TEST(LibRadosIoPP, XattrListPP) {
1102   AioTestDataPP test_data;
1103   ASSERT_EQ("", test_data.init());
1104   // create an object with 2 attributes
1105   char buf[128];
1106   char attr1[] = "attr1";
1107   char attr1_buf[] = "foo bar baz";
1108   char attr2[] = "attr2";
1109   char attr2_buf[256];
1110   for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
1111     attr2_buf[j] = j % 0xff;
1112   }
1113   memset(buf, 0xaa, sizeof(buf));
1114   bufferlist bl1;
1115   bl1.append(buf, sizeof(buf));
1116   ASSERT_EQ(0, test_data.m_ioctx.append("foo", bl1, sizeof(buf)));
1117   bufferlist bl2;
1118   bl2.append(attr1_buf, sizeof(attr1_buf));
1119   ASSERT_EQ(0, test_data.m_ioctx.setxattr("foo", attr1, bl2));
1120   bufferlist bl3;
1121   bl3.append(attr2_buf, sizeof(attr2_buf));
1122   ASSERT_EQ(0, test_data.m_ioctx.setxattr("foo", attr2, bl3));
1123   // call async version of getxattrs
1124   boost::scoped_ptr<AioCompletion> my_completion
1125     (test_data.m_cluster.aio_create_completion
1126      ((void*)&test_data, set_completion_completePP, set_completion_safePP));
1127   std::map<std::string, bufferlist> attrset;
1128   ASSERT_EQ(0, test_data.m_ioctx.aio_getxattrs("foo", my_completion.get(), attrset));
1129   {
1130     TestAlarm alarm;
1131     ASSERT_EQ(0, my_completion->wait_for_complete());
1132   }
1133   ASSERT_EQ(0, my_completion->get_return_value());
1134   for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
1135        i != attrset.end(); ++i) {
1136     if (i->first == string(attr1)) {
1137       ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
1138     }
1139     else if (i->first == string(attr2)) {
1140       ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
1141     }
1142     else {
1143       ASSERT_EQ(0, 1);
1144     }
1145   }
1146 }
1147
1148 TEST(LibRadosAio, IsComplete) {
1149   AioTestData test_data;
1150   rados_completion_t my_completion;
1151   ASSERT_EQ("", test_data.init());
1152   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1153               set_completion_complete, set_completion_safe, &my_completion));
1154   char buf[128];
1155   memset(buf, 0xcc, sizeof(buf));
1156   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1157                                my_completion, buf, sizeof(buf), 0));
1158   {
1159     TestAlarm alarm;
1160     sem_wait(test_data.m_sem);
1161     sem_wait(test_data.m_sem);
1162   }
1163   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1164   char buf2[128];
1165   memset(buf2, 0, sizeof(buf2));
1166   rados_completion_t my_completion2;
1167   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1168               set_completion_complete, set_completion_safe, &my_completion2));
1169   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
1170                               my_completion2, buf2, sizeof(buf2), 0));
1171   {
1172     TestAlarm alarm;
1173
1174     // Busy-wait until the AIO completes.
1175     // Normally we wouldn't do this, but we want to test rados_aio_is_complete.
1176     while (true) {
1177       int is_complete = rados_aio_is_complete(my_completion2);
1178       if (is_complete)
1179         break;
1180     }
1181   }
1182   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
1183   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
1184   rados_aio_release(my_completion);
1185   rados_aio_release(my_completion2);
1186 }
1187
1188 TEST(LibRadosAio, IsCompletePP) {
1189   AioTestDataPP test_data;
1190   ASSERT_EQ("", test_data.init());
1191   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1192           (void*)&test_data, set_completion_complete, set_completion_safe);
1193   AioCompletion *my_completion_null = NULL;
1194   ASSERT_NE(my_completion, my_completion_null);
1195   char buf[128];
1196   memset(buf, 0xcc, sizeof(buf));
1197   bufferlist bl1;
1198   bl1.append(buf, sizeof(buf));
1199   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1200                                            bl1, sizeof(buf), 0));
1201   {
1202     TestAlarm alarm;
1203     sem_wait(test_data.m_sem);
1204     sem_wait(test_data.m_sem);
1205   }
1206   ASSERT_EQ(0, my_completion->get_return_value());
1207   bufferlist bl2;
1208   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1209           (void*)&test_data, set_completion_complete, set_completion_safe);
1210   ASSERT_NE(my_completion2, my_completion_null);
1211   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
1212                                           &bl2, sizeof(buf), 0));
1213   {
1214     TestAlarm alarm;
1215
1216     // Busy-wait until the AIO completes.
1217     // Normally we wouldn't do this, but we want to test is_complete.
1218     while (true) {
1219       int is_complete = my_completion2->is_complete();
1220       if (is_complete)
1221         break;
1222     }
1223   }
1224   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1225   ASSERT_EQ(sizeof(buf), bl2.length());
1226   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
1227   delete my_completion;
1228   delete my_completion2;
1229 }
1230
1231 TEST(LibRadosAio, IsSafe) {
1232   AioTestData test_data;
1233   rados_completion_t my_completion;
1234   ASSERT_EQ("", test_data.init());
1235   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1236               set_completion_complete, set_completion_safe, &my_completion));
1237   char buf[128];
1238   memset(buf, 0xcc, sizeof(buf));
1239   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1240                                my_completion, buf, sizeof(buf), 0));
1241   {
1242     TestAlarm alarm;
1243
1244     // Busy-wait until the AIO completes.
1245     // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
1246     while (true) {
1247       int is_safe = rados_aio_is_safe(my_completion);
1248       if (is_safe)
1249         break;
1250     }
1251   }
1252   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1253   char buf2[128];
1254   memset(buf2, 0, sizeof(buf2));
1255   rados_completion_t my_completion2;
1256   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1257               set_completion_complete, set_completion_safe, &my_completion2));
1258   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
1259                               my_completion2, buf2, sizeof(buf2), 0));
1260   {
1261     TestAlarm alarm;
1262     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1263   }
1264   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
1265   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
1266   rados_aio_release(my_completion);
1267   rados_aio_release(my_completion2);
1268 }
1269
1270 TEST(LibRadosAio, IsSafePP) {
1271   AioTestDataPP test_data;
1272   ASSERT_EQ("", test_data.init());
1273   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1274           (void*)&test_data, set_completion_complete, set_completion_safe);
1275   AioCompletion *my_completion_null = NULL;
1276   ASSERT_NE(my_completion, my_completion_null);
1277   char buf[128];
1278   memset(buf, 0xcc, sizeof(buf));
1279   bufferlist bl1;
1280   bl1.append(buf, sizeof(buf));
1281   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1282                                            bl1, sizeof(buf), 0));
1283   {
1284     TestAlarm alarm;
1285
1286     // Busy-wait until the AIO completes.
1287     // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
1288     while (true) {
1289       int is_safe = my_completion->is_safe();
1290       if (is_safe)
1291         break;
1292     }
1293   }
1294   ASSERT_EQ(0, my_completion->get_return_value());
1295   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1296           (void*)&test_data, set_completion_complete, set_completion_safe);
1297   bufferlist bl2;
1298   ASSERT_NE(my_completion2, my_completion_null);
1299   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
1300                                           &bl2, sizeof(buf), 0));
1301   {
1302     TestAlarm alarm;
1303     ASSERT_EQ(0, my_completion2->wait_for_complete());
1304   }
1305   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1306   ASSERT_EQ(sizeof(buf), bl2.length());
1307   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
1308   delete my_completion;
1309   delete my_completion2;
1310 }
1311
1312 TEST(LibRadosAio, ReturnValue) {
1313   AioTestData test_data;
1314   rados_completion_t my_completion;
1315   ASSERT_EQ("", test_data.init());
1316   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1317               set_completion_complete, set_completion_safe, &my_completion));
1318   char buf[128];
1319   memset(buf, 0, sizeof(buf));
1320   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "nonexistent",
1321                                my_completion, buf, sizeof(buf), 0));
1322   {
1323     TestAlarm alarm;
1324     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
1325   }
1326   ASSERT_EQ(-ENOENT, rados_aio_get_return_value(my_completion));
1327   rados_aio_release(my_completion);
1328 }
1329
1330 TEST(LibRadosAio, ReturnValuePP) {
1331   AioTestDataPP test_data;
1332   ASSERT_EQ("", test_data.init());
1333   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1334           (void*)&test_data, set_completion_complete, set_completion_safe);
1335   AioCompletion *my_completion_null = NULL;
1336   ASSERT_NE(my_completion, my_completion_null);
1337   bufferlist bl1;
1338   ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent",
1339                                my_completion, &bl1, 128, 0));
1340   {
1341     TestAlarm alarm;
1342     ASSERT_EQ(0, my_completion->wait_for_complete());
1343   }
1344   ASSERT_EQ(-ENOENT, my_completion->get_return_value());
1345   delete my_completion;
1346 }
1347
1348 TEST(LibRadosAio, Flush) {
1349   AioTestData test_data;
1350   rados_completion_t my_completion;
1351   ASSERT_EQ("", test_data.init());
1352   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1353               set_completion_complete, set_completion_safe, &my_completion));
1354   char buf[128];
1355   memset(buf, 0xee, sizeof(buf));
1356   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1357                                my_completion, buf, sizeof(buf), 0));
1358   ASSERT_EQ(0, rados_aio_flush(test_data.m_ioctx));
1359   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1360   char buf2[128];
1361   memset(buf2, 0, sizeof(buf2));
1362   rados_completion_t my_completion2;
1363   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1364               set_completion_complete, set_completion_safe, &my_completion2));
1365   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
1366                               my_completion2, buf2, sizeof(buf2), 0));
1367   {
1368     TestAlarm alarm;
1369     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1370   }
1371   ASSERT_EQ((int)sizeof(buf2), rados_aio_get_return_value(my_completion2));
1372   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
1373   rados_aio_release(my_completion);
1374   rados_aio_release(my_completion2);
1375 }
1376
1377 TEST(LibRadosAio, FlushPP) {
1378   AioTestDataPP test_data;
1379   ASSERT_EQ("", test_data.init());
1380   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1381           (void*)&test_data, set_completion_complete, set_completion_safe);
1382   AioCompletion *my_completion_null = NULL;
1383   ASSERT_NE(my_completion, my_completion_null);
1384   char buf[128];
1385   memset(buf, 0xee, sizeof(buf));
1386   bufferlist bl1;
1387   bl1.append(buf, sizeof(buf));
1388   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1389                                            bl1, sizeof(buf), 0));
1390   ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
1391   ASSERT_EQ(0, my_completion->get_return_value());
1392   bufferlist bl2;
1393   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1394           (void*)&test_data, set_completion_complete, set_completion_safe);
1395   ASSERT_NE(my_completion2, my_completion_null);
1396   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
1397                                           &bl2, sizeof(buf), 0));
1398   {
1399     TestAlarm alarm;
1400     ASSERT_EQ(0, my_completion2->wait_for_complete());
1401   }
1402   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1403   ASSERT_EQ(sizeof(buf), bl2.length());
1404   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
1405   delete my_completion;
1406   delete my_completion2;
1407 }
1408
1409 TEST(LibRadosAio, FlushAsync) {
1410   AioTestData test_data;
1411   rados_completion_t my_completion;
1412   ASSERT_EQ("", test_data.init());
1413   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1414               set_completion_complete, set_completion_safe, &my_completion));
1415   rados_completion_t flush_completion;
1416   ASSERT_EQ(0, rados_aio_create_completion(NULL, NULL, NULL, &flush_completion));
1417   char buf[128];
1418   memset(buf, 0xee, sizeof(buf));
1419   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1420                                my_completion, buf, sizeof(buf), 0));
1421   ASSERT_EQ(0, rados_aio_flush_async(test_data.m_ioctx, flush_completion));
1422   {
1423     TestAlarm alarm;
1424     ASSERT_EQ(0, rados_aio_wait_for_complete(flush_completion));
1425     ASSERT_EQ(0, rados_aio_wait_for_safe(flush_completion));
1426   }
1427   ASSERT_EQ(1, rados_aio_is_complete(my_completion));
1428   ASSERT_EQ(1, rados_aio_is_safe(my_completion));
1429   ASSERT_EQ(1, rados_aio_is_complete(flush_completion));
1430   ASSERT_EQ(1, rados_aio_is_safe(flush_completion));
1431   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1432   char buf2[128];
1433   memset(buf2, 0, sizeof(buf2));
1434   rados_completion_t my_completion2;
1435   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1436               set_completion_complete, set_completion_safe, &my_completion2));
1437   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
1438                               my_completion2, buf2, sizeof(buf2), 0));
1439   {
1440     TestAlarm alarm;
1441     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1442   }
1443   ASSERT_EQ((int)sizeof(buf2), rados_aio_get_return_value(my_completion2));
1444   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
1445   rados_aio_release(my_completion);
1446   rados_aio_release(my_completion2);
1447   rados_aio_release(flush_completion);
1448 }
1449
1450 TEST(LibRadosAio, FlushAsyncPP) {
1451   AioTestDataPP test_data;
1452   ASSERT_EQ("", test_data.init());
1453   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1454           (void*)&test_data, set_completion_complete, set_completion_safe);
1455   AioCompletion *flush_completion =
1456       test_data.m_cluster.aio_create_completion(NULL, NULL, NULL);
1457   AioCompletion *my_completion_null = NULL;
1458   ASSERT_NE(my_completion, my_completion_null);
1459   char buf[128];
1460   memset(buf, 0xee, sizeof(buf));
1461   bufferlist bl1;
1462   bl1.append(buf, sizeof(buf));
1463   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1464                                            bl1, sizeof(buf), 0));
1465   ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion));
1466   {
1467       TestAlarm alarm;
1468       ASSERT_EQ(0, flush_completion->wait_for_complete());
1469       ASSERT_EQ(0, flush_completion->wait_for_safe());
1470   }
1471   ASSERT_EQ(1, my_completion->is_complete());
1472   ASSERT_EQ(1, my_completion->is_safe());
1473   ASSERT_EQ(1, flush_completion->is_complete());
1474   ASSERT_EQ(1, flush_completion->is_safe());
1475   ASSERT_EQ(0, my_completion->get_return_value());
1476   bufferlist bl2;
1477   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1478           (void*)&test_data, set_completion_complete, set_completion_safe);
1479   ASSERT_NE(my_completion2, my_completion_null);
1480   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
1481                                           &bl2, sizeof(buf), 0));
1482   {
1483     TestAlarm alarm;
1484     ASSERT_EQ(0, my_completion2->wait_for_complete());
1485   }
1486   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
1487   ASSERT_EQ(sizeof(buf), bl2.length());
1488   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
1489   delete my_completion;
1490   delete my_completion2;
1491   delete flush_completion;
1492 }
1493
1494 TEST(LibRadosAio, RoundTripWriteFull) {
1495   AioTestData test_data;
1496   rados_completion_t my_completion, my_completion2, my_completion3;
1497   ASSERT_EQ("", test_data.init());
1498   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1499               set_completion_complete, set_completion_safe, &my_completion));
1500   char buf[128];
1501   memset(buf, 0xcc, sizeof(buf));
1502   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1503                                my_completion, buf, sizeof(buf), 0));
1504   {
1505     TestAlarm alarm;
1506     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
1507   }
1508   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1509   char buf2[64];
1510   memset(buf2, 0xdd, sizeof(buf2));
1511   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1512               set_completion_complete, set_completion_safe, &my_completion2));
1513   ASSERT_EQ(0, rados_aio_write_full(test_data.m_ioctx, "foo",
1514                                my_completion2, buf2, sizeof(buf2)));
1515   {
1516     TestAlarm alarm;
1517     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1518   }
1519   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
1520   char buf3[sizeof(buf) + sizeof(buf2)];
1521   memset(buf3, 0, sizeof(buf3));
1522   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1523               set_completion_complete, set_completion_safe, &my_completion3));
1524   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
1525                               my_completion3, buf3, sizeof(buf3), 0));
1526   {
1527     TestAlarm alarm;
1528     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
1529   }
1530   ASSERT_EQ((int)sizeof(buf2), rados_aio_get_return_value(my_completion3));
1531   ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2)));
1532   rados_aio_release(my_completion);
1533   rados_aio_release(my_completion2);
1534   rados_aio_release(my_completion3);
1535 }
1536
1537 TEST(LibRadosAio, RoundTripWriteFullPP) {
1538   AioTestDataPP test_data;
1539   ASSERT_EQ("", test_data.init());
1540   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1541           (void*)&test_data, set_completion_complete, set_completion_safe);
1542   AioCompletion *my_completion_null = NULL;
1543   ASSERT_NE(my_completion, my_completion_null);
1544   char buf[128];
1545   memset(buf, 0xcc, sizeof(buf));
1546   bufferlist bl1;
1547   bl1.append(buf, sizeof(buf));
1548   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1549                                            bl1, sizeof(buf), 0));
1550   {
1551     TestAlarm alarm;
1552     ASSERT_EQ(0, my_completion->wait_for_complete());
1553   }
1554   ASSERT_EQ(0, my_completion->get_return_value());
1555   char buf2[64];
1556   memset(buf2, 0xdd, sizeof(buf2));
1557   bufferlist bl2;
1558   bl2.append(buf2, sizeof(buf2));
1559   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1560           (void*)&test_data, set_completion_complete, set_completion_safe);
1561   ASSERT_NE(my_completion2, my_completion_null);
1562   ASSERT_EQ(0, test_data.m_ioctx.aio_write_full("foo", my_completion2, bl2));
1563   {
1564     TestAlarm alarm;
1565     ASSERT_EQ(0, my_completion2->wait_for_complete());
1566   }
1567   ASSERT_EQ(0, my_completion2->get_return_value());
1568   bufferlist bl3;
1569   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
1570           (void*)&test_data, set_completion_complete, set_completion_safe);
1571   ASSERT_NE(my_completion3, my_completion_null);
1572   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
1573                                           &bl3, sizeof(buf), 0));
1574   {
1575     TestAlarm alarm;
1576     ASSERT_EQ(0, my_completion3->wait_for_complete());
1577   }
1578   ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
1579   ASSERT_EQ(sizeof(buf2), bl3.length());
1580   ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
1581   delete my_completion;
1582   delete my_completion2;
1583   delete my_completion3;
1584 }
1585
1586 //using ObjectWriteOperation/ObjectReadOperation with iohint
1587 TEST(LibRadosAio, RoundTripWriteFullPP2)
1588 {
1589   Rados cluster;
1590   std::string pool_name = get_temp_pool_name();
1591   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1592   IoCtx ioctx;
1593   cluster.ioctx_create(pool_name.c_str(), ioctx);
1594
1595   boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
1596   ObjectWriteOperation op;
1597   char buf[128];
1598   memset(buf, 0xcc, sizeof(buf));
1599   bufferlist bl;
1600   bl.append(buf);
1601
1602   op.write_full(bl);
1603   op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
1604   ioctx.aio_operate("test_obj", my_completion1.get(), &op);
1605   {
1606     TestAlarm alarm;
1607     ASSERT_EQ(0, my_completion1->wait_for_complete());
1608   }
1609   EXPECT_EQ(0, my_completion1->get_return_value());
1610
1611   boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
1612   bl.clear();
1613   ObjectReadOperation op1;
1614   op1.read(0, sizeof(buf), &bl, NULL);
1615   op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
1616   ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
1617   {
1618     TestAlarm alarm;
1619     ASSERT_EQ(0, my_completion2->wait_for_complete());
1620   }
1621   EXPECT_EQ(0, my_completion2->get_return_value());
1622   ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
1623
1624   ioctx.remove("test_obj");
1625   destroy_one_pool_pp(pool_name, cluster);
1626 }
1627
1628 TEST(LibRadosAio, RoundTripWriteSame) {
1629   AioTestData test_data;
1630   rados_completion_t my_completion, my_completion2, my_completion3;
1631   ASSERT_EQ("", test_data.init());
1632   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1633               set_completion_complete, set_completion_safe, &my_completion));
1634   char full[128];
1635   memset(full, 0xcc, sizeof(full));
1636   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1637                                my_completion, full, sizeof(full), 0));
1638   {
1639     TestAlarm alarm;
1640     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
1641   }
1642   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1643   /* write the same buf four times */
1644   char buf[32];
1645   size_t ws_write_len = sizeof(full);
1646   memset(buf, 0xdd, sizeof(buf));
1647   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1648               set_completion_complete, set_completion_safe, &my_completion2));
1649   ASSERT_EQ(0, rados_aio_writesame(test_data.m_ioctx, "foo",
1650                                    my_completion2, buf, sizeof(buf),
1651                                    ws_write_len, 0));
1652   {
1653     TestAlarm alarm;
1654     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1655   }
1656   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
1657   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1658               set_completion_complete, set_completion_safe, &my_completion3));
1659   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
1660                               my_completion3, full, sizeof(full), 0));
1661   {
1662     TestAlarm alarm;
1663     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
1664   }
1665   ASSERT_EQ((int)sizeof(full), rados_aio_get_return_value(my_completion3));
1666   for (char *cmp = full; cmp < full + sizeof(full); cmp += sizeof(buf)) {
1667     ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
1668   }
1669   rados_aio_release(my_completion);
1670   rados_aio_release(my_completion2);
1671   rados_aio_release(my_completion3);
1672 }
1673
1674 TEST(LibRadosAio, RoundTripWriteSamePP) {
1675   AioTestDataPP test_data;
1676   ASSERT_EQ("", test_data.init());
1677   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1678           (void*)&test_data, set_completion_complete, set_completion_safe);
1679   AioCompletion *my_completion_null = NULL;
1680   ASSERT_NE(my_completion, my_completion_null);
1681   char full[128];
1682   memset(full, 0xcc, sizeof(full));
1683   bufferlist bl1;
1684   bl1.append(full, sizeof(full));
1685   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1686                                            bl1, sizeof(full), 0));
1687   {
1688     TestAlarm alarm;
1689     ASSERT_EQ(0, my_completion->wait_for_complete());
1690   }
1691   ASSERT_EQ(0, my_completion->get_return_value());
1692   /* write the same buf four times */
1693   char buf[32];
1694   size_t ws_write_len = sizeof(full);
1695   memset(buf, 0xdd, sizeof(buf));
1696   bufferlist bl2;
1697   bl2.append(buf, sizeof(buf));
1698   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1699           (void*)&test_data, set_completion_complete, set_completion_safe);
1700   ASSERT_NE(my_completion2, my_completion_null);
1701   ASSERT_EQ(0, test_data.m_ioctx.aio_writesame("foo", my_completion2, bl2,
1702                                                ws_write_len, 0));
1703   {
1704     TestAlarm alarm;
1705     ASSERT_EQ(0, my_completion2->wait_for_complete());
1706   }
1707   ASSERT_EQ(0, my_completion2->get_return_value());
1708   bufferlist bl3;
1709   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
1710           (void*)&test_data, set_completion_complete, set_completion_safe);
1711   ASSERT_NE(my_completion3, my_completion_null);
1712   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
1713                                           &bl3, sizeof(full), 0));
1714   {
1715     TestAlarm alarm;
1716     ASSERT_EQ(0, my_completion3->wait_for_complete());
1717   }
1718   ASSERT_EQ((int)sizeof(full), my_completion3->get_return_value());
1719   ASSERT_EQ(sizeof(full), bl3.length());
1720   for (char *cmp = bl3.c_str(); cmp < bl3.c_str() + bl3.length();
1721                                                         cmp += sizeof(buf)) {
1722     ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
1723   }
1724   delete my_completion;
1725   delete my_completion2;
1726   delete my_completion3;
1727 }
1728
1729 TEST(LibRadosAio, RoundTripWriteSamePP2)
1730 {
1731   Rados cluster;
1732   std::string pool_name = get_temp_pool_name();
1733   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
1734   IoCtx ioctx;
1735   cluster.ioctx_create(pool_name.c_str(), ioctx);
1736
1737   boost::scoped_ptr<AioCompletion>
1738                         wr_cmpl(cluster.aio_create_completion(0, 0, 0));
1739   ObjectWriteOperation op;
1740   char buf[128];
1741   memset(buf, 0xcc, sizeof(buf));
1742   bufferlist bl;
1743   bl.append(buf, sizeof(buf));
1744
1745   op.writesame(0, sizeof(buf) * 4, bl);
1746   op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
1747   ioctx.aio_operate("test_obj", wr_cmpl.get(), &op);
1748   {
1749     TestAlarm alarm;
1750     ASSERT_EQ(0, wr_cmpl->wait_for_complete());
1751   }
1752   EXPECT_EQ(0, wr_cmpl->get_return_value());
1753
1754   boost::scoped_ptr<AioCompletion>
1755                         rd_cmpl(cluster.aio_create_completion(0, 0, 0));
1756   char *cmp;
1757   char full[sizeof(buf) * 4];
1758   memset(full, 0, sizeof(full));
1759   bufferlist fl;
1760   fl.append(full, sizeof(full));
1761   ObjectReadOperation op1;
1762   op1.read(0, sizeof(full), &fl, NULL);
1763   op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
1764   ioctx.aio_operate("test_obj", rd_cmpl.get(), &op1, 0);
1765   {
1766     TestAlarm alarm;
1767     ASSERT_EQ(0, rd_cmpl->wait_for_complete());
1768   }
1769   EXPECT_EQ(0, rd_cmpl->get_return_value());
1770   for (cmp = fl.c_str(); cmp < fl.c_str() + fl.length(); cmp += sizeof(buf)) {
1771     ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf)));
1772   }
1773
1774   ioctx.remove("test_obj");
1775   destroy_one_pool_pp(pool_name, cluster);
1776 }
1777
1778 TEST(LibRadosAio, SimpleStat) {
1779   AioTestData test_data;
1780   rados_completion_t my_completion;
1781   ASSERT_EQ("", test_data.init());
1782   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1783               set_completion_complete, set_completion_safe, &my_completion));
1784   char buf[128];
1785   memset(buf, 0xcc, sizeof(buf));
1786   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1787                                my_completion, buf, sizeof(buf), 0));
1788   {
1789     TestAlarm alarm;
1790     sem_wait(test_data.m_sem);
1791     sem_wait(test_data.m_sem);
1792   }
1793   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1794   uint64_t psize;
1795   time_t pmtime;
1796   rados_completion_t my_completion2;
1797   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1798               set_completion_complete, set_completion_safe, &my_completion2));
1799   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
1800                               my_completion2, &psize, &pmtime));
1801   {
1802     TestAlarm alarm;
1803     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1804   }
1805   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
1806   ASSERT_EQ(sizeof(buf), psize);
1807   rados_aio_release(my_completion);
1808   rados_aio_release(my_completion2);
1809 }
1810
1811 TEST(LibRadosAio, SimpleStatPP) {
1812   AioTestDataPP test_data;
1813   ASSERT_EQ("", test_data.init());
1814   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1815           (void*)&test_data, set_completion_complete, set_completion_safe);
1816   AioCompletion *my_completion_null = NULL;
1817   ASSERT_NE(my_completion, my_completion_null);
1818   char buf[128];
1819   memset(buf, 0xcc, sizeof(buf));
1820   bufferlist bl1;
1821   bl1.append(buf, sizeof(buf));
1822   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1823                                            bl1, sizeof(buf), 0));
1824   {
1825     TestAlarm alarm;
1826     sem_wait(test_data.m_sem);
1827     sem_wait(test_data.m_sem);
1828   }
1829   ASSERT_EQ(0, my_completion->get_return_value());
1830   uint64_t psize;
1831   time_t pmtime;
1832   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1833           (void*)&test_data, set_completion_complete, set_completion_safe);
1834   ASSERT_NE(my_completion2, my_completion_null);
1835   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
1836                                         &psize, &pmtime));
1837   {
1838     TestAlarm alarm;
1839     ASSERT_EQ(0, my_completion2->wait_for_complete());
1840   }
1841   ASSERT_EQ(0, my_completion2->get_return_value());
1842   ASSERT_EQ(sizeof(buf), psize);
1843   delete my_completion;
1844   delete my_completion2;
1845 }
1846
1847 TEST(LibRadosAio, SimpleStatNS) {
1848   AioTestData test_data;
1849   rados_completion_t my_completion;
1850   ASSERT_EQ("", test_data.init());
1851   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1852               set_completion_complete, set_completion_safe, &my_completion));
1853   char buf[128];
1854   memset(buf, 0xcc, sizeof(buf));
1855   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1856                                my_completion, buf, sizeof(buf), 0));
1857   {
1858     TestAlarm alarm;
1859     sem_wait(test_data.m_sem);
1860     sem_wait(test_data.m_sem);
1861   }
1862   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1863   rados_ioctx_set_namespace(test_data.m_ioctx, "nspace");
1864   char buf2[64];
1865   memset(buf2, 0xbb, sizeof(buf2));
1866   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1867               set_completion_complete, set_completion_safe, &my_completion));
1868   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1869                                my_completion, buf2, sizeof(buf2), 0));
1870   {
1871     TestAlarm alarm;
1872     sem_wait(test_data.m_sem);
1873     sem_wait(test_data.m_sem);
1874   }
1875   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1876   uint64_t psize;
1877   time_t pmtime;
1878   rados_completion_t my_completion2;
1879   rados_ioctx_set_namespace(test_data.m_ioctx, "");
1880   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1881               set_completion_complete, set_completion_safe, &my_completion2));
1882   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
1883                               my_completion2, &psize, &pmtime));
1884   {
1885     TestAlarm alarm;
1886     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1887   }
1888   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
1889   ASSERT_EQ(sizeof(buf), psize);
1890
1891   rados_ioctx_set_namespace(test_data.m_ioctx, "nspace");
1892   rados_completion_t my_completion3;
1893   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1894               set_completion_complete, set_completion_safe, &my_completion3));
1895   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
1896                               my_completion3, &psize, &pmtime));
1897   {
1898     TestAlarm alarm;
1899     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
1900   }
1901   ASSERT_EQ(0, rados_aio_get_return_value(my_completion3));
1902   ASSERT_EQ(sizeof(buf2), psize);
1903
1904   rados_aio_release(my_completion);
1905   rados_aio_release(my_completion2);
1906   rados_aio_release(my_completion3);
1907 }
1908
1909 TEST(LibRadosAio, SimpleStatPPNS) {
1910   AioTestDataPP test_data;
1911   ASSERT_EQ("", test_data.init());
1912   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
1913           (void*)&test_data, set_completion_complete, set_completion_safe);
1914   AioCompletion *my_completion_null = NULL;
1915   ASSERT_NE(my_completion, my_completion_null);
1916   char buf[128];
1917   memset(buf, 0xcc, sizeof(buf));
1918   bufferlist bl1;
1919   bl1.append(buf, sizeof(buf));
1920   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
1921                                            bl1, sizeof(buf), 0));
1922   {
1923     TestAlarm alarm;
1924     sem_wait(test_data.m_sem);
1925     sem_wait(test_data.m_sem);
1926   }
1927   ASSERT_EQ(0, my_completion->get_return_value());
1928   uint64_t psize;
1929   time_t pmtime;
1930   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
1931           (void*)&test_data, set_completion_complete, set_completion_safe);
1932   ASSERT_NE(my_completion2, my_completion_null);
1933   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
1934                                         &psize, &pmtime));
1935   {
1936     TestAlarm alarm;
1937     ASSERT_EQ(0, my_completion2->wait_for_complete());
1938   }
1939   ASSERT_EQ(0, my_completion2->get_return_value());
1940   ASSERT_EQ(sizeof(buf), psize);
1941   delete my_completion;
1942   delete my_completion2;
1943 }
1944
1945 TEST(LibRadosAio, StatRemove) {
1946   AioTestData test_data;
1947   rados_completion_t my_completion;
1948   ASSERT_EQ("", test_data.init());
1949   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1950               set_completion_complete, set_completion_safe, &my_completion));
1951   char buf[128];
1952   memset(buf, 0xcc, sizeof(buf));
1953   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
1954                                my_completion, buf, sizeof(buf), 0));
1955   {
1956     TestAlarm alarm;
1957     sem_wait(test_data.m_sem);
1958     sem_wait(test_data.m_sem);
1959   }
1960   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
1961   uint64_t psize;
1962   time_t pmtime;
1963   rados_completion_t my_completion2;
1964   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1965               set_completion_complete, set_completion_safe, &my_completion2));
1966   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
1967                               my_completion2, &psize, &pmtime));
1968   {
1969     TestAlarm alarm;
1970     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
1971   }
1972   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
1973   ASSERT_EQ(sizeof(buf), psize);
1974   rados_completion_t my_completion3;
1975   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1976               set_completion_complete, set_completion_safe, &my_completion3));
1977   ASSERT_EQ(0, rados_aio_remove(test_data.m_ioctx, "foo", my_completion3));
1978   {
1979     TestAlarm alarm;
1980     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
1981   }
1982   ASSERT_EQ(0, rados_aio_get_return_value(my_completion3));
1983   uint64_t psize2;
1984   time_t pmtime2;
1985   rados_completion_t my_completion4;
1986   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
1987               set_completion_complete, set_completion_safe, &my_completion4));
1988   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
1989                               my_completion4, &psize2, &pmtime2));
1990   {
1991     TestAlarm alarm;
1992     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion4));
1993   }
1994   ASSERT_EQ(-ENOENT, rados_aio_get_return_value(my_completion4));
1995   rados_aio_release(my_completion);
1996   rados_aio_release(my_completion2);
1997   rados_aio_release(my_completion3);
1998   rados_aio_release(my_completion4);
1999 }
2000
2001 TEST(LibRadosAio, StatRemovePP) {
2002   AioTestDataPP test_data;
2003   ASSERT_EQ("", test_data.init());
2004   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2005           (void*)&test_data, set_completion_complete, set_completion_safe);
2006   AioCompletion *my_completion_null = NULL;
2007   ASSERT_NE(my_completion, my_completion_null);
2008   char buf[128];
2009   memset(buf, 0xcc, sizeof(buf));
2010   bufferlist bl1;
2011   bl1.append(buf, sizeof(buf));
2012   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
2013                                            bl1, sizeof(buf), 0));
2014   {
2015     TestAlarm alarm;
2016     sem_wait(test_data.m_sem);
2017     sem_wait(test_data.m_sem);
2018   }
2019   ASSERT_EQ(0, my_completion->get_return_value());
2020   uint64_t psize;
2021   time_t pmtime;
2022   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
2023           (void*)&test_data, set_completion_complete, set_completion_safe);
2024   ASSERT_NE(my_completion2, my_completion_null);
2025   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
2026                                         &psize, &pmtime));
2027   {
2028     TestAlarm alarm;
2029     ASSERT_EQ(0, my_completion2->wait_for_complete());
2030   }
2031   ASSERT_EQ(0, my_completion2->get_return_value());
2032   ASSERT_EQ(sizeof(buf), psize);
2033   uint64_t psize2;
2034   time_t pmtime2;
2035   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
2036           (void*)&test_data, set_completion_complete, set_completion_safe);
2037   ASSERT_NE(my_completion3, my_completion_null);
2038   ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion3));
2039   {
2040     TestAlarm alarm;
2041     ASSERT_EQ(0, my_completion3->wait_for_complete());
2042   }
2043   ASSERT_EQ(0, my_completion3->get_return_value());
2044
2045   AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
2046           (void*)&test_data, set_completion_complete, set_completion_safe);
2047   ASSERT_NE(my_completion4, my_completion_null);
2048   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion4,
2049                                         &psize2, &pmtime2));
2050   {
2051     TestAlarm alarm;
2052     ASSERT_EQ(0, my_completion4->wait_for_complete());
2053   }
2054   ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
2055   delete my_completion;
2056   delete my_completion2;
2057   delete my_completion3;
2058   delete my_completion4;
2059 }
2060
2061 TEST(LibRadosAio, ExecuteClass) {
2062   AioTestData test_data;
2063   rados_completion_t my_completion;
2064   ASSERT_EQ("", test_data.init());
2065   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2066               set_completion_complete, set_completion_safe, &my_completion));
2067   char buf[128];
2068   memset(buf, 0xcc, sizeof(buf));
2069   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2070                                my_completion, buf, sizeof(buf), 0));
2071   {
2072     TestAlarm alarm;
2073     sem_wait(test_data.m_sem);
2074     sem_wait(test_data.m_sem);
2075   }
2076   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2077   rados_completion_t my_completion2;
2078   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2079               set_completion_complete, set_completion_safe, &my_completion2));
2080   char out[128];
2081   ASSERT_EQ(0, rados_aio_exec(test_data.m_ioctx, "foo", my_completion2,
2082                               "hello", "say_hello", NULL, 0, out, sizeof(out)));
2083   {
2084     TestAlarm alarm;
2085     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
2086   }
2087   ASSERT_EQ(13, rados_aio_get_return_value(my_completion2));
2088   ASSERT_EQ(0, strncmp("Hello, world!", out, 13));
2089   rados_aio_release(my_completion);
2090   rados_aio_release(my_completion2);
2091 }
2092
2093 TEST(LibRadosAio, ExecuteClassPP) {
2094   AioTestDataPP test_data;
2095   ASSERT_EQ("", test_data.init());
2096   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2097           (void*)&test_data, set_completion_complete, set_completion_safe);
2098   AioCompletion *my_completion_null = NULL;
2099   ASSERT_NE(my_completion, my_completion_null);
2100   char buf[128];
2101   memset(buf, 0xcc, sizeof(buf));
2102   bufferlist bl1;
2103   bl1.append(buf, sizeof(buf));
2104   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
2105                                            bl1, sizeof(buf), 0));
2106   {
2107     TestAlarm alarm;
2108     sem_wait(test_data.m_sem);
2109     sem_wait(test_data.m_sem);
2110   }
2111   ASSERT_EQ(0, my_completion->get_return_value());
2112   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
2113           (void*)&test_data, set_completion_complete, set_completion_safe);
2114   ASSERT_NE(my_completion2, my_completion_null);
2115   bufferlist in, out;
2116   ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2,
2117                                           "hello", "say_hello", in, &out));
2118   {
2119     TestAlarm alarm;
2120     ASSERT_EQ(0, my_completion2->wait_for_complete());
2121   }
2122   ASSERT_EQ(0, my_completion2->get_return_value());
2123   ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
2124   delete my_completion;
2125   delete my_completion2;
2126 }
2127
2128 using std::string;
2129 using std::map;
2130 using std::set;
2131
2132 TEST(LibRadosAio, OmapPP) {
2133   Rados cluster;
2134   std::string pool_name = get_temp_pool_name();
2135   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
2136   IoCtx ioctx;
2137   cluster.ioctx_create(pool_name.c_str(), ioctx);
2138
2139   string header_str = "baz";
2140   bufferptr bp(header_str.c_str(), header_str.size() + 1);
2141   bufferlist header_to_set;
2142   header_to_set.push_back(bp);
2143   map<string, bufferlist> to_set;
2144   {
2145     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2146     ObjectWriteOperation op;
2147     to_set["foo"] = header_to_set;
2148     to_set["foo2"] = header_to_set;
2149     to_set["qfoo3"] = header_to_set;
2150     op.omap_set(to_set);
2151
2152     op.omap_set_header(header_to_set);
2153
2154     ioctx.aio_operate("test_obj", my_completion.get(), &op);
2155     {
2156       TestAlarm alarm;
2157       ASSERT_EQ(0, my_completion->wait_for_complete());
2158     }
2159     EXPECT_EQ(0, my_completion->get_return_value());
2160   }
2161
2162   {
2163     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2164     ObjectReadOperation op;
2165     map<string, pair<bufferlist, int> > assertions;
2166     bufferlist val;
2167     val.append(string("bar"));
2168     assertions["foo"] = pair<bufferlist, int>(val, CEPH_OSD_CMPXATTR_OP_EQ);
2169
2170     int r;
2171     op.omap_cmp(assertions, &r);
2172
2173     ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
2174     {
2175       TestAlarm alarm;
2176       ASSERT_EQ(0, my_completion->wait_for_complete());
2177     }
2178     EXPECT_EQ(-ECANCELED, my_completion->get_return_value());
2179     ASSERT_EQ(-ECANCELED, r);
2180   }
2181
2182   {
2183     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2184     ObjectReadOperation op;
2185
2186     set<string> set_got;
2187     map<string, bufferlist> map_got;
2188
2189     set<string> to_get;
2190     map<string, bufferlist> got3;
2191
2192     map<string, bufferlist> got4;
2193
2194     bufferlist header;
2195
2196     op.omap_get_keys2("", 1, &set_got, nullptr, 0);
2197     op.omap_get_vals2("foo", 1, &map_got, nullptr, 0);
2198
2199     to_get.insert("foo");
2200     to_get.insert("qfoo3");
2201     op.omap_get_vals_by_keys(to_get, &got3, 0);
2202
2203     op.omap_get_header(&header, 0);
2204
2205     op.omap_get_vals2("foo2", "q", 1, &got4, nullptr, 0);
2206
2207     ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
2208     {
2209       TestAlarm alarm;
2210       ASSERT_EQ(0, my_completion->wait_for_complete());
2211     }
2212     EXPECT_EQ(0, my_completion->get_return_value());
2213
2214     ASSERT_EQ(header.length(), header_to_set.length());
2215     ASSERT_EQ(set_got.size(), (unsigned)1);
2216     ASSERT_EQ(*set_got.begin(), "foo");
2217     ASSERT_EQ(map_got.size(), (unsigned)1);
2218     ASSERT_EQ(map_got.begin()->first, "foo2");
2219     ASSERT_EQ(got3.size(), (unsigned)2);
2220     ASSERT_EQ(got3.begin()->first, "foo");
2221     ASSERT_EQ(got3.rbegin()->first, "qfoo3");
2222     ASSERT_EQ(got4.size(), (unsigned)1);
2223     ASSERT_EQ(got4.begin()->first, "qfoo3");
2224   }
2225
2226   {
2227     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2228     ObjectWriteOperation op;
2229     set<string> to_remove;
2230     to_remove.insert("foo2");
2231     op.omap_rm_keys(to_remove);
2232     ioctx.aio_operate("test_obj", my_completion.get(), &op);
2233     {
2234       TestAlarm alarm;
2235       ASSERT_EQ(0, my_completion->wait_for_complete());
2236     }
2237     EXPECT_EQ(0, my_completion->get_return_value());
2238   }
2239
2240   {
2241     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2242     ObjectReadOperation op;
2243
2244     set<string> set_got;
2245     op.omap_get_keys2("", -1, &set_got, nullptr, 0);
2246     ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
2247     {
2248       TestAlarm alarm;
2249       ASSERT_EQ(0, my_completion->wait_for_complete());
2250     }
2251     EXPECT_EQ(0, my_completion->get_return_value());
2252     ASSERT_EQ(set_got.size(), (unsigned)2);
2253   }
2254
2255   {
2256     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2257     ObjectWriteOperation op;
2258     op.omap_clear();
2259     ioctx.aio_operate("test_obj", my_completion.get(), &op);
2260     {
2261       TestAlarm alarm;
2262       ASSERT_EQ(0, my_completion->wait_for_complete());
2263     }
2264     EXPECT_EQ(0, my_completion->get_return_value());
2265   }
2266
2267   {
2268     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2269     ObjectReadOperation op;
2270
2271     set<string> set_got;
2272     op.omap_get_keys2("", -1, &set_got, nullptr, 0);
2273     ioctx.aio_operate("test_obj", my_completion.get(), &op, 0);
2274     {
2275       TestAlarm alarm;
2276       ASSERT_EQ(0, my_completion->wait_for_complete());
2277     }
2278     EXPECT_EQ(0, my_completion->get_return_value());
2279     ASSERT_EQ(set_got.size(), (unsigned)0);
2280   }
2281
2282   // omap_clear clears header *and* keys
2283   {
2284     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2285     ObjectWriteOperation op;
2286     bufferlist bl;
2287     bl.append("some data");
2288     map<string,bufferlist> to_set;
2289     to_set["foo"] = bl;
2290     to_set["foo2"] = bl;
2291     to_set["qfoo3"] = bl;
2292     op.omap_set(to_set);
2293     op.omap_set_header(bl);
2294     ioctx.aio_operate("foo3", my_completion.get(), &op);
2295     {
2296       TestAlarm alarm;
2297       ASSERT_EQ(0, my_completion->wait_for_complete());
2298     }
2299     EXPECT_EQ(0, my_completion->get_return_value());
2300   }
2301   {
2302     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2303     ObjectWriteOperation op;
2304     op.omap_clear();
2305     ioctx.aio_operate("foo3", my_completion.get(), &op);
2306     {
2307       TestAlarm alarm;
2308       ASSERT_EQ(0, my_completion->wait_for_complete());
2309     }
2310     EXPECT_EQ(0, my_completion->get_return_value());
2311   }
2312   {
2313     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
2314     ObjectReadOperation op;
2315     set<string> set_got;
2316     bufferlist hdr;
2317     op.omap_get_keys2("", -1, &set_got, nullptr, 0);
2318     op.omap_get_header(&hdr, NULL);
2319     ioctx.aio_operate("foo3", my_completion.get(), &op, 0);
2320     {
2321       TestAlarm alarm;
2322       ASSERT_EQ(0, my_completion->wait_for_complete());
2323     }
2324     EXPECT_EQ(0, my_completion->get_return_value());
2325     ASSERT_EQ(set_got.size(), (unsigned)0);
2326     ASSERT_EQ(hdr.length(), 0u);
2327   }
2328
2329   ioctx.remove("test_obj");
2330   destroy_one_pool_pp(pool_name, cluster);
2331 }
2332
2333 TEST(LibRadosAio, MultiWrite) {
2334   AioTestData test_data;
2335   rados_completion_t my_completion, my_completion2, my_completion3;
2336   ASSERT_EQ("", test_data.init());
2337   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2338               set_completion_complete, set_completion_safe, &my_completion));
2339   char buf[128];
2340   memset(buf, 0xcc, sizeof(buf));
2341   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2342                                my_completion, buf, sizeof(buf), 0));
2343   {
2344     TestAlarm alarm;
2345     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
2346   }
2347   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2348
2349   char buf2[64];
2350   memset(buf2, 0xdd, sizeof(buf2));
2351   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2352               set_completion_complete, set_completion_safe, &my_completion2));
2353   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2354                                my_completion2, buf2, sizeof(buf2), sizeof(buf)));
2355   {
2356     TestAlarm alarm;
2357     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
2358   }
2359   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
2360
2361   char buf3[(sizeof(buf) + sizeof(buf2)) * 3];
2362   memset(buf3, 0, sizeof(buf3));
2363   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2364               set_completion_complete, set_completion_safe, &my_completion3));
2365   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
2366                               my_completion3, buf3, sizeof(buf3), 0));
2367   {
2368     TestAlarm alarm;
2369     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
2370   }
2371   ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)), rados_aio_get_return_value(my_completion3));
2372   ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
2373   ASSERT_EQ(0, memcmp(buf3 + sizeof(buf), buf2, sizeof(buf2)));
2374   rados_aio_release(my_completion);
2375   rados_aio_release(my_completion2);
2376   rados_aio_release(my_completion3);
2377 }
2378
2379 TEST(LibRadosAio, MultiWritePP) {
2380   AioTestDataPP test_data;
2381   ASSERT_EQ("", test_data.init());
2382   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2383           (void*)&test_data, set_completion_complete, set_completion_safe);
2384   AioCompletion *my_completion_null = NULL;
2385   ASSERT_NE(my_completion, my_completion_null);
2386   char buf[128];
2387   memset(buf, 0xcc, sizeof(buf));
2388   bufferlist bl1;
2389   bl1.append(buf, sizeof(buf));
2390   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
2391                                            bl1, sizeof(buf), 0));
2392   {
2393     TestAlarm alarm;
2394     ASSERT_EQ(0, my_completion->wait_for_complete());
2395   }
2396   ASSERT_EQ(0, my_completion->get_return_value());
2397
2398   char buf2[64];
2399   memset(buf2, 0xdd, sizeof(buf2));
2400   bufferlist bl2;
2401   bl2.append(buf2, sizeof(buf2));
2402   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
2403           (void*)&test_data, set_completion_complete, set_completion_safe);
2404   ASSERT_NE(my_completion2, my_completion_null);
2405   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion2,
2406                                            bl2, sizeof(buf2), sizeof(buf)));
2407   {
2408     TestAlarm alarm;
2409     ASSERT_EQ(0, my_completion2->wait_for_complete());
2410   }
2411   ASSERT_EQ(0, my_completion2->get_return_value());
2412
2413   bufferlist bl3;
2414   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
2415           (void*)&test_data, set_completion_complete, set_completion_safe);
2416   ASSERT_NE(my_completion3, my_completion_null);
2417   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
2418                                           &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
2419   {
2420     TestAlarm alarm;
2421     ASSERT_EQ(0, my_completion3->wait_for_complete());
2422   }
2423   ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)), my_completion3->get_return_value());
2424   ASSERT_EQ(sizeof(buf) + sizeof(buf2), bl3.length());
2425   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
2426   ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf), buf2, sizeof(buf2)));
2427   delete my_completion;
2428   delete my_completion2;
2429   delete my_completion3;
2430 }
2431
2432 TEST(LibRadosAio, AioUnlock) {
2433   AioTestData test_data;
2434   ASSERT_EQ("", test_data.init());
2435   ASSERT_EQ(0, rados_lock_exclusive(test_data.m_ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
2436   rados_completion_t my_completion;
2437   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2438             set_completion_complete, set_completion_safe, &my_completion));
2439   ASSERT_EQ(0, rados_aio_unlock(test_data.m_ioctx, "foo", "TestLock", "Cookie", my_completion));
2440   {
2441     TestAlarm alarm;
2442     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
2443   }
2444   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2445   ASSERT_EQ(0, rados_lock_exclusive(test_data.m_ioctx, "foo", "TestLock", "Cookie", "", NULL,  0));
2446 }
2447
2448 TEST(LibRadosAio, AioUnlockPP) {
2449   AioTestDataPP test_data;
2450   ASSERT_EQ("", test_data.init());
2451   ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
2452   boost::scoped_ptr<AioCompletion> my_completion
2453     (test_data.m_cluster.aio_create_completion
2454      ((void*)&test_data, set_completion_completePP, set_completion_safePP));
2455   ASSERT_EQ(0, test_data.m_ioctx.aio_unlock("foo", "TestLock", "Cookie", my_completion.get()));
2456   {
2457     TestAlarm alarm;
2458     ASSERT_EQ(0, my_completion->wait_for_complete());
2459   }
2460   ASSERT_EQ(0, my_completion->get_return_value());
2461   bufferlist bl2;
2462   ASSERT_EQ(0, test_data.m_ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
2463 }
2464
2465 // EC test cases
2466 class AioTestDataEC
2467 {
2468 public:
2469   AioTestDataEC()
2470     : m_cluster(NULL),
2471       m_ioctx(NULL),
2472       m_init(false),
2473       m_complete(false),
2474       m_safe(false)
2475   {
2476   }
2477
2478   ~AioTestDataEC()
2479   {
2480     if (m_init) {
2481       rados_ioctx_destroy(m_ioctx);
2482       destroy_one_ec_pool(m_pool_name, &m_cluster);
2483       sem_close(m_sem);
2484     }
2485   }
2486
2487   std::string init()
2488   {
2489     int ret;
2490     if (SEM_FAILED == (m_sem = sem_open("/test_aio_sem", O_CREAT, 0644, 0))) {
2491       int err = errno;
2492       ostringstream oss;
2493       oss << "sem_open failed: " << cpp_strerror(err);
2494       return oss.str();
2495     }
2496     m_pool_name = get_temp_pool_name();
2497     std::string err = create_one_ec_pool(m_pool_name, &m_cluster);
2498     if (!err.empty()) {
2499       sem_close(m_sem);
2500       ostringstream oss;
2501       oss << "create_one_ec_pool(" << m_pool_name << ") failed: error " << err;
2502       return oss.str();
2503     }
2504     ret = rados_ioctx_create(m_cluster, m_pool_name.c_str(), &m_ioctx);
2505     if (ret) {
2506       sem_close(m_sem);
2507       destroy_one_ec_pool(m_pool_name, &m_cluster);
2508       ostringstream oss;
2509       oss << "rados_ioctx_create failed: error " << ret;
2510       return oss.str();
2511     }
2512     m_init = true;
2513     return "";
2514   }
2515
2516   sem_t *m_sem;
2517   rados_t m_cluster;
2518   rados_ioctx_t m_ioctx;
2519   std::string m_pool_name;
2520   bool m_init;
2521   bool m_complete;
2522   bool m_safe;
2523 };
2524
2525 class AioTestDataECPP
2526 {
2527 public:
2528   AioTestDataECPP()
2529     : m_init(false),
2530       m_complete(false),
2531       m_safe(false)
2532   {
2533   }
2534
2535   ~AioTestDataECPP()
2536   {
2537     if (m_init) {
2538       m_ioctx.close();
2539       destroy_one_ec_pool_pp(m_pool_name, m_cluster);
2540       sem_close(m_sem);
2541     }
2542   }
2543
2544   std::string init()
2545   {
2546     int ret;
2547     if (SEM_FAILED == (m_sem = sem_open("/test_aio_sem", O_CREAT, 0644, 0))) {
2548       int err = errno;
2549       ostringstream oss;
2550       oss << "sem_open failed: " << cpp_strerror(err);
2551       return oss.str();
2552     }
2553     m_pool_name = get_temp_pool_name();
2554     std::string err = create_one_ec_pool_pp(m_pool_name, m_cluster);
2555     if (!err.empty()) {
2556       sem_close(m_sem);
2557       ostringstream oss;
2558       oss << "create_one_ec_pool(" << m_pool_name << ") failed: error " << err;
2559       return oss.str();
2560     }
2561     ret = m_cluster.ioctx_create(m_pool_name.c_str(), m_ioctx);
2562     if (ret) {
2563       sem_close(m_sem);
2564       destroy_one_ec_pool_pp(m_pool_name, m_cluster);
2565       ostringstream oss;
2566       oss << "rados_ioctx_create failed: error " << ret;
2567       return oss.str();
2568     }
2569     m_init = true;
2570     return "";
2571   }
2572
2573   sem_t *m_sem = nullptr;
2574   Rados m_cluster;
2575   IoCtx m_ioctx;
2576   std::string m_pool_name;
2577   bool m_init;
2578   bool m_complete;
2579   bool m_safe;
2580 };
2581
2582 void set_completion_completeEC(rados_completion_t cb, void *arg)
2583 {
2584   AioTestDataEC *test = static_cast<AioTestDataEC*>(arg);
2585   test->m_complete = true;
2586   sem_post(test->m_sem);
2587 }
2588
2589 void set_completion_safeEC(rados_completion_t cb, void *arg)
2590 {
2591   AioTestDataEC *test = static_cast<AioTestDataEC*>(arg);
2592   test->m_safe = true;
2593   sem_post(test->m_sem);
2594 }
2595
2596 void set_completion_completeECPP(rados_completion_t cb, void *arg)
2597 {
2598   AioTestDataECPP *test = static_cast<AioTestDataECPP*>(arg);
2599   test->m_complete = true;
2600   sem_post(test->m_sem);
2601 }
2602
2603 void set_completion_safeECPP(rados_completion_t cb, void *arg)
2604 {
2605   AioTestDataECPP *test = static_cast<AioTestDataECPP*>(arg);
2606   test->m_safe = true;
2607   sem_post(test->m_sem);
2608 }
2609
2610 TEST(LibRadosAioEC, SimpleWrite) {
2611   AioTestDataEC test_data;
2612   rados_completion_t my_completion;
2613   ASSERT_EQ("", test_data.init());
2614   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2615               set_completion_completeEC, set_completion_safeEC, &my_completion));
2616   char buf[128];
2617   memset(buf, 0xcc, sizeof(buf));
2618   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2619                                my_completion, buf, sizeof(buf), 0));
2620   {
2621     TestAlarm alarm;
2622     sem_wait(test_data.m_sem);
2623     sem_wait(test_data.m_sem);
2624   }
2625   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2626
2627   rados_ioctx_set_namespace(test_data.m_ioctx, "nspace");
2628   rados_completion_t my_completion2;
2629   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2630               set_completion_completeEC, set_completion_safeEC, &my_completion2));
2631   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2632                                my_completion2, buf, sizeof(buf), 0));
2633   {
2634     TestAlarm alarm;
2635     sem_wait(test_data.m_sem);
2636     sem_wait(test_data.m_sem);
2637   }
2638   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
2639   rados_aio_release(my_completion);
2640   rados_aio_release(my_completion2);
2641 }
2642
2643 TEST(LibRadosAioEC, SimpleWritePP) {
2644   char buf[128];
2645   memset(buf, 0xcc, sizeof(buf));
2646   bufferlist bl1;
2647   bl1.append(buf, sizeof(buf));
2648   {
2649   AioTestDataECPP test_data;
2650   ASSERT_EQ("", test_data.init());
2651   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2652           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2653   AioCompletion *my_completion_null = NULL;
2654   ASSERT_NE(my_completion, my_completion_null);
2655   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
2656                                my_completion, bl1, sizeof(buf), 0));
2657   {
2658     TestAlarm alarm;
2659     sem_wait(test_data.m_sem);
2660     sem_wait(test_data.m_sem);
2661   }
2662   ASSERT_EQ(0, my_completion->get_return_value());
2663   delete my_completion;
2664   }
2665
2666   {
2667   AioTestDataECPP test_data;
2668   ASSERT_EQ("", test_data.init());
2669   test_data.m_ioctx.set_namespace("nspace");
2670   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2671           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2672   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
2673                                my_completion, bl1, sizeof(buf), 0));
2674   {
2675     TestAlarm alarm;
2676     sem_wait(test_data.m_sem);
2677     sem_wait(test_data.m_sem);
2678   }
2679   ASSERT_EQ(0, my_completion->get_return_value());
2680   delete my_completion;
2681   }
2682 }
2683
2684 TEST(LibRadosAioEC, WaitForSafe) {
2685   AioTestDataEC test_data;
2686   rados_completion_t my_completion;
2687   ASSERT_EQ("", test_data.init());
2688   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2689               set_completion_completeEC, set_completion_safeEC, &my_completion));
2690   char buf[128];
2691   memset(buf, 0xcc, sizeof(buf));
2692   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2693                                my_completion, buf, sizeof(buf), 0));
2694   TestAlarm alarm;
2695   ASSERT_EQ(0, rados_aio_wait_for_safe(my_completion));
2696   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2697   rados_aio_release(my_completion);
2698 }
2699
2700 TEST(LibRadosAioEC, WaitForSafePP) {
2701   AioTestDataECPP test_data;
2702   ASSERT_EQ("", test_data.init());
2703   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2704           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2705   AioCompletion *my_completion_null = NULL;
2706   ASSERT_NE(my_completion, my_completion_null);
2707   char buf[128];
2708   memset(buf, 0xcc, sizeof(buf));
2709   bufferlist bl1;
2710   bl1.append(buf, sizeof(buf));
2711   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
2712                                my_completion, bl1, sizeof(buf), 0));
2713   TestAlarm alarm;
2714   ASSERT_EQ(0, my_completion->wait_for_safe());
2715   ASSERT_EQ(0, my_completion->get_return_value());
2716   delete my_completion;
2717 }
2718
2719 TEST(LibRadosAioEC, RoundTrip) {
2720   AioTestDataEC test_data;
2721   rados_completion_t my_completion;
2722   ASSERT_EQ("", test_data.init());
2723   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2724               set_completion_completeEC, set_completion_safeEC, &my_completion));
2725   char buf[128];
2726   memset(buf, 0xcc, sizeof(buf));
2727   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2728                                my_completion, buf, sizeof(buf), 0));
2729   {
2730     TestAlarm alarm;
2731     sem_wait(test_data.m_sem);
2732     sem_wait(test_data.m_sem);
2733   }
2734   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2735   char buf2[256];
2736   memset(buf2, 0, sizeof(buf2));
2737   rados_completion_t my_completion2;
2738   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2739               set_completion_completeEC, set_completion_safeEC, &my_completion2));
2740   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
2741                               my_completion2, buf2, sizeof(buf2), 0));
2742   {
2743     TestAlarm alarm;
2744     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
2745   }
2746   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
2747   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
2748   rados_aio_release(my_completion);
2749   rados_aio_release(my_completion2);
2750 }
2751
2752 TEST(LibRadosAioEC, RoundTrip2) {
2753   AioTestDataEC test_data;
2754   rados_completion_t my_completion;
2755   ASSERT_EQ("", test_data.init());
2756   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2757               set_completion_completeEC, set_completion_safeEC, &my_completion));
2758   char buf[128];
2759   memset(buf, 0xcc, sizeof(buf));
2760   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
2761                                my_completion, buf, sizeof(buf), 0));
2762   {
2763     TestAlarm alarm;
2764     sem_wait(test_data.m_sem);
2765     sem_wait(test_data.m_sem);
2766   }
2767   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2768   char buf2[128];
2769   memset(buf2, 0, sizeof(buf2));
2770   rados_completion_t my_completion2;
2771   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2772               set_completion_completeEC, set_completion_safeEC, &my_completion2));
2773   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
2774                               my_completion2, buf2, sizeof(buf2), 0));
2775   {
2776     TestAlarm alarm;
2777     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
2778   }
2779   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
2780   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
2781   rados_aio_release(my_completion);
2782   rados_aio_release(my_completion2);
2783 }
2784
2785 TEST(LibRadosAioEC, RoundTripPP) {
2786   AioTestDataECPP test_data;
2787   ASSERT_EQ("", test_data.init());
2788   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2789           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2790   AioCompletion *my_completion_null = NULL;
2791   ASSERT_NE(my_completion, my_completion_null);
2792   char buf[128];
2793   memset(buf, 0xcc, sizeof(buf));
2794   bufferlist bl1;
2795   bl1.append(buf, sizeof(buf));
2796   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
2797                                            bl1, sizeof(buf), 0));
2798   {
2799     TestAlarm alarm;
2800     sem_wait(test_data.m_sem);
2801     sem_wait(test_data.m_sem);
2802   }
2803   ASSERT_EQ(0, my_completion->get_return_value());
2804   bufferlist bl2;
2805   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
2806           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2807   ASSERT_NE(my_completion2, my_completion_null);
2808   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
2809                               my_completion2, &bl2, sizeof(buf), 0));
2810   {
2811     TestAlarm alarm;
2812     ASSERT_EQ(0, my_completion2->wait_for_complete());
2813   }
2814   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
2815   ASSERT_EQ(sizeof(buf), bl2.length());
2816   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
2817   delete my_completion;
2818   delete my_completion2;
2819 }
2820
2821 TEST(LibRadosAioEC, RoundTripPP2) {
2822   AioTestDataECPP test_data;
2823   ASSERT_EQ("", test_data.init());
2824   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2825           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2826   AioCompletion *my_completion_null = NULL;
2827   ASSERT_NE(my_completion, my_completion_null);
2828   char buf[128];
2829   memset(buf, 0xcc, sizeof(buf));
2830   bufferlist bl1;
2831   bl1.append(buf, sizeof(buf));
2832   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
2833                                            bl1, sizeof(buf), 0));
2834   {
2835     TestAlarm alarm;
2836     sem_wait(test_data.m_sem);
2837     sem_wait(test_data.m_sem);
2838   }
2839   ASSERT_EQ(0, my_completion->get_return_value());
2840   bufferlist bl2;
2841   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
2842           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2843   ASSERT_NE(my_completion2, my_completion_null);
2844   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
2845                               my_completion2, &bl2, sizeof(buf), 0));
2846   {
2847     TestAlarm alarm;
2848     ASSERT_EQ(0, my_completion2->wait_for_safe());
2849     ASSERT_EQ(0, my_completion2->wait_for_complete());
2850   }
2851   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
2852   ASSERT_EQ(sizeof(buf), bl2.length());
2853   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
2854   delete my_completion;
2855   delete my_completion2;
2856 }
2857
2858 //using ObjectWriteOperation/ObjectReadOperation with iohint
2859 TEST(LibRadosAioEC, RoundTripPP3)
2860 {
2861   Rados cluster;
2862   std::string pool_name = get_temp_pool_name();
2863   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
2864   IoCtx ioctx;
2865   cluster.ioctx_create(pool_name.c_str(), ioctx);
2866
2867   boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
2868   ObjectWriteOperation op;
2869   char buf[128];
2870   memset(buf, 0xcc, sizeof(buf));
2871   bufferlist bl;
2872   bl.append(buf);
2873
2874   op.write(0, bl);
2875   op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
2876   ioctx.aio_operate("test_obj", my_completion1.get(), &op);
2877   {
2878     TestAlarm alarm;
2879     ASSERT_EQ(0, my_completion1->wait_for_complete());
2880   }
2881   EXPECT_EQ(0, my_completion1->get_return_value());
2882
2883   boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
2884   bl.clear();
2885   ObjectReadOperation op1;
2886   op1.read(0, sizeof(buf), &bl, NULL);
2887   op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
2888   ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
2889   {
2890     TestAlarm alarm;
2891     ASSERT_EQ(0, my_completion2->wait_for_complete());
2892   }
2893   EXPECT_EQ(0, my_completion2->get_return_value());
2894   ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
2895
2896   ioctx.remove("test_obj");
2897   destroy_one_pool_pp(pool_name, cluster);
2898 }
2899
2900 TEST(LibRadosAioEC, RoundTripSparseReadPP) {
2901   AioTestDataECPP test_data;
2902   ASSERT_EQ("", test_data.init());
2903   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
2904           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2905   AioCompletion *my_completion_null = NULL;
2906   ASSERT_NE(my_completion, my_completion_null);
2907   char buf[128];
2908   memset(buf, 0xcc, sizeof(buf));
2909   bufferlist bl1;
2910   bl1.append(buf, sizeof(buf));
2911   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
2912                                            bl1, sizeof(buf), 0));
2913   {
2914     TestAlarm alarm;
2915     sem_wait(test_data.m_sem);
2916     sem_wait(test_data.m_sem);
2917   }
2918   ASSERT_EQ(0, my_completion->get_return_value());
2919
2920   map<uint64_t, uint64_t> extents;
2921   bufferlist bl2;
2922   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
2923           (void*)&test_data, set_completion_completeECPP, set_completion_safeECPP);
2924   ASSERT_NE(my_completion2, my_completion_null);
2925   ASSERT_EQ(0, test_data.m_ioctx.aio_sparse_read("foo",
2926                               my_completion2, &extents, &bl2, sizeof(buf), 0));
2927   {
2928     TestAlarm alarm;
2929     ASSERT_EQ(0, my_completion2->wait_for_complete());
2930   }
2931   ASSERT_EQ(0, my_completion2->get_return_value());
2932   assert_eq_sparse(bl1, extents, bl2);
2933   delete my_completion;
2934   delete my_completion2;
2935 }
2936
2937 TEST(LibRadosAioEC, RoundTripAppend) {
2938   AioTestDataEC test_data;
2939   rados_completion_t my_completion, my_completion2, my_completion3, my_completion4;
2940   ASSERT_EQ("", test_data.init());
2941   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2942               set_completion_completeEC, set_completion_safeEC, &my_completion));
2943   int requires;
2944   ASSERT_EQ(0, rados_ioctx_pool_requires_alignment2(test_data.m_ioctx, &requires));
2945   ASSERT_NE(0, requires);
2946   uint64_t alignment;
2947   ASSERT_EQ(0, rados_ioctx_pool_required_alignment2(test_data.m_ioctx, &alignment));
2948   ASSERT_NE(0U, alignment);
2949
2950   int bsize = alignment;
2951   char *buf = (char *)new char[bsize];
2952   memset(buf, 0xcc, bsize);
2953   ASSERT_EQ(0, rados_aio_append(test_data.m_ioctx, "foo",
2954                                my_completion, buf, bsize));
2955   {
2956     TestAlarm alarm;
2957     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
2958   }
2959   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
2960
2961   int hbsize = bsize / 2;
2962   char *buf2 = (char *)new char[hbsize];
2963   memset(buf2, 0xdd, hbsize);
2964   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2965               set_completion_completeEC, set_completion_safeEC, &my_completion2));
2966   ASSERT_EQ(0, rados_aio_append(test_data.m_ioctx, "foo",
2967                                my_completion2, buf2, hbsize));
2968   {
2969     TestAlarm alarm;
2970     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
2971   }
2972   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
2973
2974   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2975               set_completion_completeEC, set_completion_safeEC, &my_completion3));
2976   ASSERT_EQ(0, rados_aio_append(test_data.m_ioctx, "foo",
2977                                my_completion3, buf2, hbsize));
2978   {
2979     TestAlarm alarm;
2980     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
2981   }
2982   EXPECT_EQ(-EOPNOTSUPP, rados_aio_get_return_value(my_completion3));
2983
2984   int tbsize = bsize + hbsize;
2985   char *buf3 = (char *)new char[tbsize];
2986   memset(buf3, 0, tbsize);
2987   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
2988               set_completion_completeEC, set_completion_safeEC, &my_completion4));
2989   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
2990                               my_completion4, buf3, bsize * 3, 0));
2991   {
2992     TestAlarm alarm;
2993     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion4));
2994   }
2995   ASSERT_EQ(tbsize, rados_aio_get_return_value(my_completion4));
2996   ASSERT_EQ(0, memcmp(buf3, buf, bsize));
2997   ASSERT_EQ(0, memcmp(buf3 + bsize, buf2, hbsize));
2998   rados_aio_release(my_completion);
2999   rados_aio_release(my_completion2);
3000   rados_aio_release(my_completion3);
3001   rados_aio_release(my_completion4);
3002   delete[] buf;
3003   delete[] buf2;
3004   delete[] buf3;
3005 }
3006
3007 TEST(LibRadosAioEC, RoundTripAppendPP) {
3008   AioTestDataECPP test_data;
3009   ASSERT_EQ("", test_data.init());
3010   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3011           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3012   AioCompletion *my_completion_null = NULL;
3013   ASSERT_NE(my_completion, my_completion_null);
3014   bool requires;
3015   ASSERT_EQ(0, test_data.m_ioctx.pool_requires_alignment2(&requires));
3016   ASSERT_TRUE(requires);
3017   uint64_t alignment;
3018   ASSERT_EQ(0, test_data.m_ioctx.pool_required_alignment2(&alignment));
3019   ASSERT_NE((unsigned)0, alignment);
3020   int bsize = alignment;
3021   char *buf = (char *)new char[bsize];
3022   memset(buf, 0xcc, bsize);
3023   bufferlist bl1;
3024   bl1.append(buf, bsize);
3025   ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion,
3026                                             bl1, bsize));
3027   {
3028     TestAlarm alarm;
3029     ASSERT_EQ(0, my_completion->wait_for_complete());
3030   }
3031   ASSERT_EQ(0, my_completion->get_return_value());
3032
3033   int hbsize = bsize / 2;
3034   char *buf2 = (char *)new char[hbsize];
3035   memset(buf2, 0xdd, hbsize);
3036   bufferlist bl2;
3037   bl2.append(buf2, hbsize);
3038   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3039           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3040   ASSERT_NE(my_completion2, my_completion_null);
3041   ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion2,
3042                                             bl2, hbsize));
3043   {
3044     TestAlarm alarm;
3045     ASSERT_EQ(0, my_completion2->wait_for_complete());
3046   }
3047   ASSERT_EQ(0, my_completion2->get_return_value());
3048
3049   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
3050           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3051   ASSERT_NE(my_completion3, my_completion_null);
3052   ASSERT_EQ(0, test_data.m_ioctx.aio_append("foo", my_completion3,
3053                                             bl2, hbsize));
3054   {
3055     TestAlarm alarm;
3056     ASSERT_EQ(0, my_completion3->wait_for_complete());
3057   }
3058   EXPECT_EQ(-EOPNOTSUPP, my_completion3->get_return_value());
3059
3060   bufferlist bl3;
3061   AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
3062           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3063   ASSERT_NE(my_completion4, my_completion_null);
3064   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo",
3065                               my_completion4, &bl3, bsize * 3, 0));
3066   {
3067     TestAlarm alarm;
3068     ASSERT_EQ(0, my_completion4->wait_for_complete());
3069   }
3070   int tbsize = bsize + hbsize;
3071   ASSERT_EQ(tbsize, my_completion4->get_return_value());
3072   ASSERT_EQ((unsigned)tbsize, bl3.length());
3073   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
3074   ASSERT_EQ(0, memcmp(bl3.c_str() + bsize, buf2, hbsize));
3075   delete my_completion;
3076   delete my_completion2;
3077   delete my_completion3;
3078   delete[] buf;
3079   delete[] buf2;
3080 }
3081
3082 TEST(LibRadosAioEC, IsComplete) {
3083   AioTestDataEC test_data;
3084   rados_completion_t my_completion;
3085   ASSERT_EQ("", test_data.init());
3086   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3087               set_completion_completeEC, set_completion_safeEC, &my_completion));
3088   char buf[128];
3089   memset(buf, 0xcc, sizeof(buf));
3090   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3091                                my_completion, buf, sizeof(buf), 0));
3092   {
3093     TestAlarm alarm;
3094     sem_wait(test_data.m_sem);
3095     sem_wait(test_data.m_sem);
3096   }
3097   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3098   char buf2[128];
3099   memset(buf2, 0, sizeof(buf2));
3100   rados_completion_t my_completion2;
3101   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3102               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3103   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
3104                               my_completion2, buf2, sizeof(buf2), 0));
3105   {
3106     TestAlarm alarm;
3107
3108     // Busy-wait until the AIO completes.
3109     // Normally we wouldn't do this, but we want to test rados_aio_is_complete.
3110     while (true) {
3111       int is_complete = rados_aio_is_complete(my_completion2);
3112       if (is_complete)
3113         break;
3114     }
3115   }
3116   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
3117   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
3118   rados_aio_release(my_completion);
3119   rados_aio_release(my_completion2);
3120 }
3121
3122 TEST(LibRadosAioEC, IsCompletePP) {
3123   AioTestDataECPP test_data;
3124   ASSERT_EQ("", test_data.init());
3125   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3126           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3127   AioCompletion *my_completion_null = NULL;
3128   ASSERT_NE(my_completion, my_completion_null);
3129   char buf[128];
3130   memset(buf, 0xcc, sizeof(buf));
3131   bufferlist bl1;
3132   bl1.append(buf, sizeof(buf));
3133   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3134                                            bl1, sizeof(buf), 0));
3135   {
3136     TestAlarm alarm;
3137     sem_wait(test_data.m_sem);
3138     sem_wait(test_data.m_sem);
3139   }
3140   ASSERT_EQ(0, my_completion->get_return_value());
3141   bufferlist bl2;
3142   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3143           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3144   ASSERT_NE(my_completion2, my_completion_null);
3145   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
3146                                           &bl2, sizeof(buf), 0));
3147   {
3148     TestAlarm alarm;
3149
3150     // Busy-wait until the AIO completes.
3151     // Normally we wouldn't do this, but we want to test is_complete.
3152     while (true) {
3153       int is_complete = my_completion2->is_complete();
3154       if (is_complete)
3155         break;
3156     }
3157   }
3158   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
3159   ASSERT_EQ(sizeof(buf), bl2.length());
3160   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
3161   delete my_completion;
3162   delete my_completion2;
3163 }
3164
3165 TEST(LibRadosAioEC, IsSafe) {
3166   AioTestDataEC test_data;
3167   rados_completion_t my_completion;
3168   ASSERT_EQ("", test_data.init());
3169   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3170               set_completion_completeEC, set_completion_safeEC, &my_completion));
3171   char buf[128];
3172   memset(buf, 0xcc, sizeof(buf));
3173   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3174                                my_completion, buf, sizeof(buf), 0));
3175   {
3176     TestAlarm alarm;
3177
3178     // Busy-wait until the AIO completes.
3179     // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
3180     while (true) {
3181       int is_safe = rados_aio_is_safe(my_completion);
3182       if (is_safe)
3183         break;
3184     }
3185   }
3186   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3187   char buf2[128];
3188   memset(buf2, 0, sizeof(buf2));
3189   rados_completion_t my_completion2;
3190   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3191               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3192   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
3193                               my_completion2, buf2, sizeof(buf2), 0));
3194   {
3195     TestAlarm alarm;
3196     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3197   }
3198   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion2));
3199   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
3200   rados_aio_release(my_completion);
3201   rados_aio_release(my_completion2);
3202 }
3203
3204 TEST(LibRadosAioEC, IsSafePP) {
3205   AioTestDataECPP test_data;
3206   ASSERT_EQ("", test_data.init());
3207   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3208           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3209   AioCompletion *my_completion_null = NULL;
3210   ASSERT_NE(my_completion, my_completion_null);
3211   char buf[128];
3212   memset(buf, 0xcc, sizeof(buf));
3213   bufferlist bl1;
3214   bl1.append(buf, sizeof(buf));
3215   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3216                                            bl1, sizeof(buf), 0));
3217   {
3218     TestAlarm alarm;
3219
3220     // Busy-wait until the AIO completes.
3221     // Normally we wouldn't do this, but we want to test rados_aio_is_safe.
3222     while (true) {
3223       int is_safe = my_completion->is_safe();
3224       if (is_safe)
3225         break;
3226     }
3227   }
3228   ASSERT_EQ(0, my_completion->get_return_value());
3229   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3230           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3231   bufferlist bl2;
3232   ASSERT_NE(my_completion2, my_completion_null);
3233   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
3234                                           &bl2, sizeof(buf), 0));
3235   {
3236     TestAlarm alarm;
3237     ASSERT_EQ(0, my_completion2->wait_for_complete());
3238   }
3239   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
3240   ASSERT_EQ(sizeof(buf), bl2.length());
3241   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
3242   delete my_completion;
3243   delete my_completion2;
3244 }
3245
3246 TEST(LibRadosAioEC, ReturnValue) {
3247   AioTestDataEC test_data;
3248   rados_completion_t my_completion;
3249   ASSERT_EQ("", test_data.init());
3250   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3251               set_completion_completeEC, set_completion_safeEC, &my_completion));
3252   char buf[128];
3253   memset(buf, 0, sizeof(buf));
3254   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "nonexistent",
3255                                my_completion, buf, sizeof(buf), 0));
3256   {
3257     TestAlarm alarm;
3258     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
3259   }
3260   ASSERT_EQ(-ENOENT, rados_aio_get_return_value(my_completion));
3261   rados_aio_release(my_completion);
3262 }
3263
3264 TEST(LibRadosAioEC, ReturnValuePP) {
3265   AioTestDataECPP test_data;
3266   ASSERT_EQ("", test_data.init());
3267   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3268           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3269   AioCompletion *my_completion_null = NULL;
3270   ASSERT_NE(my_completion, my_completion_null);
3271   bufferlist bl1;
3272   ASSERT_EQ(0, test_data.m_ioctx.aio_read("nonexistent",
3273                                my_completion, &bl1, 128, 0));
3274   {
3275     TestAlarm alarm;
3276     ASSERT_EQ(0, my_completion->wait_for_complete());
3277   }
3278   ASSERT_EQ(-ENOENT, my_completion->get_return_value());
3279   delete my_completion;
3280 }
3281
3282 TEST(LibRadosAioEC, Flush) {
3283   AioTestDataEC test_data;
3284   rados_completion_t my_completion;
3285   ASSERT_EQ("", test_data.init());
3286   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3287               set_completion_completeEC, set_completion_safeEC, &my_completion));
3288   char buf[128];
3289   memset(buf, 0xee, sizeof(buf));
3290   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3291                                my_completion, buf, sizeof(buf), 0));
3292   ASSERT_EQ(0, rados_aio_flush(test_data.m_ioctx));
3293   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3294   char buf2[128];
3295   memset(buf2, 0, sizeof(buf2));
3296   rados_completion_t my_completion2;
3297   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3298               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3299   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
3300                               my_completion2, buf2, sizeof(buf2), 0));
3301   {
3302     TestAlarm alarm;
3303     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3304   }
3305   ASSERT_EQ((int)sizeof(buf2), rados_aio_get_return_value(my_completion2));
3306   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
3307   rados_aio_release(my_completion);
3308   rados_aio_release(my_completion2);
3309 }
3310
3311 TEST(LibRadosAioEC, FlushPP) {
3312   AioTestDataECPP test_data;
3313   ASSERT_EQ("", test_data.init());
3314   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3315           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3316   AioCompletion *my_completion_null = NULL;
3317   ASSERT_NE(my_completion, my_completion_null);
3318   char buf[128];
3319   memset(buf, 0xee, sizeof(buf));
3320   bufferlist bl1;
3321   bl1.append(buf, sizeof(buf));
3322   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3323                                            bl1, sizeof(buf), 0));
3324   ASSERT_EQ(0, test_data.m_ioctx.aio_flush());
3325   ASSERT_EQ(0, my_completion->get_return_value());
3326   bufferlist bl2;
3327   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3328           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3329   ASSERT_NE(my_completion2, my_completion_null);
3330   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
3331                                           &bl2, sizeof(buf), 0));
3332   {
3333     TestAlarm alarm;
3334     ASSERT_EQ(0, my_completion2->wait_for_complete());
3335   }
3336   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
3337   ASSERT_EQ(sizeof(buf), bl2.length());
3338   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
3339   delete my_completion;
3340   delete my_completion2;
3341 }
3342
3343 TEST(LibRadosAioEC, FlushAsync) {
3344   AioTestDataEC test_data;
3345   rados_completion_t my_completion;
3346   ASSERT_EQ("", test_data.init());
3347   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3348               set_completion_completeEC, set_completion_safeEC, &my_completion));
3349   rados_completion_t flush_completion;
3350   ASSERT_EQ(0, rados_aio_create_completion(NULL, NULL, NULL, &flush_completion));
3351   char buf[128];
3352   memset(buf, 0xee, sizeof(buf));
3353   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3354                                my_completion, buf, sizeof(buf), 0));
3355   ASSERT_EQ(0, rados_aio_flush_async(test_data.m_ioctx, flush_completion));
3356   {
3357     TestAlarm alarm;
3358     ASSERT_EQ(0, rados_aio_wait_for_complete(flush_completion));
3359     ASSERT_EQ(0, rados_aio_wait_for_safe(flush_completion));
3360   }
3361   ASSERT_EQ(1, rados_aio_is_complete(my_completion));
3362   ASSERT_EQ(1, rados_aio_is_safe(my_completion));
3363   ASSERT_EQ(1, rados_aio_is_complete(flush_completion));
3364   ASSERT_EQ(1, rados_aio_is_safe(flush_completion));
3365   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3366   char buf2[128];
3367   memset(buf2, 0, sizeof(buf2));
3368   rados_completion_t my_completion2;
3369   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3370               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3371   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
3372                               my_completion2, buf2, sizeof(buf2), 0));
3373   {
3374     TestAlarm alarm;
3375     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3376   }
3377   ASSERT_EQ((int)sizeof(buf2), rados_aio_get_return_value(my_completion2));
3378   ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
3379   rados_aio_release(my_completion);
3380   rados_aio_release(my_completion2);
3381   rados_aio_release(flush_completion);
3382 }
3383
3384 TEST(LibRadosAioEC, FlushAsyncPP) {
3385   AioTestDataECPP test_data;
3386   ASSERT_EQ("", test_data.init());
3387   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3388           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3389   AioCompletion *flush_completion =
3390       test_data.m_cluster.aio_create_completion(NULL, NULL, NULL);
3391   AioCompletion *my_completion_null = NULL;
3392   ASSERT_NE(my_completion, my_completion_null);
3393   char buf[128];
3394   memset(buf, 0xee, sizeof(buf));
3395   bufferlist bl1;
3396   bl1.append(buf, sizeof(buf));
3397   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3398                                            bl1, sizeof(buf), 0));
3399   ASSERT_EQ(0, test_data.m_ioctx.aio_flush_async(flush_completion));
3400   {
3401       TestAlarm alarm;
3402       ASSERT_EQ(0, flush_completion->wait_for_complete());
3403       ASSERT_EQ(0, flush_completion->wait_for_safe());
3404   }
3405   ASSERT_EQ(1, my_completion->is_complete());
3406   ASSERT_EQ(1, my_completion->is_safe());
3407   ASSERT_EQ(1, flush_completion->is_complete());
3408   ASSERT_EQ(1, flush_completion->is_safe());
3409   ASSERT_EQ(0, my_completion->get_return_value());
3410   bufferlist bl2;
3411   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3412           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3413   ASSERT_NE(my_completion2, my_completion_null);
3414   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion2,
3415                                           &bl2, sizeof(buf), 0));
3416   {
3417     TestAlarm alarm;
3418     ASSERT_EQ(0, my_completion2->wait_for_complete());
3419   }
3420   ASSERT_EQ((int)sizeof(buf), my_completion2->get_return_value());
3421   ASSERT_EQ(sizeof(buf), bl2.length());
3422   ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
3423   delete my_completion;
3424   delete my_completion2;
3425   delete flush_completion;
3426 }
3427
3428 TEST(LibRadosAioEC, RoundTripWriteFull) {
3429   AioTestDataEC test_data;
3430   rados_completion_t my_completion, my_completion2, my_completion3;
3431   ASSERT_EQ("", test_data.init());
3432   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3433               set_completion_completeEC, set_completion_safeEC, &my_completion));
3434   char buf[128];
3435   memset(buf, 0xcc, sizeof(buf));
3436   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3437                                my_completion, buf, sizeof(buf), 0));
3438   {
3439     TestAlarm alarm;
3440     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
3441   }
3442   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3443   char buf2[64];
3444   memset(buf2, 0xdd, sizeof(buf2));
3445   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3446               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3447   ASSERT_EQ(0, rados_aio_write_full(test_data.m_ioctx, "foo",
3448                                my_completion2, buf2, sizeof(buf2)));
3449   {
3450     TestAlarm alarm;
3451     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3452   }
3453   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
3454   char buf3[sizeof(buf) + sizeof(buf2)];
3455   memset(buf3, 0, sizeof(buf3));
3456   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3457               set_completion_completeEC, set_completion_safeEC, &my_completion3));
3458   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
3459                               my_completion3, buf3, sizeof(buf3), 0));
3460   {
3461     TestAlarm alarm;
3462     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
3463   }
3464   ASSERT_EQ((int)sizeof(buf2), rados_aio_get_return_value(my_completion3));
3465   ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2)));
3466   rados_aio_release(my_completion);
3467   rados_aio_release(my_completion2);
3468   rados_aio_release(my_completion3);
3469 }
3470
3471 TEST(LibRadosAioEC, RoundTripWriteFullPP) {
3472   AioTestDataECPP test_data;
3473   ASSERT_EQ("", test_data.init());
3474   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3475           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3476   AioCompletion *my_completion_null = NULL;
3477   ASSERT_NE(my_completion, my_completion_null);
3478   char buf[128];
3479   memset(buf, 0xcc, sizeof(buf));
3480   bufferlist bl1;
3481   bl1.append(buf, sizeof(buf));
3482   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3483                                            bl1, sizeof(buf), 0));
3484   {
3485     TestAlarm alarm;
3486     ASSERT_EQ(0, my_completion->wait_for_complete());
3487   }
3488   ASSERT_EQ(0, my_completion->get_return_value());
3489   char buf2[64];
3490   memset(buf2, 0xdd, sizeof(buf2));
3491   bufferlist bl2;
3492   bl2.append(buf2, sizeof(buf2));
3493   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3494           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3495   ASSERT_NE(my_completion2, my_completion_null);
3496   ASSERT_EQ(0, test_data.m_ioctx.aio_write_full("foo", my_completion2, bl2));
3497   {
3498     TestAlarm alarm;
3499     ASSERT_EQ(0, my_completion2->wait_for_complete());
3500   }
3501   ASSERT_EQ(0, my_completion2->get_return_value());
3502   bufferlist bl3;
3503   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
3504           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3505   ASSERT_NE(my_completion3, my_completion_null);
3506   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
3507                                           &bl3, sizeof(buf), 0));
3508   {
3509     TestAlarm alarm;
3510     ASSERT_EQ(0, my_completion3->wait_for_complete());
3511   }
3512   ASSERT_EQ((int)sizeof(buf2), my_completion3->get_return_value());
3513   ASSERT_EQ(sizeof(buf2), bl3.length());
3514   ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
3515   delete my_completion;
3516   delete my_completion2;
3517   delete my_completion3;
3518 }
3519
3520 //using ObjectWriteOperation/ObjectReadOperation with iohint
3521 TEST(LibRadosAioEC, RoundTripWriteFullPP2)
3522 {
3523   Rados cluster;
3524   std::string pool_name = get_temp_pool_name();
3525   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
3526   IoCtx ioctx;
3527   cluster.ioctx_create(pool_name.c_str(), ioctx);
3528
3529   boost::scoped_ptr<AioCompletion> my_completion1(cluster.aio_create_completion(0, 0, 0));
3530   ObjectWriteOperation op;
3531   char buf[128];
3532   memset(buf, 0xcc, sizeof(buf));
3533   bufferlist bl;
3534   bl.append(buf);
3535
3536   op.write_full(bl);
3537   op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
3538   ioctx.aio_operate("test_obj", my_completion1.get(), &op);
3539   {
3540     TestAlarm alarm;
3541     ASSERT_EQ(0, my_completion1->wait_for_complete());
3542   }
3543   EXPECT_EQ(0, my_completion1->get_return_value());
3544
3545   boost::scoped_ptr<AioCompletion> my_completion2(cluster.aio_create_completion(0, 0, 0));
3546   bl.clear();
3547   ObjectReadOperation op1;
3548   op1.read(0, sizeof(buf), &bl, NULL);
3549   op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
3550   ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
3551   {
3552     TestAlarm alarm;
3553     ASSERT_EQ(0, my_completion2->wait_for_complete());
3554   }
3555   EXPECT_EQ(0, my_completion2->get_return_value());
3556   ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));
3557
3558   ioctx.remove("test_obj");
3559   destroy_one_pool_pp(pool_name, cluster);
3560 }
3561
3562 TEST(LibRadosAioEC, SimpleStat) {
3563   AioTestDataEC test_data;
3564   rados_completion_t my_completion;
3565   ASSERT_EQ("", test_data.init());
3566   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3567               set_completion_completeEC, set_completion_safeEC, &my_completion));
3568   char buf[128];
3569   memset(buf, 0xcc, sizeof(buf));
3570   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3571                                my_completion, buf, sizeof(buf), 0));
3572   {
3573     TestAlarm alarm;
3574     sem_wait(test_data.m_sem);
3575     sem_wait(test_data.m_sem);
3576   }
3577   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3578   uint64_t psize;
3579   time_t pmtime;
3580   rados_completion_t my_completion2;
3581   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3582               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3583   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
3584                               my_completion2, &psize, &pmtime));
3585   {
3586     TestAlarm alarm;
3587     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3588   }
3589   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
3590   ASSERT_EQ(sizeof(buf), psize);
3591   rados_aio_release(my_completion);
3592   rados_aio_release(my_completion2);
3593 }
3594
3595 TEST(LibRadosAioEC, SimpleStatPP) {
3596   AioTestDataECPP test_data;
3597   ASSERT_EQ("", test_data.init());
3598   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3599           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3600   AioCompletion *my_completion_null = NULL;
3601   ASSERT_NE(my_completion, my_completion_null);
3602   char buf[128];
3603   memset(buf, 0xcc, sizeof(buf));
3604   bufferlist bl1;
3605   bl1.append(buf, sizeof(buf));
3606   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3607                                            bl1, sizeof(buf), 0));
3608   {
3609     TestAlarm alarm;
3610     sem_wait(test_data.m_sem);
3611     sem_wait(test_data.m_sem);
3612   }
3613   ASSERT_EQ(0, my_completion->get_return_value());
3614   uint64_t psize;
3615   time_t pmtime;
3616   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3617           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3618   ASSERT_NE(my_completion2, my_completion_null);
3619   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
3620                                         &psize, &pmtime));
3621   {
3622     TestAlarm alarm;
3623     ASSERT_EQ(0, my_completion2->wait_for_complete());
3624   }
3625   ASSERT_EQ(0, my_completion2->get_return_value());
3626   ASSERT_EQ(sizeof(buf), psize);
3627   delete my_completion;
3628   delete my_completion2;
3629 }
3630
3631 TEST(LibRadosAioEC, SimpleStatNS) {
3632   AioTestDataEC test_data;
3633   rados_completion_t my_completion;
3634   ASSERT_EQ("", test_data.init());
3635   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3636               set_completion_completeEC, set_completion_safeEC, &my_completion));
3637   char buf[128];
3638   memset(buf, 0xcc, sizeof(buf));
3639   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3640                                my_completion, buf, sizeof(buf), 0));
3641   {
3642     TestAlarm alarm;
3643     sem_wait(test_data.m_sem);
3644     sem_wait(test_data.m_sem);
3645   }
3646   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3647   rados_ioctx_set_namespace(test_data.m_ioctx, "nspace");
3648   char buf2[64];
3649   memset(buf2, 0xbb, sizeof(buf2));
3650   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3651               set_completion_completeEC, set_completion_safeEC, &my_completion));
3652   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3653                                my_completion, buf2, sizeof(buf2), 0));
3654   {
3655     TestAlarm alarm;
3656     sem_wait(test_data.m_sem);
3657     sem_wait(test_data.m_sem);
3658   }
3659   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3660   uint64_t psize;
3661   time_t pmtime;
3662   rados_completion_t my_completion2;
3663   rados_ioctx_set_namespace(test_data.m_ioctx, "");
3664   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3665               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3666   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
3667                               my_completion2, &psize, &pmtime));
3668   {
3669     TestAlarm alarm;
3670     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3671   }
3672   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
3673   ASSERT_EQ(sizeof(buf), psize);
3674
3675   rados_ioctx_set_namespace(test_data.m_ioctx, "nspace");
3676   rados_completion_t my_completion3;
3677   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3678               set_completion_completeEC, set_completion_safeEC, &my_completion3));
3679   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
3680                               my_completion3, &psize, &pmtime));
3681   {
3682     TestAlarm alarm;
3683     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
3684   }
3685   ASSERT_EQ(0, rados_aio_get_return_value(my_completion3));
3686   ASSERT_EQ(sizeof(buf2), psize);
3687
3688   rados_aio_release(my_completion);
3689   rados_aio_release(my_completion2);
3690   rados_aio_release(my_completion3);
3691 }
3692
3693 TEST(LibRadosAioEC, SimpleStatPPNS) {
3694   AioTestDataECPP test_data;
3695   ASSERT_EQ("", test_data.init());
3696   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3697           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3698   AioCompletion *my_completion_null = NULL;
3699   ASSERT_NE(my_completion, my_completion_null);
3700   char buf[128];
3701   memset(buf, 0xcc, sizeof(buf));
3702   bufferlist bl1;
3703   bl1.append(buf, sizeof(buf));
3704   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3705                                            bl1, sizeof(buf), 0));
3706   {
3707     TestAlarm alarm;
3708     sem_wait(test_data.m_sem);
3709     sem_wait(test_data.m_sem);
3710   }
3711   ASSERT_EQ(0, my_completion->get_return_value());
3712   uint64_t psize;
3713   time_t pmtime;
3714   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3715           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3716   ASSERT_NE(my_completion2, my_completion_null);
3717   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
3718                                         &psize, &pmtime));
3719   {
3720     TestAlarm alarm;
3721     ASSERT_EQ(0, my_completion2->wait_for_complete());
3722   }
3723   ASSERT_EQ(0, my_completion2->get_return_value());
3724   ASSERT_EQ(sizeof(buf), psize);
3725   delete my_completion;
3726   delete my_completion2;
3727 }
3728
3729 TEST(LibRadosAioEC, StatRemove) {
3730   AioTestDataEC test_data;
3731   rados_completion_t my_completion;
3732   ASSERT_EQ("", test_data.init());
3733   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3734               set_completion_completeEC, set_completion_safeEC, &my_completion));
3735   char buf[128];
3736   memset(buf, 0xcc, sizeof(buf));
3737   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3738                                my_completion, buf, sizeof(buf), 0));
3739   {
3740     TestAlarm alarm;
3741     sem_wait(test_data.m_sem);
3742     sem_wait(test_data.m_sem);
3743   }
3744   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3745   uint64_t psize;
3746   time_t pmtime;
3747   rados_completion_t my_completion2;
3748   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3749               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3750   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
3751                               my_completion2, &psize, &pmtime));
3752   {
3753     TestAlarm alarm;
3754     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3755   }
3756   ASSERT_EQ(0, rados_aio_get_return_value(my_completion2));
3757   ASSERT_EQ(sizeof(buf), psize);
3758   rados_completion_t my_completion3;
3759   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3760               set_completion_completeEC, set_completion_safeEC, &my_completion3));
3761   ASSERT_EQ(0, rados_aio_remove(test_data.m_ioctx, "foo", my_completion3));
3762   {
3763     TestAlarm alarm;
3764     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
3765   }
3766   ASSERT_EQ(0, rados_aio_get_return_value(my_completion3));
3767   uint64_t psize2;
3768   time_t pmtime2;
3769   rados_completion_t my_completion4;
3770   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3771               set_completion_completeEC, set_completion_safeEC, &my_completion4));
3772   ASSERT_EQ(0, rados_aio_stat(test_data.m_ioctx, "foo",
3773                               my_completion4, &psize2, &pmtime2));
3774   {
3775     TestAlarm alarm;
3776     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion4));
3777   }
3778   ASSERT_EQ(-ENOENT, rados_aio_get_return_value(my_completion4));
3779   rados_aio_release(my_completion);
3780   rados_aio_release(my_completion2);
3781   rados_aio_release(my_completion3);
3782   rados_aio_release(my_completion4);
3783 }
3784
3785 TEST(LibRadosAioEC, StatRemovePP) {
3786   AioTestDataECPP test_data;
3787   ASSERT_EQ("", test_data.init());
3788   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3789           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3790   AioCompletion *my_completion_null = NULL;
3791   ASSERT_NE(my_completion, my_completion_null);
3792   char buf[128];
3793   memset(buf, 0xcc, sizeof(buf));
3794   bufferlist bl1;
3795   bl1.append(buf, sizeof(buf));
3796   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3797                                            bl1, sizeof(buf), 0));
3798   {
3799     TestAlarm alarm;
3800     sem_wait(test_data.m_sem);
3801     sem_wait(test_data.m_sem);
3802   }
3803   ASSERT_EQ(0, my_completion->get_return_value());
3804   uint64_t psize;
3805   time_t pmtime;
3806   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3807           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3808   ASSERT_NE(my_completion2, my_completion_null);
3809   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion2,
3810                                         &psize, &pmtime));
3811   {
3812     TestAlarm alarm;
3813     ASSERT_EQ(0, my_completion2->wait_for_complete());
3814   }
3815   ASSERT_EQ(0, my_completion2->get_return_value());
3816   ASSERT_EQ(sizeof(buf), psize);
3817   uint64_t psize2;
3818   time_t pmtime2;
3819   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
3820           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3821   ASSERT_NE(my_completion3, my_completion_null);
3822   ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion3));
3823   {
3824     TestAlarm alarm;
3825     ASSERT_EQ(0, my_completion3->wait_for_complete());
3826   }
3827   ASSERT_EQ(0, my_completion3->get_return_value());
3828
3829   AioCompletion *my_completion4 = test_data.m_cluster.aio_create_completion(
3830           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3831   ASSERT_NE(my_completion4, my_completion_null);
3832   ASSERT_EQ(0, test_data.m_ioctx.aio_stat("foo", my_completion4,
3833                                         &psize2, &pmtime2));
3834   {
3835     TestAlarm alarm;
3836     ASSERT_EQ(0, my_completion4->wait_for_complete());
3837   }
3838   ASSERT_EQ(-ENOENT, my_completion4->get_return_value());
3839   delete my_completion;
3840   delete my_completion2;
3841   delete my_completion3;
3842   delete my_completion4;
3843 }
3844
3845 TEST(LibRadosAioEC, ExecuteClass) {
3846   AioTestDataEC test_data;
3847   rados_completion_t my_completion;
3848   ASSERT_EQ("", test_data.init());
3849   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3850               set_completion_completeEC, set_completion_safeEC, &my_completion));
3851   char buf[128];
3852   memset(buf, 0xcc, sizeof(buf));
3853   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3854                                my_completion, buf, sizeof(buf), 0));
3855   {
3856     TestAlarm alarm;
3857     sem_wait(test_data.m_sem);
3858     sem_wait(test_data.m_sem);
3859   }
3860   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3861   rados_completion_t my_completion2;
3862   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3863               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3864   char out[128];
3865   ASSERT_EQ(0, rados_aio_exec(test_data.m_ioctx, "foo", my_completion2,
3866                               "hello", "say_hello", NULL, 0, out, sizeof(out)));
3867   {
3868     TestAlarm alarm;
3869     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3870   }
3871   ASSERT_EQ(13, rados_aio_get_return_value(my_completion2));
3872   ASSERT_EQ(0, strncmp("Hello, world!", out, 13));
3873   rados_aio_release(my_completion);
3874   rados_aio_release(my_completion2);
3875 }
3876
3877 TEST(LibRadosAioEC, ExecuteClassPP) {
3878   AioTestDataECPP test_data;
3879   ASSERT_EQ("", test_data.init());
3880   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3881           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3882   AioCompletion *my_completion_null = NULL;
3883   ASSERT_NE(my_completion, my_completion_null);
3884   char buf[128];
3885   memset(buf, 0xcc, sizeof(buf));
3886   bufferlist bl1;
3887   bl1.append(buf, sizeof(buf));
3888   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
3889                                            bl1, sizeof(buf), 0));
3890   {
3891     TestAlarm alarm;
3892     sem_wait(test_data.m_sem);
3893     sem_wait(test_data.m_sem);
3894   }
3895   ASSERT_EQ(0, my_completion->get_return_value());
3896   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
3897           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3898   ASSERT_NE(my_completion2, my_completion_null);
3899   bufferlist in, out;
3900   ASSERT_EQ(0, test_data.m_ioctx.aio_exec("foo", my_completion2,
3901                                           "hello", "say_hello", in, &out));
3902   {
3903     TestAlarm alarm;
3904     ASSERT_EQ(0, my_completion2->wait_for_complete());
3905   }
3906   ASSERT_EQ(0, my_completion2->get_return_value());
3907   ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
3908   delete my_completion;
3909   delete my_completion2;
3910 }
3911
3912 TEST(LibRadosAioEC, OmapPP) {
3913   Rados cluster;
3914   std::string pool_name = get_temp_pool_name();
3915   ASSERT_EQ("", create_one_ec_pool_pp(pool_name, cluster));
3916   IoCtx ioctx;
3917   cluster.ioctx_create(pool_name.c_str(), ioctx);
3918
3919   string header_str = "baz";
3920   bufferptr bp(header_str.c_str(), header_str.size() + 1);
3921   bufferlist header_to_set;
3922   header_to_set.push_back(bp);
3923   map<string, bufferlist> to_set;
3924   {
3925     boost::scoped_ptr<AioCompletion> my_completion(cluster.aio_create_completion(0, 0, 0));
3926     ObjectWriteOperation op;
3927     to_set["foo"] = header_to_set;
3928     to_set["foo2"] = header_to_set;
3929     to_set["qfoo3"] = header_to_set;
3930     op.omap_set(to_set);
3931
3932     op.omap_set_header(header_to_set);
3933
3934     ioctx.aio_operate("test_obj", my_completion.get(), &op);
3935     {
3936       TestAlarm alarm;
3937       ASSERT_EQ(0, my_completion->wait_for_complete());
3938     }
3939     EXPECT_EQ(-EOPNOTSUPP, my_completion->get_return_value());
3940   }
3941   ioctx.remove("test_obj");
3942   destroy_one_pool_pp(pool_name, cluster);
3943 }
3944
3945 TEST(LibRadosAioEC, MultiWrite) {
3946   AioTestDataEC test_data;
3947   rados_completion_t my_completion, my_completion2, my_completion3;
3948   ASSERT_EQ("", test_data.init());
3949   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3950               set_completion_completeEC, set_completion_safeEC, &my_completion));
3951   char buf[128];
3952   memset(buf, 0xcc, sizeof(buf));
3953   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3954                                my_completion, buf, sizeof(buf), 0));
3955   {
3956     TestAlarm alarm;
3957     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion));
3958   }
3959   ASSERT_EQ(0, rados_aio_get_return_value(my_completion));
3960
3961   char buf2[64];
3962   memset(buf2, 0xdd, sizeof(buf2));
3963   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3964               set_completion_completeEC, set_completion_safeEC, &my_completion2));
3965   ASSERT_EQ(0, rados_aio_write(test_data.m_ioctx, "foo",
3966                                my_completion2, buf2, sizeof(buf2), sizeof(buf)));
3967   {
3968     TestAlarm alarm;
3969     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion2));
3970   }
3971   ASSERT_EQ(-EOPNOTSUPP, rados_aio_get_return_value(my_completion2));
3972
3973   char buf3[(sizeof(buf) + sizeof(buf2)) * 3];
3974   memset(buf3, 0, sizeof(buf3));
3975   ASSERT_EQ(0, rados_aio_create_completion((void*)&test_data,
3976               set_completion_completeEC, set_completion_safeEC, &my_completion3));
3977   ASSERT_EQ(0, rados_aio_read(test_data.m_ioctx, "foo",
3978                               my_completion3, buf3, sizeof(buf3), 0));
3979   {
3980     TestAlarm alarm;
3981     ASSERT_EQ(0, rados_aio_wait_for_complete(my_completion3));
3982   }
3983   ASSERT_EQ((int)sizeof(buf), rados_aio_get_return_value(my_completion3));
3984   ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
3985   rados_aio_release(my_completion);
3986   rados_aio_release(my_completion2);
3987   rados_aio_release(my_completion3);
3988 }
3989
3990 TEST(LibRadosAioEC, MultiWritePP) {
3991   AioTestDataECPP test_data;
3992   ASSERT_EQ("", test_data.init());
3993   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
3994           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
3995   AioCompletion *my_completion_null = NULL;
3996   ASSERT_NE(my_completion, my_completion_null);
3997   char buf[128];
3998   memset(buf, 0xcc, sizeof(buf));
3999   bufferlist bl1;
4000   bl1.append(buf, sizeof(buf));
4001   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
4002                                            bl1, sizeof(buf), 0));
4003   {
4004     TestAlarm alarm;
4005     ASSERT_EQ(0, my_completion->wait_for_complete());
4006   }
4007   ASSERT_EQ(0, my_completion->get_return_value());
4008
4009   char buf2[64];
4010   memset(buf2, 0xdd, sizeof(buf2));
4011   bufferlist bl2;
4012   bl2.append(buf2, sizeof(buf2));
4013   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
4014           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
4015   ASSERT_NE(my_completion2, my_completion_null);
4016   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion2,
4017                                            bl2, sizeof(buf2), sizeof(buf)));
4018   {
4019     TestAlarm alarm;
4020     ASSERT_EQ(0, my_completion2->wait_for_complete());
4021   }
4022   ASSERT_EQ(-EOPNOTSUPP, my_completion2->get_return_value());
4023
4024   bufferlist bl3;
4025   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
4026           (void*)&test_data, set_completion_completeEC, set_completion_safeEC);
4027   ASSERT_NE(my_completion3, my_completion_null);
4028   ASSERT_EQ(0, test_data.m_ioctx.aio_read("foo", my_completion3,
4029                                           &bl3, (sizeof(buf) + sizeof(buf2) * 3), 0));
4030   {
4031     TestAlarm alarm;
4032     ASSERT_EQ(0, my_completion3->wait_for_complete());
4033   }
4034   ASSERT_EQ((int)sizeof(buf), my_completion3->get_return_value());
4035   ASSERT_EQ(sizeof(buf), bl3.length());
4036   ASSERT_EQ(0, memcmp(bl3.c_str(), buf, sizeof(buf)));
4037   delete my_completion;
4038   delete my_completion2;
4039   delete my_completion3;
4040 }
4041
4042 TEST(LibRadosAio, RacingRemovePP) {
4043   AioTestDataPP test_data;
4044   ASSERT_EQ("", test_data.init({{"objecter_retry_writes_after_first_reply", "true"}}));
4045   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
4046         (void*)&test_data, set_completion_complete, set_completion_safe);
4047   ASSERT_NE(my_completion, nullptr);
4048   char buf[128];
4049   memset(buf, 0xcc, sizeof(buf));
4050   bufferlist bl;
4051   bl.append(buf, sizeof(buf));
4052   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
4053         (void*)&test_data, set_completion_complete, set_completion_safe);
4054   ASSERT_NE(my_completion2, nullptr);
4055   ASSERT_EQ(0, test_data.m_ioctx.aio_remove("foo", my_completion2));
4056   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
4057                                          bl, sizeof(buf), 0));
4058   {
4059     TestAlarm alarm;
4060     sem_wait(test_data.m_sem);
4061     sem_wait(test_data.m_sem);
4062     my_completion2->wait_for_complete();
4063     my_completion->wait_for_complete();
4064   }
4065   ASSERT_EQ(-ENOENT, my_completion2->get_return_value());
4066   ASSERT_EQ(0, my_completion->get_return_value());
4067   ASSERT_EQ(0, test_data.m_ioctx.stat("foo", nullptr, nullptr));
4068   delete my_completion;
4069   delete my_completion2;
4070 }
4071
4072 TEST(LibRadosAio, RoundTripCmpExtPP) {
4073   AioTestDataPP test_data;
4074   ASSERT_EQ("", test_data.init());
4075   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
4076           (void*)&test_data, set_completion_complete, set_completion_safe);
4077   AioCompletion *my_completion_null = NULL;
4078   ASSERT_NE(my_completion, my_completion_null);
4079   char full[128];
4080   memset(full, 0xcc, sizeof(full));
4081   bufferlist bl1;
4082   bl1.append(full, sizeof(full));
4083   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion,
4084                                            bl1, sizeof(full), 0));
4085   {
4086     TestAlarm alarm;
4087     ASSERT_EQ(0, my_completion->wait_for_complete());
4088   }
4089   ASSERT_EQ(0, my_completion->get_return_value());
4090
4091   /* compare with match */
4092   bufferlist cbl;
4093   cbl.append(full, sizeof(full));
4094   AioCompletion *my_completion2 = test_data.m_cluster.aio_create_completion(
4095           (void*)&test_data, set_completion_complete, set_completion_safe);
4096   ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext("foo", my_completion2, 0, cbl));
4097
4098   {
4099     TestAlarm alarm;
4100     ASSERT_EQ(0, my_completion2->wait_for_complete());
4101   }
4102   ASSERT_EQ(0, my_completion2->get_return_value());
4103
4104   /* compare with mismatch */
4105   memset(full, 0xdd, sizeof(full));
4106   cbl.clear();
4107   cbl.append(full, sizeof(full));
4108   AioCompletion *my_completion3 = test_data.m_cluster.aio_create_completion(
4109           (void*)&test_data, set_completion_complete, set_completion_safe);
4110   ASSERT_EQ(0, test_data.m_ioctx.aio_cmpext("foo", my_completion3, 0, cbl));
4111
4112   {
4113     TestAlarm alarm;
4114     ASSERT_EQ(0, my_completion3->wait_for_complete());
4115   }
4116   ASSERT_EQ(-MAX_ERRNO, my_completion3->get_return_value());
4117
4118   delete my_completion;
4119   delete my_completion2;
4120   delete my_completion3;
4121 }
4122
4123 TEST(LibRadosAio, RoundTripCmpExtPP2)
4124 {
4125   int ret;
4126   char buf[128];
4127   char miscmp_buf[128];
4128   bufferlist cbl;
4129   Rados cluster;
4130   std::string pool_name = get_temp_pool_name();
4131   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
4132   IoCtx ioctx;
4133   cluster.ioctx_create(pool_name.c_str(), ioctx);
4134
4135   boost::scoped_ptr<AioCompletion>
4136                         wr_cmpl(cluster.aio_create_completion(0, 0, 0));
4137   ObjectWriteOperation wr_op;
4138   memset(buf, 0xcc, sizeof(buf));
4139   memset(miscmp_buf, 0xdd, sizeof(miscmp_buf));
4140   bufferlist bl;
4141   bl.append(buf, sizeof(buf));
4142
4143   wr_op.write_full(bl);
4144   wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
4145   ioctx.aio_operate("test_obj", wr_cmpl.get(), &wr_op);
4146   {
4147     TestAlarm alarm;
4148     ASSERT_EQ(0, wr_cmpl->wait_for_complete());
4149   }
4150   EXPECT_EQ(0, wr_cmpl->get_return_value());
4151
4152   /* cmpext as write op. first match then mismatch */
4153   boost::scoped_ptr<AioCompletion>
4154                         wr_cmpext_cmpl(cluster.aio_create_completion(0, 0, 0));
4155   cbl.append(buf, sizeof(buf));
4156   ret = 0;
4157
4158   wr_op.cmpext(0, cbl, &ret);
4159   wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
4160   ioctx.aio_operate("test_obj", wr_cmpext_cmpl.get(), &wr_op);
4161   {
4162     TestAlarm alarm;
4163     ASSERT_EQ(0, wr_cmpext_cmpl->wait_for_complete());
4164   }
4165   EXPECT_EQ(0, wr_cmpext_cmpl->get_return_value());
4166   EXPECT_EQ(0, ret);
4167
4168   boost::scoped_ptr<AioCompletion>
4169                         wr_cmpext_cmpl2(cluster.aio_create_completion(0, 0, 0));
4170   cbl.clear();
4171   cbl.append(miscmp_buf, sizeof(miscmp_buf));
4172   ret = 0;
4173
4174   wr_op.cmpext(0, cbl, &ret);
4175   wr_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
4176   ioctx.aio_operate("test_obj", wr_cmpext_cmpl2.get(), &wr_op);
4177   {
4178     TestAlarm alarm;
4179     ASSERT_EQ(0, wr_cmpext_cmpl2->wait_for_complete());
4180   }
4181   EXPECT_EQ(-MAX_ERRNO, wr_cmpext_cmpl2->get_return_value());
4182   EXPECT_EQ(-MAX_ERRNO, ret);
4183
4184   /* cmpext as read op */
4185   boost::scoped_ptr<AioCompletion>
4186                         rd_cmpext_cmpl(cluster.aio_create_completion(0, 0, 0));
4187   ObjectReadOperation rd_op;
4188   cbl.clear();
4189   cbl.append(buf, sizeof(buf));
4190   ret = 0;
4191   rd_op.cmpext(0, cbl, &ret);
4192   rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
4193   ioctx.aio_operate("test_obj", rd_cmpext_cmpl.get(), &rd_op, 0);
4194   {
4195     TestAlarm alarm;
4196     ASSERT_EQ(0, rd_cmpext_cmpl->wait_for_complete());
4197   }
4198   EXPECT_EQ(0, rd_cmpext_cmpl->get_return_value());
4199   EXPECT_EQ(0, ret);
4200
4201   boost::scoped_ptr<AioCompletion>
4202                         rd_cmpext_cmpl2(cluster.aio_create_completion(0, 0, 0));
4203   cbl.clear();
4204   cbl.append(miscmp_buf, sizeof(miscmp_buf));
4205   ret = 0;
4206
4207   rd_op.cmpext(0, cbl, &ret);
4208   rd_op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
4209   ioctx.aio_operate("test_obj", rd_cmpext_cmpl2.get(), &rd_op, 0);
4210   {
4211     TestAlarm alarm;
4212     ASSERT_EQ(0, rd_cmpext_cmpl2->wait_for_complete());
4213   }
4214   EXPECT_EQ(-MAX_ERRNO, rd_cmpext_cmpl2->get_return_value());
4215   EXPECT_EQ(-MAX_ERRNO, ret);
4216
4217   ioctx.remove("test_obj");
4218   destroy_one_pool_pp(pool_name, cluster);
4219 }