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