1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/librados_test_stub/LibradosTestStub.h"
5 #include "include/rados/librados.hpp"
6 #include "include/stringify.h"
7 #include "common/ceph_argparse.h"
8 #include "common/ceph_context.h"
9 #include "common/common_init.h"
10 #include "common/config.h"
11 #include "common/debug.h"
12 #include "common/snap_types.h"
13 #include "librados/AioCompletionImpl.h"
14 #include "log/Log.h"
15 #include "test/librados_test_stub/TestClassHandler.h"
16 #include "test/librados_test_stub/TestIoCtxImpl.h"
17 #include "test/librados_test_stub/TestRadosClient.h"
18 #include "test/librados_test_stub/TestMemCluster.h"
19 #include "test/librados_test_stub/TestMemRadosClient.h"
20 #include "objclass/objclass.h"
21 #include "osd/osd_types.h"
22 #include <arpa/inet.h>
23 #include <boost/bind.hpp>
24 #include <boost/shared_ptr.hpp>
25 #include <deque>
26 #include <list>
27 #include <vector>
28 #include "include/ceph_assert.h"
29 #include "include/compat.h"
30
31 #define dout_context g_ceph_context
32 #define dout_subsys ceph_subsys_rados
33
34 namespace librados {
35
36 MockTestMemIoCtxImpl &get_mock_io_ctx(IoCtx &ioctx) {
37 MockTestMemIoCtxImpl **mock =
38 reinterpret_cast<MockTestMemIoCtxImpl **>(&ioctx);
39 return **mock;
40 }
41
42 } // namespace librados
43
44 namespace librados_test_stub {
45
46 TestClusterRef &cluster() {
47 static TestClusterRef s_cluster;
48 return s_cluster;
49 }
50
51 void set_cluster(TestClusterRef cluster_ref) {
52 cluster() = cluster_ref;
53 }
54
55 TestClusterRef get_cluster() {
56 auto &cluster_ref = cluster();
57 if (cluster_ref.get() == nullptr) {
58 cluster_ref.reset(new librados::TestMemCluster());
59 }
60 return cluster_ref;
61 }
62
63 } // namespace librados_test_stub
64
65 namespace {
66
67 librados::TestClassHandler *get_class_handler() {
68 static boost::shared_ptr<librados::TestClassHandler> s_class_handler;
69 if (!s_class_handler) {
70 s_class_handler.reset(new librados::TestClassHandler());
71 s_class_handler->open_all_classes();
72 }
73 return s_class_handler.get();
74 }
75
76 void do_out_buffer(bufferlist& outbl, char **outbuf, size_t *outbuflen) {
77 if (outbuf) {
78 if (outbl.length() > 0) {
79 *outbuf = (char *)malloc(outbl.length());
80 memcpy(*outbuf, outbl.c_str(), outbl.length());
81 } else {
82 *outbuf = NULL;
83 }
84 }
85 if (outbuflen) {
86 *outbuflen = outbl.length();
87 }
88 }
89
90 void do_out_buffer(string& outbl, char **outbuf, size_t *outbuflen) {
91 if (outbuf) {
92 if (outbl.length() > 0) {
93 *outbuf = (char *)malloc(outbl.length());
94 memcpy(*outbuf, outbl.c_str(), outbl.length());
95 } else {
96 *outbuf = NULL;
97 }
98 }
99 if (outbuflen) {
100 *outbuflen = outbl.length();
101 }
102 }
103
104 librados::TestRadosClient *create_rados_client() {
105 CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT);
106 CephContext *cct = common_preinit(iparams, CODE_ENVIRONMENT_LIBRARY, 0);
107 cct->_conf.parse_env(cct->get_module_type());
108 cct->_conf.apply_changes(nullptr);
109 cct->_log->start();
110
111 auto rados_client =
112 librados_test_stub::get_cluster()->create_rados_client(cct);
113 cct->put();
114 return rados_client;
115 }
116
117 } // anonymous namespace
118
119 extern "C" int rados_aio_create_completion(void *cb_arg,
120 rados_callback_t cb_complete,
121 rados_callback_t cb_safe,
122 rados_completion_t *pc)
123 {
124 librados::AioCompletionImpl *c = new librados::AioCompletionImpl;
125 if (cb_complete) {
126 c->set_complete_callback(cb_arg, cb_complete);
127 }
128 if (cb_safe) {
129 c->set_safe_callback(cb_arg, cb_safe);
130 }
131 *pc = c;
132 return 0;
133 }
134
135 extern "C" int rados_aio_get_return_value(rados_completion_t c) {
136 return reinterpret_cast<librados::AioCompletionImpl*>(c)->get_return_value();
137 }
138
139 extern "C" rados_config_t rados_cct(rados_t cluster)
140 {
141 librados::TestRadosClient *client =
142 reinterpret_cast<librados::TestRadosClient*>(cluster);
143 return reinterpret_cast<rados_config_t>(client->cct());
144 }
145
146 extern "C" int rados_conf_set(rados_t cluster, const char *option,
147 const char *value) {
148 librados::TestRadosClient *impl =
149 reinterpret_cast<librados::TestRadosClient*>(cluster);
150 CephContext *cct = impl->cct();
151 return cct->_conf.set_val(option, value);
152 }
153
154 extern "C" int rados_conf_parse_env(rados_t cluster, const char *var) {
155 librados::TestRadosClient *client =
156 reinterpret_cast<librados::TestRadosClient*>(cluster);
157 auto& conf = client->cct()->_conf;
158 conf.parse_env(client->cct()->get_module_type(), var);
159 conf.apply_changes(NULL);
160 return 0;
161 }
162
163 extern "C" int rados_conf_read_file(rados_t cluster, const char *path) {
164 librados::TestRadosClient *client =
165 reinterpret_cast<librados::TestRadosClient*>(cluster);
166 auto& conf = client->cct()->_conf;
167 int ret = conf.parse_config_files(path, NULL, 0);
168 if (ret == 0) {
169 conf.parse_env(client->cct()->get_module_type());
170 conf.apply_changes(NULL);
171 conf.complain_about_parse_error(client->cct());
172 } else if (ret == -ENOENT) {
173 // ignore missing client config
174 return 0;
175 }
176 return ret;
177 }
178
179 extern "C" int rados_connect(rados_t cluster) {
180 librados::TestRadosClient *client =
181 reinterpret_cast<librados::TestRadosClient*>(cluster);
182 return client->connect();
183 }
184
185 extern "C" int rados_create(rados_t *cluster, const char * const id) {
186 *cluster = create_rados_client();
187 return 0;
188 }
189
190 extern "C" int rados_create_with_context(rados_t *cluster,
191 rados_config_t cct_) {
192 auto cct = reinterpret_cast<CephContext*>(cct_);
193 *cluster = librados_test_stub::get_cluster()->create_rados_client(cct);
194 return 0;
195 }
196
197 extern "C" rados_config_t rados_ioctx_cct(rados_ioctx_t ioctx)
198 {
199 librados::TestIoCtxImpl *ctx =
200 reinterpret_cast<librados::TestIoCtxImpl*>(ioctx);
201 return reinterpret_cast<rados_config_t>(ctx->get_rados_client()->cct());
202 }
203
204 extern "C" int rados_ioctx_create(rados_t cluster, const char *pool_name,
205 rados_ioctx_t *ioctx) {
206 librados::TestRadosClient *client =
207 reinterpret_cast<librados::TestRadosClient*>(cluster);
208
209 int64_t pool_id = client->pool_lookup(pool_name);
210 if (pool_id < 0) {
211 return static_cast<int>(pool_id);
212 }
213
214 *ioctx = reinterpret_cast<rados_ioctx_t>(
215 client->create_ioctx(pool_id, pool_name));
216 return 0;
217 }
218
219 extern "C" int rados_ioctx_create2(rados_t cluster, int64_t pool_id,
220 rados_ioctx_t *ioctx)
221 {
222 librados::TestRadosClient *client =
223 reinterpret_cast<librados::TestRadosClient*>(cluster);
224
225 std::list<std::pair<int64_t, std::string> > pools;
226 int r = client->pool_list(pools);
227 if (r < 0) {
228 return r;
229 }
230
231 for (std::list<std::pair<int64_t, std::string> >::iterator it =
232 pools.begin(); it != pools.end(); ++it) {
233 if (it->first == pool_id) {
234 *ioctx = reinterpret_cast<rados_ioctx_t>(
235 client->create_ioctx(pool_id, it->second));
236 return 0;
237 }
238 }
239 return -ENOENT;
240 }
241
242 extern "C" void rados_ioctx_destroy(rados_ioctx_t io) {
243 librados::TestIoCtxImpl *ctx =
244 reinterpret_cast<librados::TestIoCtxImpl*>(io);
245 ctx->put();
246 }
247
248 extern "C" rados_t rados_ioctx_get_cluster(rados_ioctx_t io) {
249 librados::TestIoCtxImpl *ctx =
250 reinterpret_cast<librados::TestIoCtxImpl*>(io);
251 return reinterpret_cast<rados_t>(ctx->get_rados_client());
252 }
253
254 extern "C" int rados_mon_command(rados_t cluster, const char **cmd,
255 size_t cmdlen, const char *inbuf,
256 size_t inbuflen, char **outbuf,
257 size_t *outbuflen, char **outs,
258 size_t *outslen) {
259 librados::TestRadosClient *client =
260 reinterpret_cast<librados::TestRadosClient*>(cluster);
261
262 vector<string> cmdvec;
263 for (size_t i = 0; i < cmdlen; i++) {
264 cmdvec.push_back(cmd[i]);
265 }
266
267 bufferlist inbl;
268 inbl.append(inbuf, inbuflen);
269
270 bufferlist outbl;
271 string outstring;
272 int ret = client->mon_command(cmdvec, inbl, &outbl, &outstring);
273
274 do_out_buffer(outbl, outbuf, outbuflen);
275 do_out_buffer(outstring, outs, outslen);
276 return ret;
277 }
278
279 extern "C" int rados_nobjects_list_open(rados_ioctx_t io,
280 rados_list_ctx_t *ctx) {
281 librados::TestIoCtxImpl *io_ctx =
282 reinterpret_cast<librados::TestIoCtxImpl*>(io);
283 librados::TestRadosClient *client = io_ctx->get_rados_client();
284
285 std::list<librados::TestRadosClient::Object> *list =
286 new std::list<librados::TestRadosClient::Object>();
287
288 client->object_list(io_ctx->get_id(), list);
289 list->push_front(librados::TestRadosClient::Object());
290 *ctx = reinterpret_cast<rados_list_ctx_t>(list);
291 return 0;
292 }
293
294 extern "C" int rados_nobjects_list_next(rados_list_ctx_t ctx,
295 const char **entry,
296 const char **key,
297 const char **nspace) {
298 std::list<librados::TestRadosClient::Object> *list =
299 reinterpret_cast<std::list<librados::TestRadosClient::Object> *>(ctx);
300 if (!list->empty()) {
301 list->pop_front();
302 }
303 if (list->empty()) {
304 return -ENOENT;
305 }
306
307 librados::TestRadosClient::Object &obj = list->front();
308 if (entry != NULL) {
309 *entry = obj.oid.c_str();
310 }
311 if (key != NULL) {
312 *key = obj.locator.c_str();
313 }
314 if (nspace != NULL) {
315 *nspace = obj.nspace.c_str();
316 }
317 return 0;
318 }
319
320 extern "C" void rados_nobjects_list_close(rados_list_ctx_t ctx) {
321 std::list<librados::TestRadosClient::Object> *list =
322 reinterpret_cast<std::list<librados::TestRadosClient::Object> *>(ctx);
323 delete list;
324 }
325
326 extern "C" int rados_pool_create(rados_t cluster, const char *pool_name) {
327 librados::TestRadosClient *client =
328 reinterpret_cast<librados::TestRadosClient*>(cluster);
329 return client->pool_create(pool_name);
330 }
331
332 extern "C" int rados_pool_delete(rados_t cluster, const char *pool_name) {
333 librados::TestRadosClient *client =
334 reinterpret_cast<librados::TestRadosClient*>(cluster);
335 return client->pool_delete(pool_name);
336 }
337
338 extern "C" void rados_shutdown(rados_t cluster) {
339 librados::TestRadosClient *client =
340 reinterpret_cast<librados::TestRadosClient*>(cluster);
341 client->put();
342 }
343
344 extern "C" int rados_wait_for_latest_osdmap(rados_t cluster) {
345 librados::TestRadosClient *client =
346 reinterpret_cast<librados::TestRadosClient*>(cluster);
347 return client->wait_for_latest_osdmap();
348 }
349
350 namespace librados {
351
352 void AioCompletion::release() {
353 AioCompletionImpl *c = reinterpret_cast<AioCompletionImpl *>(pc);
354 c->release();
355 delete this;
356 }
357
358 IoCtx::IoCtx() : io_ctx_impl(NULL) {
359 }
360
361 IoCtx::~IoCtx() {
362 close();
363 }
364
365 IoCtx::IoCtx(const IoCtx& rhs) {
366 io_ctx_impl = rhs.io_ctx_impl;
367 if (io_ctx_impl) {
368 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
369 ctx->get();
370 }
371 }
372
373 IoCtx::IoCtx(IoCtx&& rhs) noexcept : io_ctx_impl(std::exchange(rhs.io_ctx_impl, nullptr))
374 {
375 }
376
377 IoCtx& IoCtx::operator=(const IoCtx& rhs) {
378 if (io_ctx_impl) {
379 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
380 ctx->put();
381 }
382
383 io_ctx_impl = rhs.io_ctx_impl;
384 if (io_ctx_impl) {
385 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
386 ctx->get();
387 }
388 return *this;
389 }
390
391 librados::IoCtx& librados::IoCtx::operator=(IoCtx&& rhs) noexcept
392 {
393 if (io_ctx_impl) {
394 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
395 ctx->put();
396 }
397
398 io_ctx_impl = std::exchange(rhs.io_ctx_impl, nullptr);
399 return *this;
400 }
401
402 int IoCtx::aio_flush() {
403 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
404 ctx->aio_flush();
405 return 0;
406 }
407
408 int IoCtx::aio_flush_async(AioCompletion *c) {
409 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
410 ctx->aio_flush_async(c->pc);
411 return 0;
412 }
413
414 int IoCtx::aio_notify(const std::string& oid, AioCompletion *c, bufferlist& bl,
415 uint64_t timeout_ms, bufferlist *pbl) {
416 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
417 ctx->aio_notify(oid, c->pc, bl, timeout_ms, pbl);
418 return 0;
419 }
420
421 int IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
422 ObjectReadOperation *op, bufferlist *pbl) {
423 return aio_operate(oid, c, op, 0, pbl);
424 }
425
426 int IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
427 ObjectReadOperation *op, int flags,
428 bufferlist *pbl) {
429 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
430 TestObjectOperationImpl *ops = reinterpret_cast<TestObjectOperationImpl*>(op->impl);
431 return ctx->aio_operate_read(oid, *ops, c->pc, flags, pbl);
432 }
433
434 int IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
435 ObjectReadOperation *op, int flags,
436 bufferlist *pbl, const blkin_trace_info *trace_info) {
437 return aio_operate(oid, c, op, flags, pbl);
438 }
439
440 int IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
441 ObjectWriteOperation *op) {
442 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
443 TestObjectOperationImpl *ops = reinterpret_cast<TestObjectOperationImpl*>(op->impl);
444 return ctx->aio_operate(oid, *ops, c->pc, NULL, 0);
445 }
446
447 int IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
448 ObjectWriteOperation *op, snap_t seq,
449 std::vector<snap_t>& snaps, int flags,
450 const blkin_trace_info *trace_info) {
451 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
452 TestObjectOperationImpl *ops = reinterpret_cast<TestObjectOperationImpl*>(op->impl);
453
454 std::vector<snapid_t> snv;
455 snv.resize(snaps.size());
456 for (size_t i = 0; i < snaps.size(); ++i)
457 snv[i] = snaps[i];
458 SnapContext snapc(seq, snv);
459
460 return ctx->aio_operate(oid, *ops, c->pc, &snapc, flags);
461 }
462
463 int IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
464 ObjectWriteOperation *op, snap_t seq,
465 std::vector<snap_t>& snaps) {
466 return aio_operate(oid, c, op, seq, snaps, 0, nullptr);
467 }
468
469 int IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
470 ObjectWriteOperation *op, snap_t seq,
471 std::vector<snap_t>& snaps,
472 const blkin_trace_info *trace_info) {
473 return aio_operate(oid, c, op, seq, snaps, 0, trace_info);
474 }
475
476 int IoCtx::aio_remove(const std::string& oid, AioCompletion *c) {
477 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
478 return ctx->aio_remove(oid, c->pc);
479 }
480
481 int IoCtx::aio_remove(const std::string& oid, AioCompletion *c, int flags) {
482 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
483 return ctx->aio_remove(oid, c->pc, flags);
484 }
485
486 int IoCtx::aio_watch(const std::string& o, AioCompletion *c, uint64_t *handle,
487 librados::WatchCtx2 *watch_ctx) {
488 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
489 return ctx->aio_watch(o, c->pc, handle, watch_ctx);
490 }
491
492 int IoCtx::aio_unwatch(uint64_t handle, AioCompletion *c) {
493 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
494 return ctx->aio_unwatch(handle, c->pc);
495 }
496
497 config_t IoCtx::cct() {
498 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
499 return reinterpret_cast<config_t>(ctx->get_rados_client()->cct());
500 }
501
502 void IoCtx::close() {
503 if (io_ctx_impl) {
504 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
505 ctx->put();
506 }
507 io_ctx_impl = NULL;
508 }
509
510 int IoCtx::create(const std::string& oid, bool exclusive) {
511 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
512 return ctx->execute_operation(
513 oid, boost::bind(&TestIoCtxImpl::create, _1, _2, exclusive,
514 ctx->get_snap_context()));
515 }
516
517 void IoCtx::dup(const IoCtx& rhs) {
518 close();
519 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(rhs.io_ctx_impl);
520 io_ctx_impl = reinterpret_cast<IoCtxImpl*>(ctx->clone());
521 }
522
523 int IoCtx::exec(const std::string& oid, const char *cls, const char *method,
524 bufferlist& inbl, bufferlist& outbl) {
525 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
526 return ctx->execute_operation(
527 oid, boost::bind(&TestIoCtxImpl::exec, _1, _2, get_class_handler(), cls,
528 method, inbl, &outbl, ctx->get_snap_context()));
529 }
530
531 void IoCtx::from_rados_ioctx_t(rados_ioctx_t p, IoCtx &io) {
532 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(p);
533 ctx->get();
534
535 io.close();
536 io.io_ctx_impl = reinterpret_cast<IoCtxImpl*>(ctx);
537 }
538
539 uint64_t IoCtx::get_instance_id() const {
540 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
541 return ctx->get_instance_id();
542 }
543
544 int64_t IoCtx::get_id() {
545 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
546 return ctx->get_id();
547 }
548
549 uint64_t IoCtx::get_last_version() {
550 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
551 return ctx->get_last_version();
552 }
553
554 std::string IoCtx::get_pool_name() {
555 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
556 return ctx->get_pool_name();
557 }
558
559 int IoCtx::list_snaps(const std::string& o, snap_set_t *out_snaps) {
560 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
561 return ctx->execute_operation(
562 o, boost::bind(&TestIoCtxImpl::list_snaps, _1, _2, out_snaps));
563 }
564
565 int IoCtx::list_watchers(const std::string& o,
566 std::list<obj_watch_t> *out_watchers) {
567 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
568 return ctx->execute_operation(
569 o, boost::bind(&TestIoCtxImpl::list_watchers, _1, _2, out_watchers));
570 }
571
572 int IoCtx::notify(const std::string& o, uint64_t ver, bufferlist& bl) {
573 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
574 return ctx->notify(o, bl, 0, NULL);
575 }
576
577 int IoCtx::notify2(const std::string& o, bufferlist& bl,
578 uint64_t timeout_ms, bufferlist *pbl) {
579 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
580 return ctx->notify(o, bl, timeout_ms, pbl);
581 }
582
583 void IoCtx::notify_ack(const std::string& o, uint64_t notify_id,
584 uint64_t handle, bufferlist& bl) {
585 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
586 ctx->notify_ack(o, notify_id, handle, bl);
587 }
588
589 int IoCtx::omap_get_vals(const std::string& oid,
590 const std::string& start_after,
591 uint64_t max_return,
592 std::map<std::string, bufferlist> *out_vals) {
593 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
594 return ctx->execute_operation(
595 oid, boost::bind(&TestIoCtxImpl::omap_get_vals, _1, _2, start_after, "",
596 max_return, out_vals));
597 }
598
599 int IoCtx::operate(const std::string& oid, ObjectWriteOperation *op) {
600 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
601 TestObjectOperationImpl *ops = reinterpret_cast<TestObjectOperationImpl*>(op->impl);
602 return ctx->operate(oid, *ops);
603 }
604
605 int IoCtx::operate(const std::string& oid, ObjectReadOperation *op,
606 bufferlist *pbl) {
607 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
608 TestObjectOperationImpl *ops = reinterpret_cast<TestObjectOperationImpl*>(op->impl);
609 return ctx->operate_read(oid, *ops, pbl);
610 }
611
612 int IoCtx::read(const std::string& oid, bufferlist& bl, size_t len,
613 uint64_t off) {
614 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
615 return ctx->execute_operation(
616 oid, boost::bind(&TestIoCtxImpl::read, _1, _2, len, off, &bl));
617 }
618
619 int IoCtx::remove(const std::string& oid) {
620 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
621 return ctx->execute_operation(
622 oid, boost::bind(&TestIoCtxImpl::remove, _1, _2, ctx->get_snap_context()));
623 }
624
625 int IoCtx::selfmanaged_snap_create(uint64_t *snapid) {
626 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
627 return ctx->selfmanaged_snap_create(snapid);
628 }
629
630 void IoCtx::aio_selfmanaged_snap_create(uint64_t *snapid, AioCompletion* c) {
631 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
632 return ctx->aio_selfmanaged_snap_create(snapid, c->pc);
633 }
634
635 int IoCtx::selfmanaged_snap_remove(uint64_t snapid) {
636 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
637 return ctx->selfmanaged_snap_remove(snapid);
638 }
639
640 void IoCtx::aio_selfmanaged_snap_remove(uint64_t snapid, AioCompletion* c) {
641 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
642 ctx->aio_selfmanaged_snap_remove(snapid, c->pc);
643 }
644
645 int IoCtx::selfmanaged_snap_rollback(const std::string& oid,
646 uint64_t snapid) {
647 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
648 return ctx->selfmanaged_snap_rollback(oid, snapid);
649 }
650
651 int IoCtx::selfmanaged_snap_set_write_ctx(snap_t seq,
652 std::vector<snap_t>& snaps) {
653 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
654 return ctx->selfmanaged_snap_set_write_ctx(seq, snaps);
655 }
656
657 void IoCtx::snap_set_read(snap_t seq) {
658 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
659 ctx->set_snap_read(seq);
660 }
661
662 int IoCtx::sparse_read(const std::string& oid, std::map<uint64_t,uint64_t>& m,
663 bufferlist& bl, size_t len, uint64_t off) {
664 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
665 return ctx->execute_operation(
666 oid, boost::bind(&TestIoCtxImpl::sparse_read, _1, _2, off, len, &m, &bl));
667 }
668
669 int IoCtx::stat(const std::string& oid, uint64_t *psize, time_t *pmtime) {
670 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
671 return ctx->execute_operation(
672 oid, boost::bind(&TestIoCtxImpl::stat, _1, _2, psize, pmtime));
673 }
674
675 int IoCtx::tmap_update(const std::string& oid, bufferlist& cmdbl) {
676 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
677 return ctx->execute_operation(
678 oid, boost::bind(&TestIoCtxImpl::tmap_update, _1, _2, cmdbl));
679 }
680
681 int IoCtx::trunc(const std::string& oid, uint64_t off) {
682 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
683 return ctx->execute_operation(
684 oid, boost::bind(&TestIoCtxImpl::truncate, _1, _2, off,
685 ctx->get_snap_context()));
686 }
687
688 int IoCtx::unwatch2(uint64_t handle) {
689 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
690 return ctx->unwatch(handle);
691 }
692
693 int IoCtx::unwatch(const std::string& o, uint64_t handle) {
694 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
695 return ctx->unwatch(handle);
696 }
697
698 int IoCtx::watch(const std::string& o, uint64_t ver, uint64_t *handle,
699 librados::WatchCtx *wctx) {
700 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
701 return ctx->watch(o, handle, wctx, NULL);
702 }
703
704 int IoCtx::watch2(const std::string& o, uint64_t *handle,
705 librados::WatchCtx2 *wctx) {
706 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
707 return ctx->watch(o, handle, NULL, wctx);
708 }
709
710 int IoCtx::write(const std::string& oid, bufferlist& bl, size_t len,
711 uint64_t off) {
712 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
713 return ctx->execute_operation(
714 oid, boost::bind(&TestIoCtxImpl::write, _1, _2, bl, len, off,
715 ctx->get_snap_context()));
716 }
717
718 int IoCtx::write_full(const std::string& oid, bufferlist& bl) {
719 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
720 return ctx->execute_operation(
721 oid, boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl,
722 ctx->get_snap_context()));
723 }
724
725 int IoCtx::writesame(const std::string& oid, bufferlist& bl, size_t len,
726 uint64_t off) {
727 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
728 return ctx->execute_operation(
729 oid, boost::bind(&TestIoCtxImpl::writesame, _1, _2, bl, len, off,
730 ctx->get_snap_context()));
731 }
732
733 int IoCtx::cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl) {
734 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
735 return ctx->execute_operation(
736 oid, boost::bind(&TestIoCtxImpl::cmpext, _1, _2, off, cmp_bl));
737 }
738
739 int IoCtx::application_enable(const std::string& app_name, bool force) {
740 return 0;
741 }
742
743 int IoCtx::application_enable_async(const std::string& app_name,
744 bool force, PoolAsyncCompletion *c) {
745 return -EOPNOTSUPP;
746 }
747
748 int IoCtx::application_list(std::set<std::string> *app_names) {
749 return -EOPNOTSUPP;
750 }
751
752 int IoCtx::application_metadata_get(const std::string& app_name,
753 const std::string &key,
754 std::string *value) {
755 return -EOPNOTSUPP;
756 }
757
758 int IoCtx::application_metadata_set(const std::string& app_name,
759 const std::string &key,
760 const std::string& value) {
761 return -EOPNOTSUPP;
762 }
763
764 int IoCtx::application_metadata_remove(const std::string& app_name,
765 const std::string &key) {
766 return -EOPNOTSUPP;
767 }
768
769 int IoCtx::application_metadata_list(const std::string& app_name,
770 std::map<std::string, std::string> *values) {
771 return -EOPNOTSUPP;
772 }
773
774 void IoCtx::set_namespace(const std::string& nspace) {
775 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
776 ctx->set_namespace(nspace);
777 }
778
779 std::string IoCtx::get_namespace() const {
780 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(io_ctx_impl);
781 return ctx->get_namespace();
782 }
783
784 static int save_operation_result(int result, int *pval) {
785 if (pval != NULL) {
786 *pval = result;
787 }
788 return result;
789 }
790
791 ObjectOperation::ObjectOperation() {
792 TestObjectOperationImpl *o = new TestObjectOperationImpl();
793 o->get();
794 impl = reinterpret_cast<ObjectOperationImpl*>(o);
795 }
796
797 ObjectOperation::~ObjectOperation() {
798 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
799 if (o) {
800 o->put();
801 o = NULL;
802 }
803 }
804
805 void ObjectOperation::assert_exists() {
806 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
807 o->ops.push_back(boost::bind(&TestIoCtxImpl::assert_exists, _1, _2));
808 }
809
810 void ObjectOperation::exec(const char *cls, const char *method,
811 bufferlist& inbl) {
812 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
813 o->ops.push_back(boost::bind(&TestIoCtxImpl::exec, _1, _2,
814 get_class_handler(), cls, method, inbl, _3, _4));
815 }
816
817 void ObjectOperation::set_op_flags2(int flags) {
818 }
819
820 size_t ObjectOperation::size() {
821 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
822 return o->ops.size();
823 }
824
825 void ObjectOperation::cmpext(uint64_t off, const bufferlist& cmp_bl,
826 int *prval) {
827 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
828 ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::cmpext, _1, _2, off, cmp_bl);
829 if (prval != NULL) {
830 op = boost::bind(save_operation_result,
831 boost::bind(op, _1, _2, _3, _4), prval);
832 }
833 o->ops.push_back(op);
834 }
835
836 void ObjectReadOperation::list_snaps(snap_set_t *out_snaps, int *prval) {
837 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
838
839 ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::list_snaps, _1, _2,
840 out_snaps);
841 if (prval != NULL) {
842 op = boost::bind(save_operation_result,
843 boost::bind(op, _1, _2, _3, _4), prval);
844 }
845 o->ops.push_back(op);
846 }
847
848 void ObjectReadOperation::list_watchers(std::list<obj_watch_t> *out_watchers,
849 int *prval) {
850 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
851
852 ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::list_watchers, _1,
853 _2, out_watchers);
854 if (prval != NULL) {
855 op = boost::bind(save_operation_result,
856 boost::bind(op, _1, _2, _3, _4), prval);
857 }
858 o->ops.push_back(op);
859 }
860
861 void ObjectReadOperation::read(size_t off, uint64_t len, bufferlist *pbl,
862 int *prval) {
863 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
864
865 ObjectOperationTestImpl op;
866 if (pbl != NULL) {
867 op = boost::bind(&TestIoCtxImpl::read, _1, _2, len, off, pbl);
868 } else {
869 op = boost::bind(&TestIoCtxImpl::read, _1, _2, len, off, _3);
870 }
871
872 if (prval != NULL) {
873 op = boost::bind(save_operation_result,
874 boost::bind(op, _1, _2, _3, _4), prval);
875 }
876 o->ops.push_back(op);
877 }
878
879 void ObjectReadOperation::sparse_read(uint64_t off, uint64_t len,
880 std::map<uint64_t,uint64_t> *m,
881 bufferlist *pbl, int *prval) {
882 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
883
884 ObjectOperationTestImpl op;
885 if (pbl != NULL) {
886 op = boost::bind(&TestIoCtxImpl::sparse_read, _1, _2, off, len, m, pbl);
887 } else {
888 op = boost::bind(&TestIoCtxImpl::sparse_read, _1, _2, off, len, m, _3);
889 }
890
891 if (prval != NULL) {
892 op = boost::bind(save_operation_result,
893 boost::bind(op, _1, _2, _3, _4), prval);
894 }
895 o->ops.push_back(op);
896 }
897
898 void ObjectReadOperation::stat(uint64_t *psize, time_t *pmtime, int *prval) {
899 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
900
901 ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::stat, _1, _2,
902 psize, pmtime);
903
904 if (prval != NULL) {
905 op = boost::bind(save_operation_result,
906 boost::bind(op, _1, _2, _3, _4), prval);
907 }
908 o->ops.push_back(op);
909 }
910
911 void ObjectWriteOperation::append(const bufferlist &bl) {
912 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
913 o->ops.push_back(boost::bind(&TestIoCtxImpl::append, _1, _2, bl, _4));
914 }
915
916 void ObjectWriteOperation::create(bool exclusive) {
917 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
918 o->ops.push_back(boost::bind(&TestIoCtxImpl::create, _1, _2, exclusive, _4));
919 }
920
921 void ObjectWriteOperation::omap_set(const std::map<std::string, bufferlist> &map) {
922 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
923 o->ops.push_back(boost::bind(&TestIoCtxImpl::omap_set, _1, _2, boost::ref(map)));
924 }
925
926 void ObjectWriteOperation::remove() {
927 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
928 o->ops.push_back(boost::bind(&TestIoCtxImpl::remove, _1, _2, _4));
929 }
930
931 void ObjectWriteOperation::selfmanaged_snap_rollback(uint64_t snapid) {
932 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
933 o->ops.push_back(boost::bind(&TestIoCtxImpl::selfmanaged_snap_rollback,
934 _1, _2, snapid));
935 }
936
937 void ObjectWriteOperation::set_alloc_hint(uint64_t expected_object_size,
938 uint64_t expected_write_size) {
939 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
940 o->ops.push_back(boost::bind(&TestIoCtxImpl::set_alloc_hint, _1, _2,
941 expected_object_size, expected_write_size, _4));
942 }
943
944
945 void ObjectWriteOperation::tmap_update(const bufferlist& cmdbl) {
946 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
947 o->ops.push_back(boost::bind(&TestIoCtxImpl::tmap_update, _1, _2,
948 cmdbl));
949 }
950
951 void ObjectWriteOperation::truncate(uint64_t off) {
952 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
953 o->ops.push_back(boost::bind(&TestIoCtxImpl::truncate, _1, _2, off, _4));
954 }
955
956 void ObjectWriteOperation::write(uint64_t off, const bufferlist& bl) {
957 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
958 o->ops.push_back(boost::bind(&TestIoCtxImpl::write, _1, _2, bl, bl.length(),
959 off, _4));
960 }
961
962 void ObjectWriteOperation::write_full(const bufferlist& bl) {
963 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
964 o->ops.push_back(boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl, _4));
965 }
966
967 void ObjectWriteOperation::writesame(uint64_t off, uint64_t len, const bufferlist& bl) {
968 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
969 o->ops.push_back(boost::bind(&TestIoCtxImpl::writesame, _1, _2, bl, len,
970 off, _4));
971 }
972
973 void ObjectWriteOperation::zero(uint64_t off, uint64_t len) {
974 TestObjectOperationImpl *o = reinterpret_cast<TestObjectOperationImpl*>(impl);
975 o->ops.push_back(boost::bind(&TestIoCtxImpl::zero, _1, _2, off, len, _4));
976 }
977
978 Rados::Rados() : client(NULL) {
979 }
980
981 Rados::Rados(IoCtx& ioctx) {
982 TestIoCtxImpl *ctx = reinterpret_cast<TestIoCtxImpl*>(ioctx.io_ctx_impl);
983 TestRadosClient *impl = ctx->get_rados_client();
984 impl->get();
985
986 client = reinterpret_cast<RadosClient*>(impl);
987 ceph_assert(client != NULL);
988 }
989
990 Rados::~Rados() {
991 shutdown();
992 }
993
994 void Rados::from_rados_t(rados_t p, Rados &rados) {
995 if (rados.client != nullptr) {
996 reinterpret_cast<TestRadosClient*>(rados.client)->put();
997 rados.client = nullptr;
998 }
999
1000 auto impl = reinterpret_cast<TestRadosClient*>(p);
1001 if (impl) {
1002 impl->get();
1003 rados.client = reinterpret_cast<RadosClient*>(impl);
1004 }
1005 }
1006
1007 AioCompletion *Rados::aio_create_completion(void *cb_arg,
1008 callback_t cb_complete,
1009 callback_t cb_safe) {
1010 AioCompletionImpl *c;
1011 int r = rados_aio_create_completion(cb_arg, cb_complete, cb_safe,
1012 reinterpret_cast<void**>(&c));
1013 ceph_assert(r == 0);
1014 return new AioCompletion(c);
1015 }
1016
1017 int Rados::aio_watch_flush(AioCompletion* c) {
1018 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1019 return impl->aio_watch_flush(c->pc);
1020 }
1021
1022 int Rados::blacklist_add(const std::string& client_address,
1023 uint32_t expire_seconds) {
1024 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1025 return impl->blacklist_add(client_address, expire_seconds);
1026 }
1027
1028 config_t Rados::cct() {
1029 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1030 return reinterpret_cast<config_t>(impl->cct());
1031 }
1032
1033 int Rados::cluster_fsid(std::string* fsid) {
1034 *fsid = "00000000-1111-2222-3333-444444444444";
1035 return 0;
1036 }
1037
1038 int Rados::conf_set(const char *option, const char *value) {
1039 return rados_conf_set(reinterpret_cast<rados_t>(client), option, value);
1040 }
1041
1042 int Rados::conf_get(const char *option, std::string &val) {
1043 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1044 CephContext *cct = impl->cct();
1045
1046 char *str = NULL;
1047 int ret = cct->_conf.get_val(option, &str, -1);
1048 if (ret != 0) {
1049 free(str);
1050 return ret;
1051 }
1052
1053 val = str;
1054 free(str);
1055 return 0;
1056 }
1057
1058 int Rados::conf_parse_env(const char *env) const {
1059 return rados_conf_parse_env(reinterpret_cast<rados_t>(client), env);
1060 }
1061
1062 int Rados::conf_read_file(const char * const path) const {
1063 return rados_conf_read_file(reinterpret_cast<rados_t>(client), path);
1064 }
1065
1066 int Rados::connect() {
1067 return rados_connect(reinterpret_cast<rados_t>(client));
1068 }
1069
1070 uint64_t Rados::get_instance_id() {
1071 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1072 return impl->get_instance_id();
1073 }
1074
1075 int Rados::get_min_compatible_osd(int8_t* require_osd_release) {
1076 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1077 return impl->get_min_compatible_osd(require_osd_release);
1078 }
1079
1080 int Rados::get_min_compatible_client(int8_t* min_compat_client,
1081 int8_t* require_min_compat_client) {
1082 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1083 return impl->get_min_compatible_client(min_compat_client,
1084 require_min_compat_client);
1085 }
1086
1087 int Rados::init(const char * const id) {
1088 return rados_create(reinterpret_cast<rados_t *>(&client), id);
1089 }
1090
1091 int Rados::init_with_context(config_t cct_) {
1092 return rados_create_with_context(reinterpret_cast<rados_t *>(&client), cct_);
1093 }
1094
1095 int Rados::ioctx_create(const char *name, IoCtx &io) {
1096 rados_ioctx_t p;
1097 int ret = rados_ioctx_create(reinterpret_cast<rados_t>(client), name, &p);
1098 if (ret) {
1099 return ret;
1100 }
1101
1102 io.close();
1103 io.io_ctx_impl = reinterpret_cast<IoCtxImpl*>(p);
1104 return 0;
1105 }
1106
1107 int Rados::ioctx_create2(int64_t pool_id, IoCtx &io)
1108 {
1109 rados_ioctx_t p;
1110 int ret = rados_ioctx_create2(reinterpret_cast<rados_t>(client), pool_id, &p);
1111 if (ret) {
1112 return ret;
1113 }
1114
1115 io.close();
1116 io.io_ctx_impl = reinterpret_cast<IoCtxImpl*>(p);
1117 return 0;
1118 }
1119
1120 int Rados::mon_command(std::string cmd, const bufferlist& inbl,
1121 bufferlist *outbl, std::string *outs) {
1122 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1123
1124 std::vector<std::string> cmds;
1125 cmds.push_back(cmd);
1126 return impl->mon_command(cmds, inbl, outbl, outs);
1127 }
1128
1129 int Rados::service_daemon_register(const std::string& service,
1130 const std::string& name,
1131 const std::map<std::string,std::string>& metadata) {
1132 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1133 return impl->service_daemon_register(service, name, metadata);
1134 }
1135
1136 int Rados::service_daemon_update_status(std::map<std::string,std::string>&& status) {
1137 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1138 return impl->service_daemon_update_status(std::move(status));
1139 }
1140
1141 int Rados::pool_create(const char *name) {
1142 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1143 return impl->pool_create(name);
1144 }
1145
1146 int Rados::pool_delete(const char *name) {
1147 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1148 return impl->pool_delete(name);
1149 }
1150
1151 int Rados::pool_get_base_tier(int64_t pool, int64_t* base_tier) {
1152 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1153 return impl->pool_get_base_tier(pool, base_tier);
1154 }
1155
1156 int Rados::pool_list(std::list<std::string>& v) {
1157 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1158 std::list<std::pair<int64_t, std::string> > pools;
1159 int r = impl->pool_list(pools);
1160 if (r < 0) {
1161 return r;
1162 }
1163
1164 v.clear();
1165 for (std::list<std::pair<int64_t, std::string> >::iterator it = pools.begin();
1166 it != pools.end(); ++it) {
1167 v.push_back(it->second);
1168 }
1169 return 0;
1170 }
1171
1172 int Rados::pool_list2(std::list<std::pair<int64_t, std::string> >& v)
1173 {
1174 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1175 return impl->pool_list(v);
1176 }
1177
1178 int64_t Rados::pool_lookup(const char *name) {
1179 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1180 return impl->pool_lookup(name);
1181 }
1182
1183 int Rados::pool_reverse_lookup(int64_t id, std::string *name) {
1184 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1185 return impl->pool_reverse_lookup(id, name);
1186 }
1187
1188 void Rados::shutdown() {
1189 if (client == NULL) {
1190 return;
1191 }
1192 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1193 impl->put();
1194 client = NULL;
1195 }
1196
1197 void Rados::test_blacklist_self(bool set) {
1198 }
1199
1200 int Rados::wait_for_latest_osdmap() {
1201 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1202 return impl->wait_for_latest_osdmap();
1203 }
1204
1205 int Rados::watch_flush() {
1206 TestRadosClient *impl = reinterpret_cast<TestRadosClient*>(client);
1207 return impl->watch_flush();
1208 }
1209
1210 WatchCtx::~WatchCtx() {
1211 }
1212
1213 WatchCtx2::~WatchCtx2() {
1214 }
1215
1216 } // namespace librados
1217
1218 int cls_cxx_create(cls_method_context_t hctx, bool exclusive) {
1219 librados::TestClassHandler::MethodContext *ctx =
1220 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1221 return ctx->io_ctx_impl->create(ctx->oid, exclusive, ctx->snapc);
1222 }
1223
1224 int cls_cxx_remove(cls_method_context_t hctx) {
1225 librados::TestClassHandler::MethodContext *ctx =
1226 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1227 return ctx->io_ctx_impl->remove(ctx->oid, ctx->io_ctx_impl->get_snap_context());
1228 }
1229
1230 int cls_get_request_origin(cls_method_context_t hctx, entity_inst_t *origin) {
1231 librados::TestClassHandler::MethodContext *ctx =
1232 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1233
1234 librados::TestRadosClient *rados_client =
1235 ctx->io_ctx_impl->get_rados_client();
1236
1237 struct sockaddr_in sin;
1238 memset(&sin, 0, sizeof(sin));
1239 sin.sin_family = AF_INET;
1240 sin.sin_port = 0;
1241 inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr);
1242
1243 entity_addr_t entity_addr(entity_addr_t::TYPE_DEFAULT,
1244 rados_client->get_nonce());
1245 entity_addr.in4_addr() = sin;
1246
1247 *origin = entity_inst_t(
1248 entity_name_t::CLIENT(rados_client->get_instance_id()),
1249 entity_addr);
1250 return 0;
1251 }
1252
1253 int cls_cxx_getxattr(cls_method_context_t hctx, const char *name,
1254 bufferlist *outbl) {
1255 std::map<string, bufferlist> attrs;
1256 int r = cls_cxx_getxattrs(hctx, &attrs);
1257 if (r < 0) {
1258 return r;
1259 }
1260
1261 std::map<string, bufferlist>::iterator it = attrs.find(name);
1262 if (it == attrs.end()) {
1263 return -ENODATA;
1264 }
1265 *outbl = it->second;
1266 return 0;
1267 }
1268
1269 int cls_cxx_getxattrs(cls_method_context_t hctx, std::map<string, bufferlist> *attrset) {
1270 librados::TestClassHandler::MethodContext *ctx =
1271 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1272 return ctx->io_ctx_impl->xattr_get(ctx->oid, attrset);
1273 }
1274
1275 int cls_cxx_map_get_keys(cls_method_context_t hctx, const string &start_obj,
1276 uint64_t max_to_get, std::set<string> *keys, bool *more) {
1277 librados::TestClassHandler::MethodContext *ctx =
1278 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1279
1280 keys->clear();
1281 std::map<string, bufferlist> vals;
1282 int r = ctx->io_ctx_impl->omap_get_vals2(ctx->oid, start_obj, "", max_to_get,
1283 &vals, more);
1284 if (r < 0) {
1285 return r;
1286 }
1287
1288 for (std::map<string, bufferlist>::iterator it = vals.begin();
1289 it != vals.end(); ++it) {
1290 keys->insert(it->first);
1291 }
1292 return keys->size();
1293 }
1294
1295 int cls_cxx_map_get_val(cls_method_context_t hctx, const string &key,
1296 bufferlist *outbl) {
1297 librados::TestClassHandler::MethodContext *ctx =
1298 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1299
1300 std::map<string, bufferlist> vals;
1301 int r = ctx->io_ctx_impl->omap_get_vals(ctx->oid, "", key, 1024, &vals);
1302 if (r < 0) {
1303 return r;
1304 }
1305
1306 std::map<string, bufferlist>::iterator it = vals.find(key);
1307 if (it == vals.end()) {
1308 return -ENOENT;
1309 }
1310
1311 *outbl = it->second;
1312 return 0;
1313 }
1314
1315 int cls_cxx_map_get_vals(cls_method_context_t hctx, const string &start_obj,
1316 const string &filter_prefix, uint64_t max_to_get,
1317 std::map<string, bufferlist> *vals, bool *more) {
1318 librados::TestClassHandler::MethodContext *ctx =
1319 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1320 int r = ctx->io_ctx_impl->omap_get_vals2(ctx->oid, start_obj, filter_prefix,
1321 max_to_get, vals, more);
1322 if (r < 0) {
1323 return r;
1324 }
1325 return vals->size();
1326 }
1327
1328 int cls_cxx_map_remove_key(cls_method_context_t hctx, const string &key) {
1329 std::set<std::string> keys;
1330 keys.insert(key);
1331
1332 librados::TestClassHandler::MethodContext *ctx =
1333 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1334 return ctx->io_ctx_impl->omap_rm_keys(ctx->oid, keys);
1335 }
1336
1337 int cls_cxx_map_set_val(cls_method_context_t hctx, const string &key,
1338 bufferlist *inbl) {
1339 std::map<std::string, bufferlist> m;
1340 m[key] = *inbl;
1341 return cls_cxx_map_set_vals(hctx, &m);
1342 }
1343
1344 int cls_cxx_map_set_vals(cls_method_context_t hctx,
1345 const std::map<string, bufferlist> *map) {
1346 librados::TestClassHandler::MethodContext *ctx =
1347 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1348 return ctx->io_ctx_impl->omap_set(ctx->oid, *map);
1349 }
1350
1351 int cls_cxx_read(cls_method_context_t hctx, int ofs, int len,
1352 bufferlist *outbl) {
1353 return cls_cxx_read2(hctx, ofs, len, outbl, 0);
1354 }
1355
1356 int cls_cxx_read2(cls_method_context_t hctx, int ofs, int len,
1357 bufferlist *outbl, uint32_t op_flags) {
1358 librados::TestClassHandler::MethodContext *ctx =
1359 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1360 return ctx->io_ctx_impl->read(ctx->oid, len, ofs, outbl);
1361 }
1362
1363 int cls_cxx_setxattr(cls_method_context_t hctx, const char *name,
1364 bufferlist *inbl) {
1365 librados::TestClassHandler::MethodContext *ctx =
1366 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1367 return ctx->io_ctx_impl->xattr_set(ctx->oid, name, *inbl);
1368 }
1369
1370 int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime) {
1371 librados::TestClassHandler::MethodContext *ctx =
1372 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1373 return ctx->io_ctx_impl->stat(ctx->oid, size, mtime);
1374 }
1375
1376 int cls_cxx_write(cls_method_context_t hctx, int ofs, int len,
1377 bufferlist *inbl) {
1378 return cls_cxx_write2(hctx, ofs, len, inbl, 0);
1379 }
1380
1381 int cls_cxx_write2(cls_method_context_t hctx, int ofs, int len,
1382 bufferlist *inbl, uint32_t op_flags) {
1383 librados::TestClassHandler::MethodContext *ctx =
1384 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1385 return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs, ctx->snapc);
1386 }
1387
1388 int cls_cxx_write_full(cls_method_context_t hctx, bufferlist *inbl) {
1389 librados::TestClassHandler::MethodContext *ctx =
1390 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1391 return ctx->io_ctx_impl->write_full(ctx->oid, *inbl, ctx->snapc);
1392 }
1393
1394 int cls_cxx_replace(cls_method_context_t hctx, int ofs, int len,
1395 bufferlist *inbl) {
1396 librados::TestClassHandler::MethodContext *ctx =
1397 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1398 int r = ctx->io_ctx_impl->truncate(ctx->oid, 0, ctx->snapc);
1399 if (r < 0) {
1400 return r;
1401 }
1402 return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs, ctx->snapc);
1403 }
1404
1405 int cls_cxx_truncate(cls_method_context_t hctx, int ofs) {
1406 librados::TestClassHandler::MethodContext *ctx =
1407 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1408 return ctx->io_ctx_impl->truncate(ctx->oid, ofs, ctx->snapc);
1409 }
1410
1411 int cls_cxx_list_watchers(cls_method_context_t hctx,
1412 obj_list_watch_response_t *watchers) {
1413 librados::TestClassHandler::MethodContext *ctx =
1414 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1415
1416 std::list<obj_watch_t> obj_watchers;
1417 int r = ctx->io_ctx_impl->list_watchers(ctx->oid, &obj_watchers);
(1) Event cond_false: |
Condition "r < 0", taking false branch. |
1418 if (r < 0) {
1419 return r;
(2) Event if_end: |
End of if statement. |
1420 }
1421
(3) Event for_loop: |
Iterating over another element of "obj_watchers". |
1422 for (auto &w : obj_watchers) {
1423 watch_item_t watcher;
1424 watcher.name = entity_name_t::CLIENT(w.watcher_id);
1425 watcher.cookie = w.cookie;
1426 watcher.timeout_seconds = w.timeout_seconds;
1427 watcher.addr.parse(w.addr, 0);
1428 watchers->entries.push_back(watcher);
1429 }
1430
1431 return 0;
1432 }
1433
1434 uint64_t cls_get_features(cls_method_context_t hctx) {
1435 return CEPH_FEATURES_SUPPORTED_DEFAULT;
1436 }
1437
1438 uint64_t cls_get_client_features(cls_method_context_t hctx) {
1439 return CEPH_FEATURES_SUPPORTED_DEFAULT;
1440 }
1441
1442 int cls_get_snapset_seq(cls_method_context_t hctx, uint64_t *snap_seq) {
1443 librados::TestClassHandler::MethodContext *ctx =
1444 reinterpret_cast<librados::TestClassHandler::MethodContext*>(hctx);
1445 librados::snap_set_t snapset;
1446 int r = ctx->io_ctx_impl->list_snaps(ctx->oid, &snapset);
1447 if (r < 0) {
1448 return r;
1449 }
1450
1451 *snap_seq = snapset.seq;
1452 return 0;
1453 }
1454
1455 int cls_log(int level, const char *format, ...) {
1456 int size = 256;
1457 va_list ap;
1458 while (1) {
1459 char buf[size];
1460 va_start(ap, format);
1461 int n = vsnprintf(buf, size, format, ap);
1462 va_end(ap);
1463 if ((n > -1 && n < size) || size > 8196) {
1464 dout(ceph::dout::need_dynamic(level)) << buf << dendl;
1465 return n;
1466 }
1467 size *= 2;
1468 }
1469 return 0;
1470 }
1471
1472 int cls_register(const char *name, cls_handle_t *handle) {
1473 librados::TestClassHandler *cls = get_class_handler();
1474 return cls->create(name, handle);
1475 }
1476
1477 int cls_register_cxx_method(cls_handle_t hclass, const char *method,
1478 int flags,
1479 cls_method_cxx_call_t class_call,
1480 cls_method_handle_t *handle) {
1481 librados::TestClassHandler *cls = get_class_handler();
1482 return cls->create_method(hclass, method, class_call, handle);
1483 }
1484
1485 int cls_register_cxx_filter(cls_handle_t hclass,
1486 const std::string &filter_name,
1487 cls_cxx_filter_factory_t fn,
1488 cls_filter_handle_t *)
1489 {
1490 librados::TestClassHandler *cls = get_class_handler();
1491 return cls->create_filter(hclass, filter_name, fn);
1492 }
1493
1494 ceph_release_t cls_get_required_osd_release(cls_handle_t hclass) {
1495 return ceph_release_t::nautilus;
1496 }
1497
1498 ceph_release_t cls_get_min_compatible_client(cls_handle_t hclass) {
1499 return ceph_release_t::nautilus;
1500 }
1501
1502 // stubs to silence TestClassHandler::open_class()
1503 PGLSFilter::~PGLSFilter()
1504 {}
1505
1506 int cls_gen_rand_base64(char *, int) {
1507 return -ENOTSUP;
1508 }
1509
1510 int cls_cxx_chunk_write_and_set(cls_method_handle_t, int,
1511 int, bufferlist *,
1512 uint32_t, bufferlist *, int) {
1513 return -ENOTSUP;
1514 }
1515
1516 int cls_cxx_map_read_header(cls_method_handle_t, bufferlist *) {
1517 return -ENOTSUP;
1518 }
1519
1520 uint64_t cls_get_osd_min_alloc_size(cls_method_context_t hctx) {
1521 return 0;
1522 }
1523