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