]> git.proxmox.com Git - ceph.git/blame - ceph/src/librados/librados.cc
bump version to 12.0.3-pve3
[ceph.git] / ceph / src / librados / librados.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2012 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include <limits.h>
16
17#include "common/config.h"
18#include "common/errno.h"
19#include "common/ceph_argparse.h"
20#include "common/ceph_json.h"
21#include "common/common_init.h"
22#include "common/TracepointProvider.h"
23#include "common/hobject.h"
24#include "include/rados/librados.h"
25#include "include/rados/librados.hpp"
26#include "include/types.h"
27#include <include/stringify.h>
28
29#include "librados/AioCompletionImpl.h"
30#include "librados/IoCtxImpl.h"
31#include "librados/PoolAsyncCompletionImpl.h"
32#include "librados/RadosClient.h"
33#include "librados/RadosXattrIter.h"
34#include "librados/ListObjectImpl.h"
35#include <cls/lock/cls_lock_client.h>
36
37#include <string>
38#include <map>
39#include <set>
40#include <vector>
41#include <list>
42#include <stdexcept>
43
44#ifdef WITH_LTTNG
45#define TRACEPOINT_DEFINE
46#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
47#include "tracing/librados.h"
48#undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
49#undef TRACEPOINT_DEFINE
50#else
51#define tracepoint(...)
52#endif
53
54using std::string;
55using std::map;
56using std::set;
57using std::vector;
58using std::list;
59using std::runtime_error;
60
61#define dout_subsys ceph_subsys_rados
62#undef dout_prefix
63#define dout_prefix *_dout << "librados: "
64
65#define RADOS_LIST_MAX_ENTRIES 1024
66
67namespace {
68
69TracepointProvider::Traits tracepoint_traits("librados_tp.so", "rados_tracing");
70
71uint8_t get_checksum_op_type(rados_checksum_type_t type) {
72 switch (type) {
73 case LIBRADOS_CHECKSUM_TYPE_XXHASH32:
74 return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH32;
75 case LIBRADOS_CHECKSUM_TYPE_XXHASH64:
76 return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH64;
77 case LIBRADOS_CHECKSUM_TYPE_CRC32C:
78 return CEPH_OSD_CHECKSUM_OP_TYPE_CRC32C;
79 default:
80 return -1;
81 }
82}
83
84} // anonymous namespace
85
86/*
87 * Structure of this file
88 *
89 * RadosClient and the related classes are the internal implementation of librados.
90 * Above that layer sits the C API, found in include/rados/librados.h, and
91 * the C++ API, found in include/rados/librados.hpp
92 *
93 * The C++ API sometimes implements things in terms of the C API.
94 * Both the C++ and C API rely on RadosClient.
95 *
96 * Visually:
97 * +--------------------------------------+
98 * | C++ API |
99 * +--------------------+ |
100 * | C API | |
101 * +--------------------+-----------------+
102 * | RadosClient |
103 * +--------------------------------------+
104 */
105
106namespace librados {
107
108struct ObjectOperationImpl {
109 ::ObjectOperation o;
110 real_time rt;
111 real_time *prt;
112
113 ObjectOperationImpl() : prt(NULL) {}
114};
115
116}
117
118size_t librados::ObjectOperation::size()
119{
120 ::ObjectOperation *o = &impl->o;
121 return o->size();
122}
123
124static void set_op_flags(::ObjectOperation *o, int flags)
125{
126 int rados_flags = 0;
127 if (flags & LIBRADOS_OP_FLAG_EXCL)
128 rados_flags |= CEPH_OSD_OP_FLAG_EXCL;
129 if (flags & LIBRADOS_OP_FLAG_FAILOK)
130 rados_flags |= CEPH_OSD_OP_FLAG_FAILOK;
131 if (flags & LIBRADOS_OP_FLAG_FADVISE_RANDOM)
132 rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_RANDOM;
133 if (flags & LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL)
134 rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL;
135 if (flags & LIBRADOS_OP_FLAG_FADVISE_WILLNEED)
136 rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_WILLNEED;
137 if (flags & LIBRADOS_OP_FLAG_FADVISE_DONTNEED)
138 rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_DONTNEED;
139 if (flags & LIBRADOS_OP_FLAG_FADVISE_NOCACHE)
140 rados_flags |= CEPH_OSD_OP_FLAG_FADVISE_NOCACHE;
141 o->set_last_op_flags(rados_flags);
142}
143
144//deprcated
145void librados::ObjectOperation::set_op_flags(ObjectOperationFlags flags)
146{
147 ::set_op_flags(&impl->o, (int)flags);
148}
149
150void librados::ObjectOperation::set_op_flags2(int flags)
151{
152 ::ObjectOperation *o = &impl->o;
153 ::set_op_flags(o, flags);
154}
155
156void librados::ObjectOperation::cmpext(uint64_t off,
157 bufferlist &cmp_bl,
158 int *prval)
159{
160 ::ObjectOperation *o = &impl->o;
161 o->cmpext(off, cmp_bl, prval);
162}
163
164void librados::ObjectOperation::cmpxattr(const char *name, uint8_t op, const bufferlist& v)
165{
166 ::ObjectOperation *o = &impl->o;
167 o->cmpxattr(name, op, CEPH_OSD_CMPXATTR_MODE_STRING, v);
168}
169
170void librados::ObjectOperation::cmpxattr(const char *name, uint8_t op, uint64_t v)
171{
172 ::ObjectOperation *o = &impl->o;
173 bufferlist bl;
174 ::encode(v, bl);
175 o->cmpxattr(name, op, CEPH_OSD_CMPXATTR_MODE_U64, bl);
176}
177
178void librados::ObjectOperation::assert_version(uint64_t ver)
179{
180 ::ObjectOperation *o = &impl->o;
181 o->assert_version(ver);
182}
183
184void librados::ObjectOperation::assert_exists()
185{
186 ::ObjectOperation *o = &impl->o;
187 o->stat(NULL, (ceph::real_time*) NULL, NULL);
188}
189
190void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl)
191{
192 ::ObjectOperation *o = &impl->o;
193 o->call(cls, method, inbl);
194}
195
196void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl, bufferlist *outbl, int *prval)
197{
198 ::ObjectOperation *o = &impl->o;
199 o->call(cls, method, inbl, outbl, NULL, prval);
200}
201
202class ObjectOpCompletionCtx : public Context {
203 librados::ObjectOperationCompletion *completion;
204 bufferlist bl;
205public:
206 explicit ObjectOpCompletionCtx(librados::ObjectOperationCompletion *c) : completion(c) {}
207 void finish(int r) override {
208 completion->handle_completion(r, bl);
209 delete completion;
210 }
211
212 bufferlist *outbl() {
213 return &bl;
214 }
215};
216
217void librados::ObjectOperation::exec(const char *cls, const char *method, bufferlist& inbl, librados::ObjectOperationCompletion *completion)
218{
219 ::ObjectOperation *o = &impl->o;
220
221 ObjectOpCompletionCtx *ctx = new ObjectOpCompletionCtx(completion);
222
223 o->call(cls, method, inbl, ctx->outbl(), ctx, NULL);
224}
225
226void librados::ObjectReadOperation::stat(uint64_t *psize, time_t *pmtime, int *prval)
227{
228 ::ObjectOperation *o = &impl->o;
229 o->stat(psize, pmtime, prval);
230}
231
232void librados::ObjectReadOperation::stat2(uint64_t *psize, struct timespec *pts, int *prval)
233{
234 ::ObjectOperation *o = &impl->o;
235 o->stat(psize, pts, prval);
236}
237
238void librados::ObjectReadOperation::read(size_t off, uint64_t len, bufferlist *pbl, int *prval)
239{
240 ::ObjectOperation *o = &impl->o;
241 o->read(off, len, pbl, prval, NULL);
242}
243
244void librados::ObjectReadOperation::sparse_read(uint64_t off, uint64_t len,
245 std::map<uint64_t,uint64_t> *m,
246 bufferlist *data_bl, int *prval)
247{
248 ::ObjectOperation *o = &impl->o;
249 o->sparse_read(off, len, m, data_bl, prval);
250}
251
252void librados::ObjectReadOperation::checksum(rados_checksum_type_t type,
253 const bufferlist &init_value_bl,
254 uint64_t off, size_t len,
255 size_t chunk_size, bufferlist *pbl,
256 int *prval)
257{
258 ::ObjectOperation *o = &impl->o;
259 o->checksum(get_checksum_op_type(type), init_value_bl, off, len, chunk_size,
260 pbl, prval, nullptr);
261}
262
263void librados::ObjectReadOperation::tmap_get(bufferlist *pbl, int *prval)
264{
265 ::ObjectOperation *o = &impl->o;
266 o->tmap_get(pbl, prval);
267}
268
269void librados::ObjectReadOperation::getxattr(const char *name, bufferlist *pbl, int *prval)
270{
271 ::ObjectOperation *o = &impl->o;
272 o->getxattr(name, pbl, prval);
273}
274
275void librados::ObjectReadOperation::omap_get_vals(
276 const std::string &start_after,
277 const std::string &filter_prefix,
278 uint64_t max_return,
279 std::map<std::string, bufferlist> *out_vals,
280 int *prval)
281{
282 ::ObjectOperation *o = &impl->o;
283 o->omap_get_vals(start_after, filter_prefix, max_return, out_vals, nullptr,
284 prval);
285}
286
287void librados::ObjectReadOperation::omap_get_vals2(
288 const std::string &start_after,
289 const std::string &filter_prefix,
290 uint64_t max_return,
291 std::map<std::string, bufferlist> *out_vals,
292 bool *pmore,
293 int *prval)
294{
295 ::ObjectOperation *o = &impl->o;
296 o->omap_get_vals(start_after, filter_prefix, max_return, out_vals, pmore,
297 prval);
298}
299
300void librados::ObjectReadOperation::omap_get_vals(
301 const std::string &start_after,
302 uint64_t max_return,
303 std::map<std::string, bufferlist> *out_vals,
304 int *prval)
305{
306 ::ObjectOperation *o = &impl->o;
307 o->omap_get_vals(start_after, "", max_return, out_vals, nullptr, prval);
308}
309
310void librados::ObjectReadOperation::omap_get_vals2(
311 const std::string &start_after,
312 uint64_t max_return,
313 std::map<std::string, bufferlist> *out_vals,
314 bool *pmore,
315 int *prval)
316{
317 ::ObjectOperation *o = &impl->o;
318 o->omap_get_vals(start_after, "", max_return, out_vals, pmore, prval);
319}
320
321void librados::ObjectReadOperation::omap_get_keys(
322 const std::string &start_after,
323 uint64_t max_return,
324 std::set<std::string> *out_keys,
325 int *prval)
326{
327 ::ObjectOperation *o = &impl->o;
328 o->omap_get_keys(start_after, max_return, out_keys, nullptr, prval);
329}
330
331void librados::ObjectReadOperation::omap_get_keys2(
332 const std::string &start_after,
333 uint64_t max_return,
334 std::set<std::string> *out_keys,
335 bool *pmore,
336 int *prval)
337{
338 ::ObjectOperation *o = &impl->o;
339 o->omap_get_keys(start_after, max_return, out_keys, pmore, prval);
340}
341
342void librados::ObjectReadOperation::omap_get_header(bufferlist *bl, int *prval)
343{
344 ::ObjectOperation *o = &impl->o;
345 o->omap_get_header(bl, prval);
346}
347
348void librados::ObjectReadOperation::omap_get_vals_by_keys(
349 const std::set<std::string> &keys,
350 std::map<std::string, bufferlist> *map,
351 int *prval)
352{
353 ::ObjectOperation *o = &impl->o;
354 o->omap_get_vals_by_keys(keys, map, prval);
355}
356
357void librados::ObjectOperation::omap_cmp(
358 const std::map<std::string, pair<bufferlist, int> > &assertions,
359 int *prval)
360{
361 ::ObjectOperation *o = &impl->o;
362 o->omap_cmp(assertions, prval);
363}
364
365void librados::ObjectReadOperation::list_watchers(
366 list<obj_watch_t> *out_watchers,
367 int *prval)
368{
369 ::ObjectOperation *o = &impl->o;
370 o->list_watchers(out_watchers, prval);
371}
372
373void librados::ObjectReadOperation::list_snaps(
374 snap_set_t *out_snaps,
375 int *prval)
376{
377 ::ObjectOperation *o = &impl->o;
378 o->list_snaps(out_snaps, prval);
379}
380
381void librados::ObjectReadOperation::is_dirty(bool *is_dirty, int *prval)
382{
383 ::ObjectOperation *o = &impl->o;
384 o->is_dirty(is_dirty, prval);
385}
386
387int librados::IoCtx::omap_get_vals(const std::string& oid,
388 const std::string& orig_start_after,
389 const std::string& filter_prefix,
390 uint64_t max_return,
391 std::map<std::string, bufferlist> *out_vals)
392{
393 bool first = true;
394 string start_after = orig_start_after;
395 bool more = true;
396 while (max_return > 0 && more) {
397 std::map<std::string,bufferlist> out;
398 ObjectReadOperation op;
399 op.omap_get_vals2(start_after, filter_prefix, max_return, &out, &more,
400 nullptr);
401 bufferlist bl;
402 int ret = operate(oid, &op, &bl);
403 if (ret < 0) {
404 return ret;
405 }
406 if (more) {
407 if (out.empty()) {
408 return -EINVAL; // wth
409 }
410 start_after = out.rbegin()->first;
411 }
412 if (out.size() <= max_return) {
413 max_return -= out.size();
414 } else {
415 max_return = 0;
416 }
417 if (first) {
418 out_vals->swap(out);
419 first = false;
420 } else {
421 out_vals->insert(out.begin(), out.end());
422 out.clear();
423 }
424 }
425 return 0;
426}
427
428int librados::IoCtx::omap_get_vals2(
429 const std::string& oid,
430 const std::string& start_after,
431 const std::string& filter_prefix,
432 uint64_t max_return,
433 std::map<std::string, bufferlist> *out_vals,
434 bool *pmore)
435{
436 ObjectReadOperation op;
437 int r;
438 op.omap_get_vals2(start_after, filter_prefix, max_return, out_vals, pmore, &r);
439 bufferlist bl;
440 int ret = operate(oid, &op, &bl);
441 if (ret < 0)
442 return ret;
443 return r;
444}
445
446void librados::ObjectReadOperation::getxattrs(map<string, bufferlist> *pattrs, int *prval)
447{
448 ::ObjectOperation *o = &impl->o;
449 o->getxattrs(pattrs, prval);
450}
451
452void librados::ObjectWriteOperation::mtime(time_t *pt)
453{
454 if (pt) {
455 impl->rt = ceph::real_clock::from_time_t(*pt);
456 impl->prt = &impl->rt;
457 }
458}
459
460void librados::ObjectWriteOperation::mtime2(struct timespec *pts)
461{
462 if (pts) {
463 impl->rt = ceph::real_clock::from_timespec(*pts);
464 impl->prt = &impl->rt;
465 }
466}
467
468void librados::ObjectWriteOperation::create(bool exclusive)
469{
470 ::ObjectOperation *o = &impl->o;
471 o->create(exclusive);
472}
473
474void librados::ObjectWriteOperation::create(bool exclusive,
475 const std::string& category) // unused
476{
477 ::ObjectOperation *o = &impl->o;
478 o->create(exclusive);
479}
480
481void librados::ObjectWriteOperation::write(uint64_t off, const bufferlist& bl)
482{
483 ::ObjectOperation *o = &impl->o;
484 bufferlist c = bl;
485 o->write(off, c);
486}
487
488void librados::ObjectWriteOperation::write_full(const bufferlist& bl)
489{
490 ::ObjectOperation *o = &impl->o;
491 bufferlist c = bl;
492 o->write_full(c);
493}
494
495void librados::ObjectWriteOperation::writesame(uint64_t off, uint64_t write_len,
496 const bufferlist& bl)
497{
498 ::ObjectOperation *o = &impl->o;
499 bufferlist c = bl;
500 o->writesame(off, write_len, c);
501}
502
503void librados::ObjectWriteOperation::append(const bufferlist& bl)
504{
505 ::ObjectOperation *o = &impl->o;
506 bufferlist c = bl;
507 o->append(c);
508}
509
510void librados::ObjectWriteOperation::remove()
511{
512 ::ObjectOperation *o = &impl->o;
513 o->remove();
514}
515
516void librados::ObjectWriteOperation::truncate(uint64_t off)
517{
518 ::ObjectOperation *o = &impl->o;
519 o->truncate(off);
520}
521
522void librados::ObjectWriteOperation::zero(uint64_t off, uint64_t len)
523{
524 ::ObjectOperation *o = &impl->o;
525 o->zero(off, len);
526}
527
528void librados::ObjectWriteOperation::rmxattr(const char *name)
529{
530 ::ObjectOperation *o = &impl->o;
531 o->rmxattr(name);
532}
533
534void librados::ObjectWriteOperation::setxattr(const char *name, const bufferlist& v)
535{
536 ::ObjectOperation *o = &impl->o;
537 o->setxattr(name, v);
538}
539
540void librados::ObjectWriteOperation::omap_set(
541 const map<string, bufferlist> &map)
542{
543 ::ObjectOperation *o = &impl->o;
544 o->omap_set(map);
545}
546
547void librados::ObjectWriteOperation::omap_set_header(const bufferlist &bl)
548{
549 bufferlist c = bl;
550 ::ObjectOperation *o = &impl->o;
551 o->omap_set_header(c);
552}
553
554void librados::ObjectWriteOperation::omap_clear()
555{
556 ::ObjectOperation *o = &impl->o;
557 o->omap_clear();
558}
559
560void librados::ObjectWriteOperation::omap_rm_keys(
561 const std::set<std::string> &to_rm)
562{
563 ::ObjectOperation *o = &impl->o;
564 o->omap_rm_keys(to_rm);
565}
566
567void librados::ObjectWriteOperation::copy_from(const std::string& src,
568 const IoCtx& src_ioctx,
569 uint64_t src_version)
570{
571 copy_from2(src, src_ioctx, src_version, 0);
572}
573
574void librados::ObjectWriteOperation::copy_from2(const std::string& src,
575 const IoCtx& src_ioctx,
576 uint64_t src_version,
577 uint32_t src_fadvise_flags)
578{
579 ::ObjectOperation *o = &impl->o;
580 o->copy_from(object_t(src), src_ioctx.io_ctx_impl->snap_seq,
581 src_ioctx.io_ctx_impl->oloc, src_version, 0, src_fadvise_flags);
582}
583
584void librados::ObjectWriteOperation::undirty()
585{
586 ::ObjectOperation *o = &impl->o;
587 o->undirty();
588}
589
590void librados::ObjectReadOperation::cache_flush()
591{
592 ::ObjectOperation *o = &impl->o;
593 o->cache_flush();
594}
595
596void librados::ObjectReadOperation::cache_try_flush()
597{
598 ::ObjectOperation *o = &impl->o;
599 o->cache_try_flush();
600}
601
602void librados::ObjectReadOperation::cache_evict()
603{
604 ::ObjectOperation *o = &impl->o;
605 o->cache_evict();
606}
607
608void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl)
609{
610 ::ObjectOperation *o = &impl->o;
611 bufferlist c = bl;
612 o->tmap_put(c);
613}
614
615void librados::ObjectWriteOperation::tmap_update(const bufferlist& cmdbl)
616{
617 ::ObjectOperation *o = &impl->o;
618 bufferlist c = cmdbl;
619 o->tmap_update(c);
620}
621
622void librados::ObjectWriteOperation::selfmanaged_snap_rollback(snap_t snapid)
623{
624 ::ObjectOperation *o = &impl->o;
625 o->rollback(snapid);
626}
627
628// You must specify the snapid not the name normally used with pool snapshots
629void librados::ObjectWriteOperation::snap_rollback(snap_t snapid)
630{
631 ::ObjectOperation *o = &impl->o;
632 o->rollback(snapid);
633}
634
635void librados::ObjectWriteOperation::set_alloc_hint(
636 uint64_t expected_object_size,
637 uint64_t expected_write_size)
638{
639 ::ObjectOperation *o = &impl->o;
640 o->set_alloc_hint(expected_object_size, expected_write_size, 0);
641}
642void librados::ObjectWriteOperation::set_alloc_hint2(
643 uint64_t expected_object_size,
644 uint64_t expected_write_size,
645 uint32_t flags)
646{
647 ::ObjectOperation *o = &impl->o;
648 o->set_alloc_hint(expected_object_size, expected_write_size, flags);
649}
650
651void librados::ObjectWriteOperation::cache_pin()
652{
653 ::ObjectOperation *o = &impl->o;
654 o->cache_pin();
655}
656
657void librados::ObjectWriteOperation::cache_unpin()
658{
659 ::ObjectOperation *o = &impl->o;
660 o->cache_unpin();
661}
662
663librados::WatchCtx::
664~WatchCtx()
665{
666}
667
668librados::WatchCtx2::
669~WatchCtx2()
670{
671}
672
673
674struct librados::ObjListCtx {
675 librados::IoCtxImpl dupctx;
676 librados::IoCtxImpl *ctx;
677 Objecter::NListContext *nlc;
678 bool legacy_list_api;
679
680 ObjListCtx(IoCtxImpl *c, Objecter::NListContext *nl, bool legacy=false)
681 : nlc(nl),
682 legacy_list_api(legacy) {
683 // Get our own private IoCtxImpl so that namespace setting isn't
684 // changed by caller between uses.
685 ctx = &dupctx;
686 dupctx.dup(*c);
687 }
688 ~ObjListCtx() {
689 ctx = NULL;
690 delete nlc;
691 }
692};
693
694///////////////////////////// NObjectIteratorImpl /////////////////////////////
695librados::NObjectIteratorImpl::NObjectIteratorImpl(ObjListCtx *ctx_)
696 : ctx(ctx_)
697{
698}
699
700librados::NObjectIteratorImpl::~NObjectIteratorImpl()
701{
702 ctx.reset();
703}
704
705librados::NObjectIteratorImpl::NObjectIteratorImpl(const NObjectIteratorImpl &rhs)
706{
707 *this = rhs;
708}
709
710librados::NObjectIteratorImpl& librados::NObjectIteratorImpl::operator=(const librados::NObjectIteratorImpl &rhs)
711{
712 if (&rhs == this)
713 return *this;
714 if (rhs.ctx.get() == NULL) {
715 ctx.reset();
716 return *this;
717 }
718 Objecter::NListContext *list_ctx = new Objecter::NListContext(*rhs.ctx->nlc);
719 ctx.reset(new ObjListCtx(rhs.ctx->ctx, list_ctx));
720 cur_obj = rhs.cur_obj;
721 return *this;
722}
723
724bool librados::NObjectIteratorImpl::operator==(const librados::NObjectIteratorImpl& rhs) const {
725
726 if (ctx.get() == NULL) {
727 if (rhs.ctx.get() == NULL)
728 return true;
729 return rhs.ctx->nlc->at_end();
730 }
731 if (rhs.ctx.get() == NULL) {
732 // Redundant but same as ObjectIterator version
733 if (ctx.get() == NULL)
734 return true;
735 return ctx->nlc->at_end();
736 }
737 return ctx.get() == rhs.ctx.get();
738}
739
740bool librados::NObjectIteratorImpl::operator!=(const librados::NObjectIteratorImpl& rhs) const {
741 return !(*this == rhs);
742}
743
744const librados::ListObject& librados::NObjectIteratorImpl::operator*() const {
745 return cur_obj;
746}
747
748const librados::ListObject* librados::NObjectIteratorImpl::operator->() const {
749 return &cur_obj;
750}
751
752librados::NObjectIteratorImpl& librados::NObjectIteratorImpl::operator++()
753{
754 get_next();
755 return *this;
756}
757
758librados::NObjectIteratorImpl librados::NObjectIteratorImpl::operator++(int)
759{
760 librados::NObjectIteratorImpl ret(*this);
761 get_next();
762 return ret;
763}
764
765uint32_t librados::NObjectIteratorImpl::seek(uint32_t pos)
766{
767 uint32_t r = rados_nobjects_list_seek(ctx.get(), pos);
768 get_next();
769 return r;
770}
771
772uint32_t librados::NObjectIteratorImpl::seek(const ObjectCursor& cursor)
773{
774 uint32_t r = rados_nobjects_list_seek_cursor(ctx.get(), (rados_object_list_cursor)cursor.c_cursor);
775 get_next();
776 return r;
777}
778
779librados::ObjectCursor librados::NObjectIteratorImpl::get_cursor()
780{
781 librados::ObjListCtx *lh = (librados::ObjListCtx *)ctx.get();
782 librados::ObjectCursor oc;
783 oc.set(lh->ctx->nlist_get_cursor(lh->nlc));
784 return oc;
785}
786
787void librados::NObjectIteratorImpl::set_filter(const bufferlist &bl)
788{
789 assert(ctx);
790 ctx->nlc->filter = bl;
791}
792
793void librados::NObjectIteratorImpl::get_next()
794{
795 const char *entry, *key, *nspace;
796 if (ctx->nlc->at_end())
797 return;
798 int ret = rados_nobjects_list_next(ctx.get(), &entry, &key, &nspace);
799 if (ret == -ENOENT) {
800 return;
801 }
802 else if (ret) {
803 ostringstream oss;
804 oss << "rados returned " << cpp_strerror(ret);
805 throw std::runtime_error(oss.str());
806 }
807
808 if (cur_obj.impl == NULL)
809 cur_obj.impl = new ListObjectImpl();
810 cur_obj.impl->nspace = nspace;
811 cur_obj.impl->oid = entry;
812 cur_obj.impl->locator = key ? key : string();
813}
814
815uint32_t librados::NObjectIteratorImpl::get_pg_hash_position() const
816{
817 return ctx->nlc->get_pg_hash_position();
818}
819
820///////////////////////////// NObjectIterator /////////////////////////////
821librados::NObjectIterator::NObjectIterator(ObjListCtx *ctx_)
822{
823 impl = new NObjectIteratorImpl(ctx_);
824}
825
826librados::NObjectIterator::~NObjectIterator()
827{
828 delete impl;
829}
830
831librados::NObjectIterator::NObjectIterator(const NObjectIterator &rhs)
832{
833 if (rhs.impl == NULL) {
834 impl = NULL;
835 return;
836 }
837 impl = new NObjectIteratorImpl();
838 *impl = *(rhs.impl);
839}
840
841librados::NObjectIterator& librados::NObjectIterator::operator=(const librados::NObjectIterator &rhs)
842{
843 if (rhs.impl == NULL) {
844 delete impl;
845 impl = NULL;
846 return *this;
847 }
848 if (impl == NULL)
849 impl = new NObjectIteratorImpl();
850 *impl = *(rhs.impl);
851 return *this;
852}
853
854bool librados::NObjectIterator::operator==(const librados::NObjectIterator& rhs) const
855{
856 if (impl && rhs.impl) {
857 return *impl == *(rhs.impl);
858 } else {
859 return impl == rhs.impl;
860 }
861}
862
863bool librados::NObjectIterator::operator!=(const librados::NObjectIterator& rhs) const
864{
865 return !(*this == rhs);
866}
867
868const librados::ListObject& librados::NObjectIterator::operator*() const {
869 assert(impl);
870 return *(impl->get_listobjectp());
871}
872
873const librados::ListObject* librados::NObjectIterator::operator->() const {
874 assert(impl);
875 return impl->get_listobjectp();
876}
877
878librados::NObjectIterator& librados::NObjectIterator::operator++()
879{
880 assert(impl);
881 impl->get_next();
882 return *this;
883}
884
885librados::NObjectIterator librados::NObjectIterator::operator++(int)
886{
887 librados::NObjectIterator ret(*this);
888 impl->get_next();
889 return ret;
890}
891
892uint32_t librados::NObjectIterator::seek(uint32_t pos)
893{
894 assert(impl);
895 return impl->seek(pos);
896}
897
898uint32_t librados::NObjectIterator::seek(const ObjectCursor& cursor)
899{
900 assert(impl);
901 return impl->seek(cursor);
902}
903
904librados::ObjectCursor librados::NObjectIterator::get_cursor()
905{
906 assert(impl);
907 return impl->get_cursor();
908}
909
910void librados::NObjectIterator::set_filter(const bufferlist &bl)
911{
912 impl->set_filter(bl);
913}
914
915void librados::NObjectIterator::get_next()
916{
917 assert(impl);
918 impl->get_next();
919}
920
921uint32_t librados::NObjectIterator::get_pg_hash_position() const
922{
923 assert(impl);
924 return impl->get_pg_hash_position();
925}
926
927const librados::NObjectIterator librados::NObjectIterator::__EndObjectIterator(NULL);
928
929///////////////////////////// PoolAsyncCompletion //////////////////////////////
930int librados::PoolAsyncCompletion::PoolAsyncCompletion::set_callback(void *cb_arg,
931 rados_callback_t cb)
932{
933 PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
934 return c->set_callback(cb_arg, cb);
935}
936
937int librados::PoolAsyncCompletion::PoolAsyncCompletion::wait()
938{
939 PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
940 return c->wait();
941}
942
943bool librados::PoolAsyncCompletion::PoolAsyncCompletion::is_complete()
944{
945 PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
946 return c->is_complete();
947}
948
949int librados::PoolAsyncCompletion::PoolAsyncCompletion::get_return_value()
950{
951 PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
952 return c->get_return_value();
953}
954
955void librados::PoolAsyncCompletion::PoolAsyncCompletion::release()
956{
957 PoolAsyncCompletionImpl *c = (PoolAsyncCompletionImpl *)pc;
958 c->release();
959 delete this;
960}
961
962///////////////////////////// AioCompletion //////////////////////////////
963int librados::AioCompletion::AioCompletion::set_complete_callback(void *cb_arg, rados_callback_t cb)
964{
965 AioCompletionImpl *c = (AioCompletionImpl *)pc;
966 return c->set_complete_callback(cb_arg, cb);
967}
968
969int librados::AioCompletion::AioCompletion::set_safe_callback(void *cb_arg, rados_callback_t cb)
970{
971 AioCompletionImpl *c = (AioCompletionImpl *)pc;
972 return c->set_safe_callback(cb_arg, cb);
973}
974
975int librados::AioCompletion::AioCompletion::wait_for_complete()
976{
977 AioCompletionImpl *c = (AioCompletionImpl *)pc;
978 return c->wait_for_complete();
979}
980
981int librados::AioCompletion::AioCompletion::wait_for_safe()
982{
983 AioCompletionImpl *c = (AioCompletionImpl *)pc;
984 return c->wait_for_safe();
985}
986
987bool librados::AioCompletion::AioCompletion::is_complete()
988{
989 AioCompletionImpl *c = (AioCompletionImpl *)pc;
990 return c->is_complete();
991}
992
993bool librados::AioCompletion::AioCompletion::is_safe()
994{
995 AioCompletionImpl *c = (AioCompletionImpl *)pc;
996 return c->is_safe();
997}
998
999int librados::AioCompletion::AioCompletion::wait_for_complete_and_cb()
1000{
1001 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1002 return c->wait_for_complete_and_cb();
1003}
1004
1005int librados::AioCompletion::AioCompletion::wait_for_safe_and_cb()
1006{
1007 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1008 return c->wait_for_safe_and_cb();
1009}
1010
1011bool librados::AioCompletion::AioCompletion::is_complete_and_cb()
1012{
1013 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1014 return c->is_complete_and_cb();
1015}
1016
1017bool librados::AioCompletion::AioCompletion::is_safe_and_cb()
1018{
1019 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1020 return c->is_safe_and_cb();
1021}
1022
1023int librados::AioCompletion::AioCompletion::get_return_value()
1024{
1025 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1026 return c->get_return_value();
1027}
1028
1029int librados::AioCompletion::AioCompletion::get_version()
1030{
1031 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1032 return c->get_version();
1033}
1034
1035uint64_t librados::AioCompletion::AioCompletion::get_version64()
1036{
1037 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1038 return c->get_version();
1039}
1040
1041void librados::AioCompletion::AioCompletion::release()
1042{
1043 AioCompletionImpl *c = (AioCompletionImpl *)pc;
1044 c->release();
1045 delete this;
1046}
1047
1048///////////////////////////// IoCtx //////////////////////////////
1049librados::IoCtx::IoCtx() : io_ctx_impl(NULL)
1050{
1051}
1052
1053void librados::IoCtx::from_rados_ioctx_t(rados_ioctx_t p, IoCtx &io)
1054{
1055 IoCtxImpl *io_ctx_impl = (IoCtxImpl*)p;
1056
1057 io.io_ctx_impl = io_ctx_impl;
1058 if (io_ctx_impl) {
1059 io_ctx_impl->get();
1060 }
1061}
1062
1063librados::IoCtx::IoCtx(const IoCtx& rhs)
1064{
1065 io_ctx_impl = rhs.io_ctx_impl;
1066 if (io_ctx_impl) {
1067 io_ctx_impl->get();
1068 }
1069}
1070
1071librados::IoCtx& librados::IoCtx::operator=(const IoCtx& rhs)
1072{
1073 if (io_ctx_impl)
1074 io_ctx_impl->put();
1075 io_ctx_impl = rhs.io_ctx_impl;
1076 io_ctx_impl->get();
1077 return *this;
1078}
1079
1080librados::IoCtx::~IoCtx()
1081{
1082 close();
1083}
1084
1085void librados::IoCtx::close()
1086{
1087 if (io_ctx_impl)
1088 io_ctx_impl->put();
1089 io_ctx_impl = 0;
1090}
1091
1092void librados::IoCtx::dup(const IoCtx& rhs)
1093{
1094 if (io_ctx_impl)
1095 io_ctx_impl->put();
1096 io_ctx_impl = new IoCtxImpl();
1097 io_ctx_impl->get();
1098 io_ctx_impl->dup(*rhs.io_ctx_impl);
1099}
1100
1101int librados::IoCtx::set_auid(uint64_t auid_)
1102{
1103 return io_ctx_impl->pool_change_auid(auid_);
1104}
1105
1106int librados::IoCtx::set_auid_async(uint64_t auid_, PoolAsyncCompletion *c)
1107{
1108 return io_ctx_impl->pool_change_auid_async(auid_, c->pc);
1109}
1110
1111int librados::IoCtx::get_auid(uint64_t *auid_)
1112{
1113 return rados_ioctx_pool_get_auid(io_ctx_impl, auid_);
1114}
1115
1116bool librados::IoCtx::pool_requires_alignment()
1117{
1118 return io_ctx_impl->client->pool_requires_alignment(get_id());
1119}
1120
1121int librados::IoCtx::pool_requires_alignment2(bool *requires)
1122{
1123 return io_ctx_impl->client->pool_requires_alignment2(get_id(), requires);
1124}
1125
1126uint64_t librados::IoCtx::pool_required_alignment()
1127{
1128 return io_ctx_impl->client->pool_required_alignment(get_id());
1129}
1130
1131int librados::IoCtx::pool_required_alignment2(uint64_t *alignment)
1132{
1133 return io_ctx_impl->client->pool_required_alignment2(get_id(), alignment);
1134}
1135
1136std::string librados::IoCtx::get_pool_name()
1137{
1138 std::string s;
1139 io_ctx_impl->client->pool_get_name(get_id(), &s);
1140 return s;
1141}
1142
1143std::string librados::IoCtx::get_pool_name() const
1144{
1145 return io_ctx_impl->get_cached_pool_name();
1146}
1147
1148uint64_t librados::IoCtx::get_instance_id() const
1149{
1150 return io_ctx_impl->client->get_instance_id();
1151}
1152
1153int librados::IoCtx::create(const std::string& oid, bool exclusive)
1154{
1155 object_t obj(oid);
1156 return io_ctx_impl->create(obj, exclusive);
1157}
1158
1159int librados::IoCtx::create(const std::string& oid, bool exclusive,
1160 const std::string& category) // unused
1161{
1162 object_t obj(oid);
1163 return io_ctx_impl->create(obj, exclusive);
1164}
1165
1166int librados::IoCtx::write(const std::string& oid, bufferlist& bl, size_t len, uint64_t off)
1167{
1168 object_t obj(oid);
1169 return io_ctx_impl->write(obj, bl, len, off);
1170}
1171
1172int librados::IoCtx::append(const std::string& oid, bufferlist& bl, size_t len)
1173{
1174 object_t obj(oid);
1175 return io_ctx_impl->append(obj, bl, len);
1176}
1177
1178int librados::IoCtx::write_full(const std::string& oid, bufferlist& bl)
1179{
1180 object_t obj(oid);
1181 return io_ctx_impl->write_full(obj, bl);
1182}
1183
1184int librados::IoCtx::writesame(const std::string& oid, bufferlist& bl,
1185 size_t write_len, uint64_t off)
1186{
1187 object_t obj(oid);
1188 return io_ctx_impl->writesame(obj, bl, write_len, off);
1189}
1190
1191
1192int librados::IoCtx::read(const std::string& oid, bufferlist& bl, size_t len, uint64_t off)
1193{
1194 object_t obj(oid);
1195 return io_ctx_impl->read(obj, bl, len, off);
1196}
1197
1198int librados::IoCtx::checksum(const std::string& oid,
1199 rados_checksum_type_t type,
1200 const bufferlist &init_value_bl, size_t len,
1201 uint64_t off, size_t chunk_size, bufferlist *pbl)
1202{
1203 object_t obj(oid);
1204 return io_ctx_impl->checksum(obj, get_checksum_op_type(type), init_value_bl,
1205 len, off, chunk_size, pbl);
1206}
1207
1208int librados::IoCtx::remove(const std::string& oid)
1209{
1210 object_t obj(oid);
1211 return io_ctx_impl->remove(obj);
1212}
1213
1214int librados::IoCtx::remove(const std::string& oid, int flags)
1215{
1216 object_t obj(oid);
1217 return io_ctx_impl->remove(obj, flags);
1218}
1219
1220int librados::IoCtx::trunc(const std::string& oid, uint64_t size)
1221{
1222 object_t obj(oid);
1223 return io_ctx_impl->trunc(obj, size);
1224}
1225
1226int librados::IoCtx::mapext(const std::string& oid, uint64_t off, size_t len,
1227 std::map<uint64_t,uint64_t>& m)
1228{
1229 object_t obj(oid);
1230 return io_ctx_impl->mapext(obj, off, len, m);
1231}
1232
1233int librados::IoCtx::cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl)
1234{
1235 object_t obj(oid);
1236 return io_ctx_impl->cmpext(obj, off, cmp_bl);
1237}
1238
1239int librados::IoCtx::sparse_read(const std::string& oid, std::map<uint64_t,uint64_t>& m,
1240 bufferlist& bl, size_t len, uint64_t off)
1241{
1242 object_t obj(oid);
1243 return io_ctx_impl->sparse_read(obj, m, bl, len, off);
1244}
1245
1246int librados::IoCtx::getxattr(const std::string& oid, const char *name, bufferlist& bl)
1247{
1248 object_t obj(oid);
1249 return io_ctx_impl->getxattr(obj, name, bl);
1250}
1251
1252int librados::IoCtx::getxattrs(const std::string& oid, map<std::string, bufferlist>& attrset)
1253{
1254 object_t obj(oid);
1255 return io_ctx_impl->getxattrs(obj, attrset);
1256}
1257
1258int librados::IoCtx::setxattr(const std::string& oid, const char *name, bufferlist& bl)
1259{
1260 object_t obj(oid);
1261 return io_ctx_impl->setxattr(obj, name, bl);
1262}
1263
1264int librados::IoCtx::rmxattr(const std::string& oid, const char *name)
1265{
1266 object_t obj(oid);
1267 return io_ctx_impl->rmxattr(obj, name);
1268}
1269
1270int librados::IoCtx::stat(const std::string& oid, uint64_t *psize, time_t *pmtime)
1271{
1272 object_t obj(oid);
1273 return io_ctx_impl->stat(obj, psize, pmtime);
1274}
1275
1276int librados::IoCtx::stat2(const std::string& oid, uint64_t *psize, struct timespec *pts)
1277{
1278 object_t obj(oid);
1279 return io_ctx_impl->stat2(obj, psize, pts);
1280}
1281
1282int librados::IoCtx::exec(const std::string& oid, const char *cls, const char *method,
1283 bufferlist& inbl, bufferlist& outbl)
1284{
1285 object_t obj(oid);
1286 return io_ctx_impl->exec(obj, cls, method, inbl, outbl);
1287}
1288
1289int librados::IoCtx::tmap_update(const std::string& oid, bufferlist& cmdbl)
1290{
1291 object_t obj(oid);
1292 return io_ctx_impl->tmap_update(obj, cmdbl);
1293}
1294
1295int librados::IoCtx::tmap_put(const std::string& oid, bufferlist& bl)
1296{
1297 object_t obj(oid);
1298 return io_ctx_impl->tmap_put(obj, bl);
1299}
1300
1301int librados::IoCtx::tmap_get(const std::string& oid, bufferlist& bl)
1302{
1303 object_t obj(oid);
1304 return io_ctx_impl->tmap_get(obj, bl);
1305}
1306
1307int librados::IoCtx::tmap_to_omap(const std::string& oid, bool nullok)
1308{
1309 object_t obj(oid);
1310 return io_ctx_impl->tmap_to_omap(obj, nullok);
1311}
1312
1313int librados::IoCtx::omap_get_vals(const std::string& oid,
1314 const std::string& start_after,
1315 uint64_t max_return,
1316 std::map<std::string, bufferlist> *out_vals)
1317{
1318 return omap_get_vals(oid, start_after, string(), max_return, out_vals);
1319}
1320
1321int librados::IoCtx::omap_get_vals2(
1322 const std::string& oid,
1323 const std::string& start_after,
1324 uint64_t max_return,
1325 std::map<std::string, bufferlist> *out_vals,
1326 bool *pmore)
1327{
1328 ObjectReadOperation op;
1329 int r;
1330 op.omap_get_vals2(start_after, max_return, out_vals, pmore, &r);
1331 bufferlist bl;
1332 int ret = operate(oid, &op, &bl);
1333 if (ret < 0)
1334 return ret;
1335 return r;
1336}
1337
1338int librados::IoCtx::omap_get_keys(const std::string& oid,
1339 const std::string& orig_start_after,
1340 uint64_t max_return,
1341 std::set<std::string> *out_keys)
1342{
1343 bool first = true;
1344 string start_after = orig_start_after;
1345 bool more = true;
1346 while (max_return > 0 && more) {
1347 std::set<std::string> out;
1348 ObjectReadOperation op;
1349 op.omap_get_keys2(start_after, max_return, &out, &more, nullptr);
1350 bufferlist bl;
1351 int ret = operate(oid, &op, &bl);
1352 if (ret < 0) {
1353 return ret;
1354 }
1355 if (more) {
1356 if (out.empty()) {
1357 return -EINVAL; // wth
1358 }
1359 start_after = *out.rbegin();
1360 }
1361 if (out.size() <= max_return) {
1362 max_return -= out.size();
1363 } else {
1364 max_return = 0;
1365 }
1366 if (first) {
1367 out_keys->swap(out);
1368 first = false;
1369 } else {
1370 out_keys->insert(out.begin(), out.end());
1371 out.clear();
1372 }
1373 }
1374 return 0;
1375}
1376
1377int librados::IoCtx::omap_get_keys2(
1378 const std::string& oid,
1379 const std::string& start_after,
1380 uint64_t max_return,
1381 std::set<std::string> *out_keys,
1382 bool *pmore)
1383{
1384 ObjectReadOperation op;
1385 int r;
1386 op.omap_get_keys2(start_after, max_return, out_keys, pmore, &r);
1387 bufferlist bl;
1388 int ret = operate(oid, &op, &bl);
1389 if (ret < 0)
1390 return ret;
1391 return r;
1392}
1393
1394int librados::IoCtx::omap_get_header(const std::string& oid,
1395 bufferlist *bl)
1396{
1397 ObjectReadOperation op;
1398 int r;
1399 op.omap_get_header(bl, &r);
1400 bufferlist b;
1401 int ret = operate(oid, &op, &b);
1402 if (ret < 0)
1403 return ret;
1404
1405 return r;
1406}
1407
1408int librados::IoCtx::omap_get_vals_by_keys(const std::string& oid,
1409 const std::set<std::string>& keys,
1410 std::map<std::string, bufferlist> *vals)
1411{
1412 ObjectReadOperation op;
1413 int r;
1414 bufferlist bl;
1415 op.omap_get_vals_by_keys(keys, vals, &r);
1416 int ret = operate(oid, &op, &bl);
1417 if (ret < 0)
1418 return ret;
1419
1420 return r;
1421}
1422
1423int librados::IoCtx::omap_set(const std::string& oid,
1424 const map<string, bufferlist>& m)
1425{
1426 ObjectWriteOperation op;
1427 op.omap_set(m);
1428 return operate(oid, &op);
1429}
1430
1431int librados::IoCtx::omap_set_header(const std::string& oid,
1432 const bufferlist& bl)
1433{
1434 ObjectWriteOperation op;
1435 op.omap_set_header(bl);
1436 return operate(oid, &op);
1437}
1438
1439int librados::IoCtx::omap_clear(const std::string& oid)
1440{
1441 ObjectWriteOperation op;
1442 op.omap_clear();
1443 return operate(oid, &op);
1444}
1445
1446int librados::IoCtx::omap_rm_keys(const std::string& oid,
1447 const std::set<std::string>& keys)
1448{
1449 ObjectWriteOperation op;
1450 op.omap_rm_keys(keys);
1451 return operate(oid, &op);
1452}
1453
1454
1455
1456static int translate_flags(int flags)
1457{
1458 int op_flags = 0;
1459 if (flags & librados::OPERATION_BALANCE_READS)
1460 op_flags |= CEPH_OSD_FLAG_BALANCE_READS;
1461 if (flags & librados::OPERATION_LOCALIZE_READS)
1462 op_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
1463 if (flags & librados::OPERATION_ORDER_READS_WRITES)
1464 op_flags |= CEPH_OSD_FLAG_RWORDERED;
1465 if (flags & librados::OPERATION_IGNORE_CACHE)
1466 op_flags |= CEPH_OSD_FLAG_IGNORE_CACHE;
1467 if (flags & librados::OPERATION_SKIPRWLOCKS)
1468 op_flags |= CEPH_OSD_FLAG_SKIPRWLOCKS;
1469 if (flags & librados::OPERATION_IGNORE_OVERLAY)
1470 op_flags |= CEPH_OSD_FLAG_IGNORE_OVERLAY;
1471 if (flags & librados::OPERATION_FULL_TRY)
1472 op_flags |= CEPH_OSD_FLAG_FULL_TRY;
1473 if (flags & librados::OPERATION_FULL_FORCE)
1474 op_flags |= CEPH_OSD_FLAG_FULL_FORCE;
1475
1476 return op_flags;
1477}
1478
1479int librados::IoCtx::operate(const std::string& oid, librados::ObjectWriteOperation *o)
1480{
1481 object_t obj(oid);
1482 return io_ctx_impl->operate(obj, &o->impl->o, (ceph::real_time *)o->impl->prt);
1483}
1484
1485int librados::IoCtx::operate(const std::string& oid, librados::ObjectReadOperation *o, bufferlist *pbl)
1486{
1487 object_t obj(oid);
1488 return io_ctx_impl->operate_read(obj, &o->impl->o, pbl);
1489}
1490
1491int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1492 librados::ObjectWriteOperation *o)
1493{
1494 object_t obj(oid);
1495 return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
1496 io_ctx_impl->snapc, 0);
1497}
1498int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1499 ObjectWriteOperation *o, int flags)
1500{
1501 object_t obj(oid);
1502 return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
1503 io_ctx_impl->snapc,
1504 translate_flags(flags));
1505}
1506
1507int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1508 librados::ObjectWriteOperation *o,
1509 snap_t snap_seq, std::vector<snap_t>& snaps)
1510{
1511 object_t obj(oid);
1512 vector<snapid_t> snv;
1513 snv.resize(snaps.size());
1514 for (size_t i = 0; i < snaps.size(); ++i)
1515 snv[i] = snaps[i];
1516 SnapContext snapc(snap_seq, snv);
1517 return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
1518 snapc, 0);
1519}
1520
1521int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1522 librados::ObjectWriteOperation *o,
1523 snap_t snap_seq, std::vector<snap_t>& snaps,
1524 const blkin_trace_info *trace_info)
1525{
1526 object_t obj(oid);
1527 vector<snapid_t> snv;
1528 snv.resize(snaps.size());
1529 for (size_t i = 0; i < snaps.size(); ++i)
1530 snv[i] = snaps[i];
1531 SnapContext snapc(snap_seq, snv);
1532 return io_ctx_impl->aio_operate(obj, &o->impl->o, c->pc,
1533 snapc, 0, trace_info);
1534}
1535
1536int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1537 librados::ObjectReadOperation *o,
1538 bufferlist *pbl)
1539{
1540 object_t obj(oid);
1541 return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
1542 0, pbl);
1543}
1544
1545// deprecated
1546int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1547 librados::ObjectReadOperation *o,
1548 snap_t snapid_unused_deprecated,
1549 int flags, bufferlist *pbl)
1550{
1551 object_t obj(oid);
1552 int op_flags = 0;
1553 if (flags & OPERATION_BALANCE_READS)
1554 op_flags |= CEPH_OSD_FLAG_BALANCE_READS;
1555 if (flags & OPERATION_LOCALIZE_READS)
1556 op_flags |= CEPH_OSD_FLAG_LOCALIZE_READS;
1557 if (flags & OPERATION_ORDER_READS_WRITES)
1558 op_flags |= CEPH_OSD_FLAG_RWORDERED;
1559
1560 return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
1561 op_flags, pbl);
1562}
1563
1564int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1565 librados::ObjectReadOperation *o,
1566 int flags, bufferlist *pbl)
1567{
1568 object_t obj(oid);
1569 return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
1570 translate_flags(flags), pbl);
1571}
1572
1573int librados::IoCtx::aio_operate(const std::string& oid, AioCompletion *c,
1574 librados::ObjectReadOperation *o,
1575 int flags, bufferlist *pbl, const blkin_trace_info *trace_info)
1576{
1577 object_t obj(oid);
1578 return io_ctx_impl->aio_operate_read(obj, &o->impl->o, c->pc,
1579 translate_flags(flags), pbl, trace_info);
1580}
1581
1582void librados::IoCtx::snap_set_read(snap_t seq)
1583{
1584 io_ctx_impl->set_snap_read(seq);
1585}
1586
1587int librados::IoCtx::selfmanaged_snap_set_write_ctx(snap_t seq, vector<snap_t>& snaps)
1588{
1589 vector<snapid_t> snv;
1590 snv.resize(snaps.size());
1591 for (unsigned i=0; i<snaps.size(); i++)
1592 snv[i] = snaps[i];
1593 return io_ctx_impl->set_snap_write_context(seq, snv);
1594}
1595
1596int librados::IoCtx::snap_create(const char *snapname)
1597{
1598 return io_ctx_impl->snap_create(snapname);
1599}
1600
1601int librados::IoCtx::snap_lookup(const char *name, snap_t *snapid)
1602{
1603 return io_ctx_impl->snap_lookup(name, snapid);
1604}
1605
1606int librados::IoCtx::snap_get_stamp(snap_t snapid, time_t *t)
1607{
1608 return io_ctx_impl->snap_get_stamp(snapid, t);
1609}
1610
1611int librados::IoCtx::snap_get_name(snap_t snapid, std::string *s)
1612{
1613 return io_ctx_impl->snap_get_name(snapid, s);
1614}
1615
1616int librados::IoCtx::snap_remove(const char *snapname)
1617{
1618 return io_ctx_impl->snap_remove(snapname);
1619}
1620
1621int librados::IoCtx::snap_list(std::vector<snap_t> *snaps)
1622{
1623 return io_ctx_impl->snap_list(snaps);
1624}
1625
1626int librados::IoCtx::snap_rollback(const std::string& oid, const char *snapname)
1627{
1628 return io_ctx_impl->rollback(oid, snapname);
1629}
1630
1631// Deprecated name kept for backward compatibility
1632int librados::IoCtx::rollback(const std::string& oid, const char *snapname)
1633{
1634 return snap_rollback(oid, snapname);
1635}
1636
1637int librados::IoCtx::selfmanaged_snap_create(uint64_t *snapid)
1638{
1639 return io_ctx_impl->selfmanaged_snap_create(snapid);
1640}
1641
1642void librados::IoCtx::aio_selfmanaged_snap_create(uint64_t *snapid,
1643 AioCompletion *c)
1644{
1645 io_ctx_impl->aio_selfmanaged_snap_create(snapid, c->pc);
1646}
1647
1648int librados::IoCtx::selfmanaged_snap_remove(uint64_t snapid)
1649{
1650 return io_ctx_impl->selfmanaged_snap_remove(snapid);
1651}
1652
1653void librados::IoCtx::aio_selfmanaged_snap_remove(uint64_t snapid,
1654 AioCompletion *c)
1655{
1656 io_ctx_impl->aio_selfmanaged_snap_remove(snapid, c->pc);
1657}
1658
1659int librados::IoCtx::selfmanaged_snap_rollback(const std::string& oid, uint64_t snapid)
1660{
1661 return io_ctx_impl->selfmanaged_snap_rollback_object(oid,
1662 io_ctx_impl->snapc,
1663 snapid);
1664}
1665
1666int librados::IoCtx::lock_exclusive(const std::string &oid, const std::string &name,
1667 const std::string &cookie,
1668 const std::string &description,
1669 struct timeval * duration, uint8_t flags)
1670{
1671 utime_t dur = utime_t();
1672 if (duration)
1673 dur.set_from_timeval(duration);
1674
1675 return rados::cls::lock::lock(this, oid, name, LOCK_EXCLUSIVE, cookie, "",
1676 description, dur, flags);
1677}
1678
1679int librados::IoCtx::lock_shared(const std::string &oid, const std::string &name,
1680 const std::string &cookie, const std::string &tag,
1681 const std::string &description,
1682 struct timeval * duration, uint8_t flags)
1683{
1684 utime_t dur = utime_t();
1685 if (duration)
1686 dur.set_from_timeval(duration);
1687
1688 return rados::cls::lock::lock(this, oid, name, LOCK_SHARED, cookie, tag,
1689 description, dur, flags);
1690}
1691
1692int librados::IoCtx::unlock(const std::string &oid, const std::string &name,
1693 const std::string &cookie)
1694{
1695 return rados::cls::lock::unlock(this, oid, name, cookie);
1696}
1697
1698struct AioUnlockCompletion : public librados::ObjectOperationCompletion {
1699 librados::AioCompletionImpl *completion;
1700 AioUnlockCompletion(librados::AioCompletion *c) : completion(c->pc) {
1701 completion->get();
1702 };
1703 void handle_completion(int r, bufferlist& outbl) override {
1704 rados_callback_t cb = completion->callback_complete;
1705 void *cb_arg = completion->callback_complete_arg;
1706 cb(completion, cb_arg);
1707 completion->lock.Lock();
1708 completion->callback_complete = NULL;
1709 completion->cond.Signal();
1710 completion->put_unlock();
1711 }
1712};
1713
1714int librados::IoCtx::aio_unlock(const std::string &oid, const std::string &name,
1715 const std::string &cookie, AioCompletion *c)
1716{
1717 return rados::cls::lock::aio_unlock(this, oid, name, cookie, c);
1718}
1719
1720int librados::IoCtx::break_lock(const std::string &oid, const std::string &name,
1721 const std::string &client, const std::string &cookie)
1722{
1723 entity_name_t locker;
1724 if (!locker.parse(client))
1725 return -EINVAL;
1726 return rados::cls::lock::break_lock(this, oid, name, cookie, locker);
1727}
1728
1729int librados::IoCtx::list_lockers(const std::string &oid, const std::string &name,
1730 int *exclusive,
1731 std::string *tag,
1732 std::list<librados::locker_t> *lockers)
1733{
1734 std::list<librados::locker_t> tmp_lockers;
1735 map<rados::cls::lock::locker_id_t, rados::cls::lock::locker_info_t> rados_lockers;
1736 std::string tmp_tag;
1737 ClsLockType tmp_type;
1738 int r = rados::cls::lock::get_lock_info(this, oid, name, &rados_lockers, &tmp_type, &tmp_tag);
1739 if (r < 0)
1740 return r;
1741
1742 map<rados::cls::lock::locker_id_t, rados::cls::lock::locker_info_t>::iterator map_it;
1743 for (map_it = rados_lockers.begin(); map_it != rados_lockers.end(); ++map_it) {
1744 librados::locker_t locker;
1745 locker.client = stringify(map_it->first.locker);
1746 locker.cookie = map_it->first.cookie;
1747 locker.address = stringify(map_it->second.addr);
1748 tmp_lockers.push_back(locker);
1749 }
1750
1751 if (lockers)
1752 *lockers = tmp_lockers;
1753 if (tag)
1754 *tag = tmp_tag;
1755 if (exclusive) {
1756 if (tmp_type == LOCK_EXCLUSIVE)
1757 *exclusive = 1;
1758 else
1759 *exclusive = 0;
1760 }
1761
1762 return tmp_lockers.size();
1763}
1764
1765librados::NObjectIterator librados::IoCtx::nobjects_begin()
1766{
1767 bufferlist bl;
1768 return nobjects_begin(bl);
1769}
1770
1771librados::NObjectIterator librados::IoCtx::nobjects_begin(
1772 const bufferlist &filter)
1773{
1774 rados_list_ctx_t listh;
1775 rados_nobjects_list_open(io_ctx_impl, &listh);
1776 NObjectIterator iter((ObjListCtx*)listh);
1777 if (filter.length() > 0) {
1778 iter.set_filter(filter);
1779 }
1780 iter.get_next();
1781 return iter;
1782}
1783
1784librados::NObjectIterator librados::IoCtx::nobjects_begin(uint32_t pos)
1785{
1786 bufferlist bl;
1787 return nobjects_begin(pos, bl);
1788}
1789
1790librados::NObjectIterator librados::IoCtx::nobjects_begin(
1791 uint32_t pos, const bufferlist &filter)
1792{
1793 rados_list_ctx_t listh;
1794 rados_nobjects_list_open(io_ctx_impl, &listh);
1795 NObjectIterator iter((ObjListCtx*)listh);
1796 if (filter.length() > 0) {
1797 iter.set_filter(filter);
1798 }
1799 iter.seek(pos);
1800 return iter;
1801}
1802
1803librados::NObjectIterator librados::IoCtx::nobjects_begin(const ObjectCursor& cursor)
1804{
1805 bufferlist bl;
1806 return nobjects_begin(cursor, bl);
1807}
1808
1809librados::NObjectIterator librados::IoCtx::nobjects_begin(
1810 const ObjectCursor& cursor, const bufferlist &filter)
1811{
1812 rados_list_ctx_t listh;
1813 rados_nobjects_list_open(io_ctx_impl, &listh);
1814 NObjectIterator iter((ObjListCtx*)listh);
1815 if (filter.length() > 0) {
1816 iter.set_filter(filter);
1817 }
1818 iter.seek(cursor);
1819 return iter;
1820}
1821
1822const librados::NObjectIterator& librados::IoCtx::nobjects_end() const
1823{
1824 return NObjectIterator::__EndObjectIterator;
1825}
1826
1827int librados::IoCtx::hit_set_list(uint32_t hash, AioCompletion *c,
1828 std::list< std::pair<time_t, time_t> > *pls)
1829{
1830 return io_ctx_impl->hit_set_list(hash, c->pc, pls);
1831}
1832
1833int librados::IoCtx::hit_set_get(uint32_t hash, AioCompletion *c, time_t stamp,
1834 bufferlist *pbl)
1835{
1836 return io_ctx_impl->hit_set_get(hash, c->pc, stamp, pbl);
1837}
1838
1839
1840
1841uint64_t librados::IoCtx::get_last_version()
1842{
1843 return io_ctx_impl->last_version();
1844}
1845
1846int librados::IoCtx::aio_read(const std::string& oid, librados::AioCompletion *c,
1847 bufferlist *pbl, size_t len, uint64_t off)
1848{
1849 return io_ctx_impl->aio_read(oid, c->pc, pbl, len, off,
1850 io_ctx_impl->snap_seq);
1851}
1852
1853int librados::IoCtx::aio_read(const std::string& oid, librados::AioCompletion *c,
1854 bufferlist *pbl, size_t len, uint64_t off,
1855 uint64_t snapid)
1856{
1857 return io_ctx_impl->aio_read(oid, c->pc, pbl, len, off, snapid);
1858}
1859
1860int librados::IoCtx::aio_exec(const std::string& oid,
1861 librados::AioCompletion *c, const char *cls,
1862 const char *method, bufferlist& inbl,
1863 bufferlist *outbl)
1864{
1865 object_t obj(oid);
1866 return io_ctx_impl->aio_exec(obj, c->pc, cls, method, inbl, outbl);
1867}
1868
1869int librados::IoCtx::aio_cmpext(const std::string& oid,
1870 librados::AioCompletion *c,
1871 uint64_t off,
1872 bufferlist& cmp_bl)
1873{
1874 return io_ctx_impl->aio_cmpext(oid, c->pc, off, cmp_bl);
1875}
1876
1877int librados::IoCtx::aio_sparse_read(const std::string& oid, librados::AioCompletion *c,
1878 std::map<uint64_t,uint64_t> *m, bufferlist *data_bl,
1879 size_t len, uint64_t off)
1880{
1881 return io_ctx_impl->aio_sparse_read(oid, c->pc,
1882 m, data_bl, len, off,
1883 io_ctx_impl->snap_seq);
1884}
1885
1886int librados::IoCtx::aio_sparse_read(const std::string& oid, librados::AioCompletion *c,
1887 std::map<uint64_t,uint64_t> *m, bufferlist *data_bl,
1888 size_t len, uint64_t off, uint64_t snapid)
1889{
1890 return io_ctx_impl->aio_sparse_read(oid, c->pc,
1891 m, data_bl, len, off, snapid);
1892}
1893
1894int librados::IoCtx::aio_write(const std::string& oid, librados::AioCompletion *c,
1895 const bufferlist& bl, size_t len, uint64_t off)
1896{
1897 return io_ctx_impl->aio_write(oid, c->pc, bl, len, off);
1898}
1899
1900int librados::IoCtx::aio_append(const std::string& oid, librados::AioCompletion *c,
1901 const bufferlist& bl, size_t len)
1902{
1903 return io_ctx_impl->aio_append(oid, c->pc, bl, len);
1904}
1905
1906int librados::IoCtx::aio_write_full(const std::string& oid, librados::AioCompletion *c,
1907 const bufferlist& bl)
1908{
1909 object_t obj(oid);
1910 return io_ctx_impl->aio_write_full(obj, c->pc, bl);
1911}
1912
1913int librados::IoCtx::aio_writesame(const std::string& oid, librados::AioCompletion *c,
1914 const bufferlist& bl, size_t write_len,
1915 uint64_t off)
1916{
1917 return io_ctx_impl->aio_writesame(oid, c->pc, bl, write_len, off);
1918}
1919
1920
1921int librados::IoCtx::aio_remove(const std::string& oid, librados::AioCompletion *c)
1922{
1923 return io_ctx_impl->aio_remove(oid, c->pc);
1924}
1925
1926int librados::IoCtx::aio_remove(const std::string& oid, librados::AioCompletion *c, int flags)
1927{
1928 return io_ctx_impl->aio_remove(oid, c->pc, flags);
1929}
1930
1931int librados::IoCtx::aio_flush_async(librados::AioCompletion *c)
1932{
1933 io_ctx_impl->flush_aio_writes_async(c->pc);
1934 return 0;
1935}
1936
1937int librados::IoCtx::aio_flush()
1938{
1939 io_ctx_impl->flush_aio_writes();
1940 return 0;
1941}
1942
1943struct AioGetxattrDataPP {
1944 AioGetxattrDataPP(librados::AioCompletionImpl *c, bufferlist *_bl) :
1945 bl(_bl), completion(c) {}
1946 bufferlist *bl;
1947 struct librados::C_AioCompleteAndSafe completion;
1948};
1949
1950static void rados_aio_getxattr_completepp(rados_completion_t c, void *arg) {
1951 AioGetxattrDataPP *cdata = reinterpret_cast<AioGetxattrDataPP*>(arg);
1952 int rc = rados_aio_get_return_value(c);
1953 if (rc >= 0) {
1954 rc = cdata->bl->length();
1955 }
1956 cdata->completion.finish(rc);
1957 delete cdata;
1958}
1959
1960int librados::IoCtx::aio_getxattr(const std::string& oid, librados::AioCompletion *c,
1961 const char *name, bufferlist& bl)
1962{
1963 // create data object to be passed to async callback
1964 AioGetxattrDataPP *cdata = new AioGetxattrDataPP(c->pc, &bl);
1965 if (!cdata) {
1966 return -ENOMEM;
1967 }
1968 // create completion callback
1969 librados::AioCompletionImpl *comp = new librados::AioCompletionImpl;
1970 comp->set_complete_callback(cdata, rados_aio_getxattr_completepp);
1971 // call actual getxattr from IoCtxImpl
1972 object_t obj(oid);
1973 return io_ctx_impl->aio_getxattr(obj, comp, name, bl);
1974}
1975
1976int librados::IoCtx::aio_getxattrs(const std::string& oid, AioCompletion *c,
1977 map<std::string, bufferlist>& attrset)
1978{
1979 object_t obj(oid);
1980 return io_ctx_impl->aio_getxattrs(obj, c->pc, attrset);
1981}
1982
1983int librados::IoCtx::aio_setxattr(const std::string& oid, AioCompletion *c,
1984 const char *name, bufferlist& bl)
1985{
1986 object_t obj(oid);
1987 return io_ctx_impl->aio_setxattr(obj, c->pc, name, bl);
1988}
1989
1990int librados::IoCtx::aio_rmxattr(const std::string& oid, AioCompletion *c,
1991 const char *name)
1992{
1993 object_t obj(oid);
1994 return io_ctx_impl->aio_rmxattr(obj, c->pc, name);
1995}
1996
1997int librados::IoCtx::aio_stat(const std::string& oid, librados::AioCompletion *c,
1998 uint64_t *psize, time_t *pmtime)
1999{
2000 object_t obj(oid);
2001 return io_ctx_impl->aio_stat(obj, c->pc, psize, pmtime);
2002}
2003
2004int librados::IoCtx::aio_cancel(librados::AioCompletion *c)
2005{
2006 return io_ctx_impl->aio_cancel(c->pc);
2007}
2008
2009int librados::IoCtx::watch(const string& oid, uint64_t ver, uint64_t *cookie,
2010 librados::WatchCtx *ctx)
2011{
2012 object_t obj(oid);
2013 return io_ctx_impl->watch(obj, cookie, ctx, NULL);
2014}
2015
2016int librados::IoCtx::watch2(const string& oid, uint64_t *cookie,
2017 librados::WatchCtx2 *ctx2)
2018{
2019 object_t obj(oid);
2020 return io_ctx_impl->watch(obj, cookie, NULL, ctx2);
2021}
2022
2023int librados::IoCtx::watch3(const string& oid, uint64_t *cookie,
2024 librados::WatchCtx2 *ctx2, uint32_t timeout)
2025{
2026 object_t obj(oid);
2027 return io_ctx_impl->watch(obj, cookie, NULL, ctx2, timeout);
2028}
2029
2030int librados::IoCtx::aio_watch(const string& oid, AioCompletion *c,
2031 uint64_t *cookie,
2032 librados::WatchCtx2 *ctx2)
2033{
2034 object_t obj(oid);
2035 return io_ctx_impl->aio_watch(obj, c->pc, cookie, NULL, ctx2);
2036}
2037
2038int librados::IoCtx::aio_watch2(const string& oid, AioCompletion *c,
2039 uint64_t *cookie,
2040 librados::WatchCtx2 *ctx2,
2041 uint32_t timeout)
2042{
2043 object_t obj(oid);
2044 return io_ctx_impl->aio_watch(obj, c->pc, cookie, NULL, ctx2, timeout);
2045}
2046
2047int librados::IoCtx::unwatch(const string& oid, uint64_t handle)
2048{
2049 return io_ctx_impl->unwatch(handle);
2050}
2051
2052int librados::IoCtx::unwatch2(uint64_t handle)
2053{
2054 return io_ctx_impl->unwatch(handle);
2055}
2056
2057int librados::IoCtx::aio_unwatch(uint64_t handle, AioCompletion *c)
2058{
2059 return io_ctx_impl->aio_unwatch(handle, c->pc);
2060}
2061
2062int librados::IoCtx::watch_check(uint64_t handle)
2063{
2064 return io_ctx_impl->watch_check(handle);
2065}
2066
2067int librados::IoCtx::notify(const string& oid, uint64_t ver, bufferlist& bl)
2068{
2069 object_t obj(oid);
2070 return io_ctx_impl->notify(obj, bl, 0, NULL, NULL, NULL);
2071}
2072
2073int librados::IoCtx::notify2(const string& oid, bufferlist& bl,
2074 uint64_t timeout_ms, bufferlist *preplybl)
2075{
2076 object_t obj(oid);
2077 return io_ctx_impl->notify(obj, bl, timeout_ms, preplybl, NULL, NULL);
2078}
2079
2080int librados::IoCtx::aio_notify(const string& oid, AioCompletion *c,
2081 bufferlist& bl, uint64_t timeout_ms,
2082 bufferlist *preplybl)
2083{
2084 object_t obj(oid);
2085 return io_ctx_impl->aio_notify(obj, c->pc, bl, timeout_ms, preplybl, NULL,
2086 NULL);
2087}
2088
2089void librados::IoCtx::notify_ack(const std::string& o,
2090 uint64_t notify_id, uint64_t handle,
2091 bufferlist& bl)
2092{
2093 io_ctx_impl->notify_ack(o, notify_id, handle, bl);
2094}
2095
2096int librados::IoCtx::list_watchers(const std::string& oid,
2097 std::list<obj_watch_t> *out_watchers)
2098{
2099 ObjectReadOperation op;
2100 int r;
2101 op.list_watchers(out_watchers, &r);
2102 bufferlist bl;
2103 int ret = operate(oid, &op, &bl);
2104 if (ret < 0)
2105 return ret;
2106
2107 return r;
2108}
2109
2110int librados::IoCtx::list_snaps(const std::string& oid,
2111 snap_set_t *out_snaps)
2112{
2113 ObjectReadOperation op;
2114 int r;
2115 if (io_ctx_impl->snap_seq != CEPH_SNAPDIR)
2116 return -EINVAL;
2117 op.list_snaps(out_snaps, &r);
2118 bufferlist bl;
2119 int ret = operate(oid, &op, &bl);
2120 if (ret < 0)
2121 return ret;
2122
2123 return r;
2124}
2125
2126void librados::IoCtx::set_notify_timeout(uint32_t timeout)
2127{
2128 io_ctx_impl->set_notify_timeout(timeout);
2129}
2130
2131int librados::IoCtx::set_alloc_hint(const std::string& o,
2132 uint64_t expected_object_size,
2133 uint64_t expected_write_size)
2134{
2135 object_t oid(o);
2136 return io_ctx_impl->set_alloc_hint(oid, expected_object_size,
2137 expected_write_size, 0);
2138}
2139
2140int librados::IoCtx::set_alloc_hint2(const std::string& o,
2141 uint64_t expected_object_size,
2142 uint64_t expected_write_size,
2143 uint32_t flags)
2144{
2145 object_t oid(o);
2146 return io_ctx_impl->set_alloc_hint(oid, expected_object_size,
2147 expected_write_size, flags);
2148}
2149
2150void librados::IoCtx::set_assert_version(uint64_t ver)
2151{
2152 io_ctx_impl->set_assert_version(ver);
2153}
2154
2155void librados::IoCtx::locator_set_key(const string& key)
2156{
2157 io_ctx_impl->oloc.key = key;
2158}
2159
2160void librados::IoCtx::set_namespace(const string& nspace)
2161{
2162 io_ctx_impl->oloc.nspace = nspace;
2163}
2164
2165int64_t librados::IoCtx::get_id()
2166{
2167 return io_ctx_impl->get_id();
2168}
2169
2170uint32_t librados::IoCtx::get_object_hash_position(const std::string& oid)
2171{
2172 uint32_t hash;
2173 int r = io_ctx_impl->get_object_hash_position(oid, &hash);
2174 if (r < 0)
2175 hash = 0;
2176 return hash;
2177}
2178
2179uint32_t librados::IoCtx::get_object_pg_hash_position(const std::string& oid)
2180{
2181 uint32_t hash;
2182 int r = io_ctx_impl->get_object_pg_hash_position(oid, &hash);
2183 if (r < 0)
2184 hash = 0;
2185 return hash;
2186}
2187
2188int librados::IoCtx::get_object_hash_position2(
2189 const std::string& oid, uint32_t *hash_position)
2190{
2191 return io_ctx_impl->get_object_hash_position(oid, hash_position);
2192}
2193
2194int librados::IoCtx::get_object_pg_hash_position2(
2195 const std::string& oid, uint32_t *pg_hash_position)
2196{
2197 return io_ctx_impl->get_object_pg_hash_position(oid, pg_hash_position);
2198}
2199
2200librados::config_t librados::IoCtx::cct()
2201{
2202 return (config_t)io_ctx_impl->client->cct;
2203}
2204
2205librados::IoCtx::IoCtx(IoCtxImpl *io_ctx_impl_)
2206 : io_ctx_impl(io_ctx_impl_)
2207{
2208}
2209
2210void librados::IoCtx::set_osdmap_full_try()
2211{
2212 io_ctx_impl->objecter->set_osdmap_full_try();
2213}
2214
2215void librados::IoCtx::unset_osdmap_full_try()
2216{
2217 io_ctx_impl->objecter->unset_osdmap_full_try();
2218}
2219
2220///////////////////////////// Rados //////////////////////////////
2221void librados::Rados::version(int *major, int *minor, int *extra)
2222{
2223 rados_version(major, minor, extra);
2224}
2225
2226librados::Rados::Rados() : client(NULL)
2227{
2228}
2229
2230librados::Rados::Rados(IoCtx &ioctx)
2231{
2232 client = ioctx.io_ctx_impl->client;
2233 assert(client != NULL);
2234 client->get();
2235}
2236
2237librados::Rados::~Rados()
2238{
2239 shutdown();
2240}
2241
2242int librados::Rados::init(const char * const id)
2243{
2244 return rados_create((rados_t *)&client, id);
2245}
2246
2247int librados::Rados::init2(const char * const name,
2248 const char * const clustername, uint64_t flags)
2249{
2250 return rados_create2((rados_t *)&client, clustername, name, flags);
2251}
2252
2253int librados::Rados::init_with_context(config_t cct_)
2254{
2255 return rados_create_with_context((rados_t *)&client, (rados_config_t)cct_);
2256}
2257
2258int librados::Rados::connect()
2259{
2260 return client->connect();
2261}
2262
2263librados::config_t librados::Rados::cct()
2264{
2265 return (config_t)client->cct;
2266}
2267
2268int librados::Rados::watch_flush()
2269{
2270 if (!client)
2271 return -EINVAL;
2272 return client->watch_flush();
2273}
2274
2275int librados::Rados::aio_watch_flush(AioCompletion *c)
2276{
2277 if (!client)
2278 return -EINVAL;
2279 return client->async_watch_flush(c->pc);
2280}
2281
2282void librados::Rados::shutdown()
2283{
2284 if (!client)
2285 return;
2286 if (client->put()) {
2287 client->shutdown();
2288 delete client;
2289 client = NULL;
2290 }
2291}
2292
2293uint64_t librados::Rados::get_instance_id()
2294{
2295 return client->get_instance_id();
2296}
2297
2298int librados::Rados::conf_read_file(const char * const path) const
2299{
2300 return rados_conf_read_file((rados_t)client, path);
2301}
2302
2303int librados::Rados::conf_parse_argv(int argc, const char ** argv) const
2304{
2305 return rados_conf_parse_argv((rados_t)client, argc, argv);
2306}
2307
2308int librados::Rados::conf_parse_argv_remainder(int argc, const char ** argv,
2309 const char ** remargv) const
2310{
2311 return rados_conf_parse_argv_remainder((rados_t)client, argc, argv, remargv);
2312}
2313
2314int librados::Rados::conf_parse_env(const char *name) const
2315{
2316 return rados_conf_parse_env((rados_t)client, name);
2317}
2318
2319int librados::Rados::conf_set(const char *option, const char *value)
2320{
2321 return rados_conf_set((rados_t)client, option, value);
2322}
2323
2324int librados::Rados::conf_get(const char *option, std::string &val)
2325{
2326 char *str = NULL;
2327 md_config_t *conf = client->cct->_conf;
2328 int ret = conf->get_val(option, &str, -1);
2329 if (ret) {
2330 free(str);
2331 return ret;
2332 }
2333 val = str;
2334 free(str);
2335 return 0;
2336}
2337
2338int librados::Rados::pool_create(const char *name)
2339{
2340 string str(name);
2341 return client->pool_create(str);
2342}
2343
2344int librados::Rados::pool_create(const char *name, uint64_t auid)
2345{
2346 string str(name);
2347 return client->pool_create(str, auid);
2348}
2349
2350int librados::Rados::pool_create(const char *name, uint64_t auid, __u8 crush_rule)
2351{
2352 string str(name);
2353 return client->pool_create(str, auid, crush_rule);
2354}
2355
2356int librados::Rados::pool_create_async(const char *name, PoolAsyncCompletion *c)
2357{
2358 string str(name);
2359 return client->pool_create_async(str, c->pc);
2360}
2361
2362int librados::Rados::pool_create_async(const char *name, uint64_t auid, PoolAsyncCompletion *c)
2363{
2364 string str(name);
2365 return client->pool_create_async(str, c->pc, auid);
2366}
2367
2368int librados::Rados::pool_create_async(const char *name, uint64_t auid, __u8 crush_rule,
2369 PoolAsyncCompletion *c)
2370{
2371 string str(name);
2372 return client->pool_create_async(str, c->pc, auid, crush_rule);
2373}
2374
2375int librados::Rados::pool_get_base_tier(int64_t pool_id, int64_t* base_tier)
2376{
2377 tracepoint(librados, rados_pool_get_base_tier_enter, (rados_t)client, pool_id);
2378 int retval = client->pool_get_base_tier(pool_id, base_tier);
2379 tracepoint(librados, rados_pool_get_base_tier_exit, retval, *base_tier);
2380 return retval;
2381}
2382
2383int librados::Rados::pool_delete(const char *name)
2384{
2385 return client->pool_delete(name);
2386}
2387
2388int librados::Rados::pool_delete_async(const char *name, PoolAsyncCompletion *c)
2389{
2390 return client->pool_delete_async(name, c->pc);
2391}
2392
2393int librados::Rados::pool_list(std::list<std::string>& v)
2394{
2395 std::list<std::pair<int64_t, std::string> > pools;
2396 int r = client->pool_list(pools);
2397 if (r < 0) {
2398 return r;
2399 }
2400
2401 v.clear();
2402 for (std::list<std::pair<int64_t, std::string> >::iterator it = pools.begin();
2403 it != pools.end(); ++it) {
2404 v.push_back(it->second);
2405 }
2406 return 0;
2407}
2408
2409int librados::Rados::pool_list2(std::list<std::pair<int64_t, std::string> >& v)
2410{
2411 return client->pool_list(v);
2412}
2413
2414int64_t librados::Rados::pool_lookup(const char *name)
2415{
2416 return client->lookup_pool(name);
2417}
2418
2419int librados::Rados::pool_reverse_lookup(int64_t id, std::string *name)
2420{
2421 return client->pool_get_name(id, name);
2422}
2423
2424int librados::Rados::mon_command(string cmd, const bufferlist& inbl,
2425 bufferlist *outbl, string *outs)
2426{
2427 vector<string> cmdvec;
2428 cmdvec.push_back(cmd);
2429 return client->mon_command(cmdvec, inbl, outbl, outs);
2430}
2431
2432int librados::Rados::osd_command(int osdid, std::string cmd, const bufferlist& inbl,
2433 bufferlist *outbl, std::string *outs)
2434{
2435 vector<string> cmdvec;
2436 cmdvec.push_back(cmd);
2437 return client->osd_command(osdid, cmdvec, inbl, outbl, outs);
2438}
2439
2440int librados::Rados::mgr_command(std::string cmd, const bufferlist& inbl,
2441 bufferlist *outbl, std::string *outs)
2442{
2443 vector<string> cmdvec;
2444 cmdvec.push_back(cmd);
2445 return client->mgr_command(cmdvec, inbl, outbl, outs);
2446}
2447
2448
2449
2450int librados::Rados::pg_command(const char *pgstr, std::string cmd, const bufferlist& inbl,
2451 bufferlist *outbl, std::string *outs)
2452{
2453 vector<string> cmdvec;
2454 cmdvec.push_back(cmd);
2455
2456 pg_t pgid;
2457 if (!pgid.parse(pgstr))
2458 return -EINVAL;
2459
2460 return client->pg_command(pgid, cmdvec, inbl, outbl, outs);
2461}
2462
2463int librados::Rados::ioctx_create(const char *name, IoCtx &io)
2464{
2465 rados_ioctx_t p;
2466 int ret = rados_ioctx_create((rados_t)client, name, &p);
2467 if (ret)
2468 return ret;
2469 io.close();
2470 io.io_ctx_impl = (IoCtxImpl*)p;
2471 return 0;
2472}
2473
2474int librados::Rados::ioctx_create2(int64_t pool_id, IoCtx &io)
2475{
2476 rados_ioctx_t p;
2477 int ret = rados_ioctx_create2((rados_t)client, pool_id, &p);
2478 if (ret)
2479 return ret;
2480 io.close();
2481 io.io_ctx_impl = (IoCtxImpl*)p;
2482 return 0;
2483}
2484
2485void librados::Rados::test_blacklist_self(bool set)
2486{
2487 client->blacklist_self(set);
2488}
2489
2490int librados::Rados::get_pool_stats(std::list<string>& v,
2491 stats_map& result)
2492{
2493 map<string,::pool_stat_t> rawresult;
2494 int r = client->get_pool_stats(v, rawresult);
2495 for (map<string,::pool_stat_t>::iterator p = rawresult.begin();
2496 p != rawresult.end();
2497 ++p) {
2498 pool_stat_t& pv = result[p->first];
2499 object_stat_sum_t *sum = &p->second.stats.sum;
2500 pv.num_kb = SHIFT_ROUND_UP(sum->num_bytes, 10);
2501 pv.num_bytes = sum->num_bytes;
2502 pv.num_objects = sum->num_objects;
2503 pv.num_object_clones = sum->num_object_clones;
2504 pv.num_object_copies = sum->num_object_copies;
2505 pv.num_objects_missing_on_primary = sum->num_objects_missing_on_primary;
2506 pv.num_objects_unfound = sum->num_objects_unfound;
2507 pv.num_objects_degraded = sum->num_objects_degraded;
2508 pv.num_rd = sum->num_rd;
2509 pv.num_rd_kb = sum->num_rd_kb;
2510 pv.num_wr = sum->num_wr;
2511 pv.num_wr_kb = sum->num_wr_kb;
2512 }
2513 return r;
2514}
2515
2516int librados::Rados::get_pool_stats(std::list<string>& v,
2517 std::map<string, stats_map>& result)
2518{
2519 stats_map m;
2520 int r = get_pool_stats(v, m);
2521 if (r < 0)
2522 return r;
2523 for (map<string,pool_stat_t>::iterator p = m.begin();
2524 p != m.end();
2525 ++p) {
2526 result[p->first][string()] = p->second;
2527 }
2528 return r;
2529}
2530
2531int librados::Rados::get_pool_stats(std::list<string>& v,
2532 string& category, // unused
2533 std::map<string, stats_map>& result)
2534{
2535 return -EOPNOTSUPP;
2536}
2537
2538bool librados::Rados::get_pool_is_selfmanaged_snaps_mode(const std::string& pool)
2539{
2540 return client->get_pool_is_selfmanaged_snaps_mode(pool);
2541}
2542
2543int librados::Rados::cluster_stat(cluster_stat_t& result)
2544{
2545 ceph_statfs stats;
2546 int r = client->get_fs_stats(stats);
2547 result.kb = stats.kb;
2548 result.kb_used = stats.kb_used;
2549 result.kb_avail = stats.kb_avail;
2550 result.num_objects = stats.num_objects;
2551 return r;
2552}
2553
2554int librados::Rados::cluster_fsid(string *fsid)
2555{
2556 return client->get_fsid(fsid);
2557}
2558
2559namespace librados {
2560 struct PlacementGroupImpl {
2561 pg_t pgid;
2562 };
2563
2564 PlacementGroup::PlacementGroup()
2565 : impl{new PlacementGroupImpl}
2566 {}
2567
2568 PlacementGroup::PlacementGroup(const PlacementGroup& pg)
2569 : impl{new PlacementGroupImpl}
2570 {
2571 impl->pgid = pg.impl->pgid;
2572 }
2573
2574 PlacementGroup::~PlacementGroup()
2575 {}
2576
2577 bool PlacementGroup::parse(const char* s)
2578 {
2579 return impl->pgid.parse(s);
2580 }
2581}
2582
2583std::ostream& librados::operator<<(std::ostream& out,
2584 const librados::PlacementGroup& pg)
2585{
2586 return out << pg.impl->pgid;
2587}
2588
2589namespace {
2590 int decode_json(JSONObj *obj, pg_t& pg)
2591 {
2592 string pg_str;
2593 JSONDecoder::decode_json("pgid", pg_str, obj);
2594 if (pg.parse(pg_str.c_str())) {
2595 return 0;
2596 } else {
2597 return -EINVAL;
2598 }
2599 }
2600
2601 int get_inconsistent_pgs(librados::RadosClient& client,
2602 int64_t pool_id,
2603 std::vector<librados::PlacementGroup>* pgs)
2604 {
2605 vector<string> cmd = {
2606 "{\"prefix\": \"pg ls\","
2607 "\"pool\": " + std::to_string(pool_id) + ","
2608 "\"states\": [\"inconsistent\"],"
2609 "\"format\": \"json\"}"
2610 };
2611 bufferlist inbl, outbl;
2612 string outstring;
2613 int ret = client.mon_command(cmd, inbl, &outbl, &outstring);
2614 if (ret) {
2615 return ret;
2616 }
2617 if (!outbl.length()) {
2618 // no pg returned
2619 return ret;
2620 }
2621 JSONParser parser;
2622 if (!parser.parse(outbl.c_str(), outbl.length())) {
2623 return -EINVAL;
2624 }
2625 if (!parser.is_array()) {
2626 return -EINVAL;
2627 }
2628 vector<string> v = parser.get_array_elements();
2629 for (auto i : v) {
2630 JSONParser pg_json;
2631 if (!pg_json.parse(i.c_str(), i.length())) {
2632 return -EINVAL;
2633 }
2634 librados::PlacementGroup pg;
2635 if (decode_json(&pg_json, pg.impl->pgid)) {
2636 return -EINVAL;
2637 }
2638 pgs->emplace_back(pg);
2639 }
2640 return 0;
2641 }
2642}
2643
2644int librados::Rados::get_inconsistent_pgs(int64_t pool_id,
2645 std::vector<PlacementGroup>* pgs)
2646{
2647 return ::get_inconsistent_pgs(*client, pool_id, pgs);
2648}
2649
2650int librados::Rados::get_inconsistent_objects(const PlacementGroup& pg,
2651 const object_id_t &start_after,
2652 unsigned max_return,
2653 AioCompletion *c,
2654 std::vector<inconsistent_obj_t>* objects,
2655 uint32_t* interval)
2656{
2657 IoCtx ioctx;
2658 const pg_t pgid = pg.impl->pgid;
2659 int r = ioctx_create2(pgid.pool(), ioctx);
2660 if (r < 0) {
2661 return r;
2662 }
2663
2664 return ioctx.io_ctx_impl->get_inconsistent_objects(pgid,
2665 start_after,
2666 max_return,
2667 c->pc,
2668 objects,
2669 interval);
2670}
2671
2672int librados::Rados::get_inconsistent_snapsets(const PlacementGroup& pg,
2673 const object_id_t &start_after,
2674 unsigned max_return,
2675 AioCompletion *c,
2676 std::vector<inconsistent_snapset_t>* snapsets,
2677 uint32_t* interval)
2678{
2679 IoCtx ioctx;
2680 const pg_t pgid = pg.impl->pgid;
2681 int r = ioctx_create2(pgid.pool(), ioctx);
2682 if (r < 0) {
2683 return r;
2684 }
2685
2686 return ioctx.io_ctx_impl->get_inconsistent_snapsets(pgid,
2687 start_after,
2688 max_return,
2689 c->pc,
2690 snapsets,
2691 interval);
2692}
2693
2694int librados::Rados::wait_for_latest_osdmap()
2695{
2696 return client->wait_for_latest_osdmap();
2697}
2698
2699int librados::Rados::blacklist_add(const std::string& client_address,
2700 uint32_t expire_seconds)
2701{
2702 return client->blacklist_add(client_address, expire_seconds);
2703}
2704
2705librados::PoolAsyncCompletion *librados::Rados::pool_async_create_completion()
2706{
2707 PoolAsyncCompletionImpl *c = new PoolAsyncCompletionImpl;
2708 return new PoolAsyncCompletion(c);
2709}
2710
2711librados::AioCompletion *librados::Rados::aio_create_completion()
2712{
2713 AioCompletionImpl *c = new AioCompletionImpl;
2714 return new AioCompletion(c);
2715}
2716
2717librados::AioCompletion *librados::Rados::aio_create_completion(void *cb_arg,
2718 callback_t cb_complete,
2719 callback_t cb_safe)
2720{
2721 AioCompletionImpl *c;
2722 int r = rados_aio_create_completion(cb_arg, cb_complete, cb_safe, (void**)&c);
2723 assert(r == 0);
2724 return new AioCompletion(c);
2725}
2726
2727librados::ObjectOperation::ObjectOperation()
2728{
2729 impl = new ObjectOperationImpl;
2730}
2731
2732librados::ObjectOperation::~ObjectOperation()
2733{
2734 delete impl;
2735}
2736
2737///////////////////////////// C API //////////////////////////////
2738
2739static CephContext *rados_create_cct(const char * const clustername,
2740 CephInitParameters *iparams)
2741{
2742 // missing things compared to global_init:
2743 // g_ceph_context, g_conf, g_lockdep, signal handlers
2744 CephContext *cct = common_preinit(*iparams, CODE_ENVIRONMENT_LIBRARY, 0);
2745 if (clustername)
2746 cct->_conf->cluster = clustername;
2747 cct->_conf->parse_env(); // environment variables override
2748 cct->_conf->apply_changes(NULL);
2749
2750 TracepointProvider::initialize<tracepoint_traits>(cct);
2751 return cct;
2752}
2753
2754extern "C" int rados_create(rados_t *pcluster, const char * const id)
2755{
2756 CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT);
2757 if (id) {
2758 iparams.name.set(CEPH_ENTITY_TYPE_CLIENT, id);
2759 }
2760 CephContext *cct = rados_create_cct("", &iparams);
2761
2762 tracepoint(librados, rados_create_enter, id);
2763 *pcluster = reinterpret_cast<rados_t>(new librados::RadosClient(cct));
2764 tracepoint(librados, rados_create_exit, 0, *pcluster);
2765
2766 cct->put();
2767 return 0;
2768}
2769
2770// as above, but
2771// 1) don't assume 'client.'; name is a full type.id namestr
2772// 2) allow setting clustername
2773// 3) flags is for future expansion (maybe some of the global_init()
2774// behavior is appropriate for some consumers of librados, for instance)
2775
2776extern "C" int rados_create2(rados_t *pcluster, const char *const clustername,
2777 const char * const name, uint64_t flags)
2778{
2779 // client is assumed, but from_str will override
2780 int retval = 0;
2781 CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT);
2782 if (!name || !iparams.name.from_str(name)) {
2783 retval = -EINVAL;
2784 }
2785
2786 CephContext *cct = rados_create_cct(clustername, &iparams);
2787 tracepoint(librados, rados_create2_enter, clustername, name, flags);
2788 if (retval == 0) {
2789 *pcluster = reinterpret_cast<rados_t>(new librados::RadosClient(cct));
2790 }
2791 tracepoint(librados, rados_create2_exit, retval, *pcluster);
2792
2793 cct->put();
2794 return retval;
2795}
2796
2797/* This function is intended for use by Ceph daemons. These daemons have
2798 * already called global_init and want to use that particular configuration for
2799 * their cluster.
2800 */
2801extern "C" int rados_create_with_context(rados_t *pcluster, rados_config_t cct_)
2802{
2803 CephContext *cct = (CephContext *)cct_;
2804 TracepointProvider::initialize<tracepoint_traits>(cct);
2805
2806 tracepoint(librados, rados_create_with_context_enter, cct_);
2807 librados::RadosClient *radosp = new librados::RadosClient(cct);
2808 *pcluster = (void *)radosp;
2809 tracepoint(librados, rados_create_with_context_exit, 0, *pcluster);
2810 return 0;
2811}
2812
2813extern "C" rados_config_t rados_cct(rados_t cluster)
2814{
2815 tracepoint(librados, rados_cct_enter, cluster);
2816 librados::RadosClient *client = (librados::RadosClient *)cluster;
2817 rados_config_t retval = (rados_config_t)client->cct;
2818 tracepoint(librados, rados_cct_exit, retval);
2819 return retval;
2820}
2821
2822extern "C" int rados_connect(rados_t cluster)
2823{
2824 tracepoint(librados, rados_connect_enter, cluster);
2825 librados::RadosClient *client = (librados::RadosClient *)cluster;
2826 int retval = client->connect();
2827 tracepoint(librados, rados_connect_exit, retval);
2828 return retval;
2829}
2830
2831extern "C" void rados_shutdown(rados_t cluster)
2832{
2833 tracepoint(librados, rados_shutdown_enter, cluster);
2834 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
2835 radosp->shutdown();
2836 delete radosp;
2837 tracepoint(librados, rados_shutdown_exit);
2838}
2839
2840extern "C" uint64_t rados_get_instance_id(rados_t cluster)
2841{
2842 tracepoint(librados, rados_get_instance_id_enter, cluster);
2843 librados::RadosClient *client = (librados::RadosClient *)cluster;
2844 uint64_t retval = client->get_instance_id();
2845 tracepoint(librados, rados_get_instance_id_exit, retval);
2846 return retval;
2847}
2848
2849extern "C" void rados_version(int *major, int *minor, int *extra)
2850{
2851 tracepoint(librados, rados_version_enter, major, minor, extra);
2852 if (major)
2853 *major = LIBRADOS_VER_MAJOR;
2854 if (minor)
2855 *minor = LIBRADOS_VER_MINOR;
2856 if (extra)
2857 *extra = LIBRADOS_VER_EXTRA;
2858 tracepoint(librados, rados_version_exit, LIBRADOS_VER_MAJOR, LIBRADOS_VER_MINOR, LIBRADOS_VER_EXTRA);
2859}
2860
2861
2862// -- config --
2863extern "C" int rados_conf_read_file(rados_t cluster, const char *path_list)
2864{
2865 tracepoint(librados, rados_conf_read_file_enter, cluster, path_list);
2866 librados::RadosClient *client = (librados::RadosClient *)cluster;
2867 md_config_t *conf = client->cct->_conf;
2868 ostringstream warnings;
2869 int ret = conf->parse_config_files(path_list, &warnings, 0);
2870 if (ret) {
2871 if (warnings.tellp() > 0)
2872 lderr(client->cct) << warnings.str() << dendl;
2873 client->cct->_conf->complain_about_parse_errors(client->cct);
2874 tracepoint(librados, rados_conf_read_file_exit, ret);
2875 return ret;
2876 }
2877 conf->parse_env(); // environment variables override
2878
2879 conf->apply_changes(NULL);
2880 client->cct->_conf->complain_about_parse_errors(client->cct);
2881 tracepoint(librados, rados_conf_read_file_exit, 0);
2882 return 0;
2883}
2884
2885extern "C" int rados_conf_parse_argv(rados_t cluster, int argc, const char **argv)
2886{
2887 tracepoint(librados, rados_conf_parse_argv_enter, cluster, argc);
2888 int i;
2889 for(i = 0; i < argc; i++) {
2890 tracepoint(librados, rados_conf_parse_argv_arg, argv[i]);
2891 }
2892 librados::RadosClient *client = (librados::RadosClient *)cluster;
2893 md_config_t *conf = client->cct->_conf;
2894 vector<const char*> args;
2895 argv_to_vec(argc, argv, args);
2896 int ret = conf->parse_argv(args);
2897 if (ret) {
2898 tracepoint(librados, rados_conf_parse_argv_exit, ret);
2899 return ret;
2900 }
2901 conf->apply_changes(NULL);
2902 tracepoint(librados, rados_conf_parse_argv_exit, 0);
2903 return 0;
2904}
2905
2906// like above, but return the remainder of argv to contain remaining
2907// unparsed args. Must be allocated to at least argc by caller.
2908// remargv will contain n <= argc pointers to original argv[], the end
2909// of which may be NULL
2910
2911extern "C" int rados_conf_parse_argv_remainder(rados_t cluster, int argc,
2912 const char **argv,
2913 const char **remargv)
2914{
2915 tracepoint(librados, rados_conf_parse_argv_remainder_enter, cluster, argc);
2916 unsigned int i;
2917 for(i = 0; i < (unsigned int) argc; i++) {
2918 tracepoint(librados, rados_conf_parse_argv_remainder_arg, argv[i]);
2919 }
2920 librados::RadosClient *client = (librados::RadosClient *)cluster;
2921 md_config_t *conf = client->cct->_conf;
2922 vector<const char*> args;
2923 for (int i=0; i<argc; i++)
2924 args.push_back(argv[i]);
2925 int ret = conf->parse_argv(args);
2926 if (ret) {
2927 tracepoint(librados, rados_conf_parse_argv_remainder_exit, ret);
2928 return ret;
2929 }
2930 conf->apply_changes(NULL);
2931 assert(args.size() <= (unsigned int)argc);
2932 for (i = 0; i < (unsigned int)argc; ++i) {
2933 if (i < args.size())
2934 remargv[i] = args[i];
2935 else
2936 remargv[i] = (const char *)NULL;
2937 tracepoint(librados, rados_conf_parse_argv_remainder_remarg, remargv[i]);
2938 }
2939 tracepoint(librados, rados_conf_parse_argv_remainder_exit, 0);
2940 return 0;
2941}
2942
2943extern "C" int rados_conf_parse_env(rados_t cluster, const char *env)
2944{
2945 tracepoint(librados, rados_conf_parse_env_enter, cluster, env);
2946 librados::RadosClient *client = (librados::RadosClient *)cluster;
2947 md_config_t *conf = client->cct->_conf;
2948 vector<const char*> args;
2949 env_to_vec(args, env);
2950 int ret = conf->parse_argv(args);
2951 if (ret) {
2952 tracepoint(librados, rados_conf_parse_env_exit, ret);
2953 return ret;
2954 }
2955 conf->apply_changes(NULL);
2956 tracepoint(librados, rados_conf_parse_env_exit, 0);
2957 return 0;
2958}
2959
2960extern "C" int rados_conf_set(rados_t cluster, const char *option, const char *value)
2961{
2962 tracepoint(librados, rados_conf_set_enter, cluster, option, value);
2963 librados::RadosClient *client = (librados::RadosClient *)cluster;
2964 md_config_t *conf = client->cct->_conf;
2965 int ret = conf->set_val(option, value);
2966 if (ret) {
2967 tracepoint(librados, rados_conf_set_exit, ret);
2968 return ret;
2969 }
2970 conf->apply_changes(NULL);
2971 tracepoint(librados, rados_conf_set_exit, 0);
2972 return 0;
2973}
2974
2975/* cluster info */
2976extern "C" int rados_cluster_stat(rados_t cluster, rados_cluster_stat_t *result)
2977{
2978 tracepoint(librados, rados_cluster_stat_enter, cluster);
2979 librados::RadosClient *client = (librados::RadosClient *)cluster;
2980
2981 ceph_statfs stats;
2982 int r = client->get_fs_stats(stats);
2983 result->kb = stats.kb;
2984 result->kb_used = stats.kb_used;
2985 result->kb_avail = stats.kb_avail;
2986 result->num_objects = stats.num_objects;
2987 tracepoint(librados, rados_cluster_stat_exit, r, result->kb, result->kb_used, result->kb_avail, result->num_objects);
2988 return r;
2989}
2990
2991extern "C" int rados_conf_get(rados_t cluster, const char *option, char *buf, size_t len)
2992{
2993 tracepoint(librados, rados_conf_get_enter, cluster, option, len);
2994 char *tmp = buf;
2995 librados::RadosClient *client = (librados::RadosClient *)cluster;
2996 md_config_t *conf = client->cct->_conf;
2997 int retval = conf->get_val(option, &tmp, len);
2998 tracepoint(librados, rados_conf_get_exit, retval, retval ? "" : option);
2999 return retval;
3000}
3001
3002extern "C" int64_t rados_pool_lookup(rados_t cluster, const char *name)
3003{
3004 tracepoint(librados, rados_pool_lookup_enter, cluster, name);
3005 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3006 int64_t retval = radosp->lookup_pool(name);
3007 tracepoint(librados, rados_pool_lookup_exit, retval);
3008 return retval;
3009}
3010
3011extern "C" int rados_pool_reverse_lookup(rados_t cluster, int64_t id,
3012 char *buf, size_t maxlen)
3013{
3014 tracepoint(librados, rados_pool_reverse_lookup_enter, cluster, id, maxlen);
3015 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3016 std::string name;
3017 int r = radosp->pool_get_name(id, &name);
3018 if (r < 0) {
3019 tracepoint(librados, rados_pool_reverse_lookup_exit, r, "");
3020 return r;
3021 }
3022 if (name.length() >= maxlen) {
3023 tracepoint(librados, rados_pool_reverse_lookup_exit, -ERANGE, "");
3024 return -ERANGE;
3025 }
3026 strcpy(buf, name.c_str());
3027 int retval = name.length();
3028 tracepoint(librados, rados_pool_reverse_lookup_exit, retval, buf);
3029 return retval;
3030}
3031
3032extern "C" int rados_cluster_fsid(rados_t cluster, char *buf,
3033 size_t maxlen)
3034{
3035 tracepoint(librados, rados_cluster_fsid_enter, cluster, maxlen);
3036 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3037 std::string fsid;
3038 radosp->get_fsid(&fsid);
3039 if (fsid.length() >= maxlen) {
3040 tracepoint(librados, rados_cluster_fsid_exit, -ERANGE, "");
3041 return -ERANGE;
3042 }
3043 strcpy(buf, fsid.c_str());
3044 int retval = fsid.length();
3045 tracepoint(librados, rados_cluster_fsid_exit, retval, buf);
3046 return retval;
3047}
3048
3049extern "C" int rados_wait_for_latest_osdmap(rados_t cluster)
3050{
3051 tracepoint(librados, rados_wait_for_latest_osdmap_enter, cluster);
3052 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3053 int retval = radosp->wait_for_latest_osdmap();
3054 tracepoint(librados, rados_wait_for_latest_osdmap_exit, retval);
3055 return retval;
3056}
3057
3058extern "C" int rados_blacklist_add(rados_t cluster, char *client_address,
3059 uint32_t expire_seconds)
3060{
3061 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3062 return radosp->blacklist_add(client_address, expire_seconds);
3063}
3064
3065extern "C" int rados_pool_list(rados_t cluster, char *buf, size_t len)
3066{
3067 tracepoint(librados, rados_pool_list_enter, cluster, len);
3068 librados::RadosClient *client = (librados::RadosClient *)cluster;
3069 std::list<std::pair<int64_t, std::string> > pools;
3070 int r = client->pool_list(pools);
3071 if (r < 0) {
3072 tracepoint(librados, rados_pool_list_exit, r);
3073 return r;
3074 }
3075
3076 if (len > 0 && !buf) {
3077 tracepoint(librados, rados_pool_list_exit, -EINVAL);
3078 return -EINVAL;
3079 }
3080
3081 char *b = buf;
3082 if (b)
3083 memset(b, 0, len);
3084 int needed = 0;
3085 std::list<std::pair<int64_t, std::string> >::const_iterator i = pools.begin();
3086 std::list<std::pair<int64_t, std::string> >::const_iterator p_end =
3087 pools.end();
3088 for (; i != p_end; ++i) {
3089 int rl = i->second.length() + 1;
3090 if (len < (unsigned)rl)
3091 break;
3092 const char* pool = i->second.c_str();
3093 tracepoint(librados, rados_pool_list_pool, pool);
3094 if (b) {
3095 strncat(b, pool, rl);
3096 b += rl;
3097 }
3098 needed += rl;
3099 len -= rl;
3100 }
3101 for (; i != p_end; ++i) {
3102 int rl = i->second.length() + 1;
3103 needed += rl;
3104 }
3105 int retval = needed + 1;
3106 tracepoint(librados, rados_pool_list_exit, retval);
3107 return retval;
3108}
3109
3110CEPH_RADOS_API int rados_inconsistent_pg_list(rados_t cluster, int64_t pool_id,
3111 char *buf, size_t len)
3112{
3113 tracepoint(librados, rados_inconsistent_pg_list_enter, cluster, pool_id, len);
3114 librados::RadosClient *client = (librados::RadosClient *)cluster;
3115 std::vector<librados::PlacementGroup> pgs;
3116 int r = ::get_inconsistent_pgs(*client, pool_id, &pgs);
3117 if (r < 0) {
3118 tracepoint(librados, rados_inconsistent_pg_list_exit, r);
3119 return r;
3120 }
3121
3122 if (len > 0 && !buf) {
3123 tracepoint(librados, rados_inconsistent_pg_list_exit, -EINVAL);
3124 return -EINVAL;
3125 }
3126
3127 char *b = buf;
3128 if (b)
3129 memset(b, 0, len);
3130 int needed = 0;
3131 for (const auto pg : pgs) {
3132 std::ostringstream ss;
3133 ss << pg;
3134 auto s = ss.str();
3135 unsigned rl = s.length() + 1;
3136 if (b && len >= rl) {
3137 tracepoint(librados, rados_inconsistent_pg_list_pg, s.c_str());
3138 strncat(b, s.c_str(), rl);
3139 b += rl;
3140 len -= rl;
3141 }
3142 needed += rl;
3143 }
3144 int retval = needed + 1;
3145 tracepoint(librados, rados_inconsistent_pg_list_exit, retval);
3146 return retval;
3147}
3148
3149static void do_out_buffer(bufferlist& outbl, char **outbuf, size_t *outbuflen)
3150{
3151 if (outbuf) {
3152 if (outbl.length() > 0) {
3153 *outbuf = (char *)malloc(outbl.length());
3154 memcpy(*outbuf, outbl.c_str(), outbl.length());
3155 } else {
3156 *outbuf = NULL;
3157 }
3158 }
3159 if (outbuflen)
3160 *outbuflen = outbl.length();
3161}
3162
3163static void do_out_buffer(string& outbl, char **outbuf, size_t *outbuflen)
3164{
3165 if (outbuf) {
3166 if (outbl.length() > 0) {
3167 *outbuf = (char *)malloc(outbl.length());
3168 memcpy(*outbuf, outbl.c_str(), outbl.length());
3169 } else {
3170 *outbuf = NULL;
3171 }
3172 }
3173 if (outbuflen)
3174 *outbuflen = outbl.length();
3175}
3176
3177extern "C" int rados_ping_monitor(rados_t cluster, const char *mon_id,
3178 char **outstr, size_t *outstrlen)
3179{
3180 tracepoint(librados, rados_ping_monitor_enter, cluster, mon_id);
3181 librados::RadosClient *client = (librados::RadosClient *)cluster;
3182 string str;
3183
3184 if (!mon_id) {
3185 tracepoint(librados, rados_ping_monitor_exit, -EINVAL, NULL, NULL);
3186 return -EINVAL;
3187 }
3188
3189 int ret = client->ping_monitor(mon_id, &str);
3190 if (ret == 0) {
3191 do_out_buffer(str, outstr, outstrlen);
3192 }
3193 tracepoint(librados, rados_ping_monitor_exit, ret, ret < 0 ? NULL : outstr, ret < 0 ? NULL : outstrlen);
3194 return ret;
3195}
3196
3197extern "C" int rados_mon_command(rados_t cluster, const char **cmd,
3198 size_t cmdlen,
3199 const char *inbuf, size_t inbuflen,
3200 char **outbuf, size_t *outbuflen,
3201 char **outs, size_t *outslen)
3202{
3203 tracepoint(librados, rados_mon_command_enter, cluster, cmdlen, inbuf, inbuflen);
3204 librados::RadosClient *client = (librados::RadosClient *)cluster;
3205 bufferlist inbl;
3206 bufferlist outbl;
3207 string outstring;
3208 vector<string> cmdvec;
3209
3210 for (size_t i = 0; i < cmdlen; i++) {
3211 tracepoint(librados, rados_mon_command_cmd, cmd[i]);
3212 cmdvec.push_back(cmd[i]);
3213 }
3214
3215 inbl.append(inbuf, inbuflen);
3216 int ret = client->mon_command(cmdvec, inbl, &outbl, &outstring);
3217
3218 do_out_buffer(outbl, outbuf, outbuflen);
3219 do_out_buffer(outstring, outs, outslen);
3220 tracepoint(librados, rados_mon_command_exit, ret, outbuf, outbuflen, outs, outslen);
3221 return ret;
3222}
3223
3224extern "C" int rados_mon_command_target(rados_t cluster, const char *name,
3225 const char **cmd,
3226 size_t cmdlen,
3227 const char *inbuf, size_t inbuflen,
3228 char **outbuf, size_t *outbuflen,
3229 char **outs, size_t *outslen)
3230{
3231 tracepoint(librados, rados_mon_command_target_enter, cluster, name, cmdlen, inbuf, inbuflen);
3232 librados::RadosClient *client = (librados::RadosClient *)cluster;
3233 bufferlist inbl;
3234 bufferlist outbl;
3235 string outstring;
3236 vector<string> cmdvec;
3237
3238 // is this a numeric id?
3239 char *endptr;
3240 errno = 0;
3241 long rank = strtol(name, &endptr, 10);
3242 if ((errno == ERANGE && (rank == LONG_MAX || rank == LONG_MIN)) ||
3243 (errno != 0 && rank == 0) ||
3244 endptr == name || // no digits
3245 *endptr != '\0') { // extra characters
3246 rank = -1;
3247 }
3248
3249 for (size_t i = 0; i < cmdlen; i++) {
3250 tracepoint(librados, rados_mon_command_target_cmd, cmd[i]);
3251 cmdvec.push_back(cmd[i]);
3252 }
3253
3254 inbl.append(inbuf, inbuflen);
3255 int ret;
3256 if (rank >= 0)
3257 ret = client->mon_command(rank, cmdvec, inbl, &outbl, &outstring);
3258 else
3259 ret = client->mon_command(name, cmdvec, inbl, &outbl, &outstring);
3260
3261 do_out_buffer(outbl, outbuf, outbuflen);
3262 do_out_buffer(outstring, outs, outslen);
3263 tracepoint(librados, rados_mon_command_target_exit, ret, outbuf, outbuflen, outs, outslen);
3264 return ret;
3265}
3266
3267extern "C" int rados_osd_command(rados_t cluster, int osdid, const char **cmd,
3268 size_t cmdlen,
3269 const char *inbuf, size_t inbuflen,
3270 char **outbuf, size_t *outbuflen,
3271 char **outs, size_t *outslen)
3272{
3273 tracepoint(librados, rados_osd_command_enter, cluster, osdid, cmdlen, inbuf, inbuflen);
3274 librados::RadosClient *client = (librados::RadosClient *)cluster;
3275 bufferlist inbl;
3276 bufferlist outbl;
3277 string outstring;
3278 vector<string> cmdvec;
3279
3280 for (size_t i = 0; i < cmdlen; i++) {
3281 tracepoint(librados, rados_osd_command_cmd, cmd[i]);
3282 cmdvec.push_back(cmd[i]);
3283 }
3284
3285 inbl.append(inbuf, inbuflen);
3286 int ret = client->osd_command(osdid, cmdvec, inbl, &outbl, &outstring);
3287
3288 do_out_buffer(outbl, outbuf, outbuflen);
3289 do_out_buffer(outstring, outs, outslen);
3290 tracepoint(librados, rados_osd_command_exit, ret, outbuf, outbuflen, outs, outslen);
3291 return ret;
3292}
3293
3294extern "C" int rados_mgr_command(rados_t cluster, const char **cmd,
3295 size_t cmdlen,
3296 const char *inbuf, size_t inbuflen,
3297 char **outbuf, size_t *outbuflen,
3298 char **outs, size_t *outslen)
3299{
3300 tracepoint(librados, rados_mgr_command_enter, cluster, cmdlen, inbuf,
3301 inbuflen);
3302
3303 librados::RadosClient *client = (librados::RadosClient *)cluster;
3304 bufferlist inbl;
3305 bufferlist outbl;
3306 string outstring;
3307 vector<string> cmdvec;
3308
3309 for (size_t i = 0; i < cmdlen; i++) {
3310 tracepoint(librados, rados_mgr_command_cmd, cmd[i]);
3311 cmdvec.push_back(cmd[i]);
3312 }
3313
3314 inbl.append(inbuf, inbuflen);
3315 int ret = client->mgr_command(cmdvec, inbl, &outbl, &outstring);
3316
3317 do_out_buffer(outbl, outbuf, outbuflen);
3318 do_out_buffer(outstring, outs, outslen);
3319 tracepoint(librados, rados_mgr_command_exit, ret, outbuf, outbuflen, outs,
3320 outslen);
3321 return ret;
3322}
3323
3324extern "C" int rados_pg_command(rados_t cluster, const char *pgstr,
3325 const char **cmd, size_t cmdlen,
3326 const char *inbuf, size_t inbuflen,
3327 char **outbuf, size_t *outbuflen,
3328 char **outs, size_t *outslen)
3329{
3330 tracepoint(librados, rados_pg_command_enter, cluster, pgstr, cmdlen, inbuf, inbuflen);
3331 librados::RadosClient *client = (librados::RadosClient *)cluster;
3332 bufferlist inbl;
3333 bufferlist outbl;
3334 string outstring;
3335 pg_t pgid;
3336 vector<string> cmdvec;
3337
3338 for (size_t i = 0; i < cmdlen; i++) {
3339 tracepoint(librados, rados_pg_command_cmd, cmd[i]);
3340 cmdvec.push_back(cmd[i]);
3341 }
3342
3343 inbl.append(inbuf, inbuflen);
3344 if (!pgid.parse(pgstr))
3345 return -EINVAL;
3346
3347 int ret = client->pg_command(pgid, cmdvec, inbl, &outbl, &outstring);
3348
3349 do_out_buffer(outbl, outbuf, outbuflen);
3350 do_out_buffer(outstring, outs, outslen);
3351 tracepoint(librados, rados_pg_command_exit, ret, outbuf, outbuflen, outs, outslen);
3352 return ret;
3353}
3354
3355extern "C" void rados_buffer_free(char *buf)
3356{
3357 tracepoint(librados, rados_buffer_free_enter, buf);
3358 if (buf)
3359 free(buf);
3360 tracepoint(librados, rados_buffer_free_exit);
3361}
3362
3363extern "C" int rados_monitor_log(rados_t cluster, const char *level, rados_log_callback_t cb, void *arg)
3364{
3365 tracepoint(librados, rados_monitor_log_enter, cluster, level, cb, arg);
3366 librados::RadosClient *client = (librados::RadosClient *)cluster;
3367 int retval = client->monitor_log(level, cb, arg);
3368 tracepoint(librados, rados_monitor_log_exit, retval);
3369 return retval;
3370}
3371
3372extern "C" int rados_ioctx_create(rados_t cluster, const char *name, rados_ioctx_t *io)
3373{
3374 tracepoint(librados, rados_ioctx_create_enter, cluster, name);
3375 librados::RadosClient *client = (librados::RadosClient *)cluster;
3376 librados::IoCtxImpl *ctx;
3377
3378 int r = client->create_ioctx(name, &ctx);
3379 if (r < 0) {
3380 tracepoint(librados, rados_ioctx_create_exit, r, NULL);
3381 return r;
3382 }
3383
3384 *io = ctx;
3385 ctx->get();
3386 tracepoint(librados, rados_ioctx_create_exit, 0, ctx);
3387 return 0;
3388}
3389
3390extern "C" int rados_ioctx_create2(rados_t cluster, int64_t pool_id,
3391 rados_ioctx_t *io)
3392{
3393 tracepoint(librados, rados_ioctx_create2_enter, cluster, pool_id);
3394 librados::RadosClient *client = (librados::RadosClient *)cluster;
3395 librados::IoCtxImpl *ctx;
3396
3397 int r = client->create_ioctx(pool_id, &ctx);
3398 if (r < 0) {
3399 tracepoint(librados, rados_ioctx_create2_exit, r, NULL);
3400 return r;
3401 }
3402
3403 *io = ctx;
3404 ctx->get();
3405 tracepoint(librados, rados_ioctx_create2_exit, 0, ctx);
3406 return 0;
3407}
3408
3409extern "C" void rados_ioctx_destroy(rados_ioctx_t io)
3410{
3411 tracepoint(librados, rados_ioctx_destroy_enter, io);
3412 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3413 ctx->put();
3414 tracepoint(librados, rados_ioctx_destroy_exit);
3415}
3416
3417extern "C" int rados_ioctx_pool_stat(rados_ioctx_t io, struct rados_pool_stat_t *stats)
3418{
3419 tracepoint(librados, rados_ioctx_pool_stat_enter, io);
3420 librados::IoCtxImpl *io_ctx_impl = (librados::IoCtxImpl *)io;
3421 list<string> ls;
3422 std::string pool_name;
3423
3424 int err = io_ctx_impl->client->pool_get_name(io_ctx_impl->get_id(), &pool_name);
3425 if (err) {
3426 tracepoint(librados, rados_ioctx_pool_stat_exit, err, stats);
3427 return err;
3428 }
3429 ls.push_back(pool_name);
3430
3431 map<string, ::pool_stat_t> rawresult;
3432 err = io_ctx_impl->client->get_pool_stats(ls, rawresult);
3433 if (err) {
3434 tracepoint(librados, rados_ioctx_pool_stat_exit, err, stats);
3435 return err;
3436 }
3437
3438 ::pool_stat_t& r = rawresult[pool_name];
3439 stats->num_kb = SHIFT_ROUND_UP(r.stats.sum.num_bytes, 10);
3440 stats->num_bytes = r.stats.sum.num_bytes;
3441 stats->num_objects = r.stats.sum.num_objects;
3442 stats->num_object_clones = r.stats.sum.num_object_clones;
3443 stats->num_object_copies = r.stats.sum.num_object_copies;
3444 stats->num_objects_missing_on_primary = r.stats.sum.num_objects_missing_on_primary;
3445 stats->num_objects_unfound = r.stats.sum.num_objects_unfound;
3446 stats->num_objects_degraded =
3447 r.stats.sum.num_objects_degraded +
3448 r.stats.sum.num_objects_misplaced; // FIXME: this is imprecise
3449 stats->num_rd = r.stats.sum.num_rd;
3450 stats->num_rd_kb = r.stats.sum.num_rd_kb;
3451 stats->num_wr = r.stats.sum.num_wr;
3452 stats->num_wr_kb = r.stats.sum.num_wr_kb;
3453 tracepoint(librados, rados_ioctx_pool_stat_exit, 0, stats);
3454 return 0;
3455}
3456
3457extern "C" rados_config_t rados_ioctx_cct(rados_ioctx_t io)
3458{
3459 tracepoint(librados, rados_ioctx_cct_enter, io);
3460 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3461 rados_config_t retval = (rados_config_t)ctx->client->cct;
3462 tracepoint(librados, rados_ioctx_cct_exit, retval);
3463 return retval;
3464}
3465
3466extern "C" void rados_ioctx_snap_set_read(rados_ioctx_t io, rados_snap_t seq)
3467{
3468 tracepoint(librados, rados_ioctx_snap_set_read_enter, io, seq);
3469 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3470 ctx->set_snap_read((snapid_t)seq);
3471 tracepoint(librados, rados_ioctx_snap_set_read_exit);
3472}
3473
3474extern "C" int rados_ioctx_selfmanaged_snap_set_write_ctx(rados_ioctx_t io,
3475 rados_snap_t seq, rados_snap_t *snaps, int num_snaps)
3476{
3477 tracepoint(librados, rados_ioctx_selfmanaged_snap_set_write_ctx_enter, io, seq, snaps, num_snaps);
3478 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3479 vector<snapid_t> snv;
3480 snv.resize(num_snaps);
3481 for (int i=0; i<num_snaps; i++) {
3482 snv[i] = (snapid_t)snaps[i];
3483 }
3484 int retval = ctx->set_snap_write_context((snapid_t)seq, snv);
3485 tracepoint(librados, rados_ioctx_selfmanaged_snap_set_write_ctx_exit, retval);
3486 return retval;
3487}
3488
3489extern "C" int rados_write(rados_ioctx_t io, const char *o, const char *buf, size_t len, uint64_t off)
3490{
3491 tracepoint(librados, rados_write_enter, io, o, buf, len, off);
3492 if (len > UINT_MAX/2)
3493 return -E2BIG;
3494 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3495 object_t oid(o);
3496 bufferlist bl;
3497 bl.append(buf, len);
3498 int retval = ctx->write(oid, bl, len, off);
3499 tracepoint(librados, rados_write_exit, retval);
3500 return retval;
3501}
3502
3503extern "C" int rados_append(rados_ioctx_t io, const char *o, const char *buf, size_t len)
3504{
3505 tracepoint(librados, rados_append_enter, io, o, buf, len);
3506 if (len > UINT_MAX/2)
3507 return -E2BIG;
3508 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3509 object_t oid(o);
3510 bufferlist bl;
3511 bl.append(buf, len);
3512 int retval = ctx->append(oid, bl, len);
3513 tracepoint(librados, rados_append_exit, retval);
3514 return retval;
3515}
3516
3517extern "C" int rados_write_full(rados_ioctx_t io, const char *o, const char *buf, size_t len)
3518{
3519 tracepoint(librados, rados_write_full_enter, io, o, buf, len);
3520 if (len > UINT_MAX/2)
3521 return -E2BIG;
3522 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3523 object_t oid(o);
3524 bufferlist bl;
3525 bl.append(buf, len);
3526 int retval = ctx->write_full(oid, bl);
3527 tracepoint(librados, rados_write_full_exit, retval);
3528 return retval;
3529}
3530
3531extern "C" int rados_writesame(rados_ioctx_t io,
3532 const char *o,
3533 const char *buf,
3534 size_t data_len,
3535 size_t write_len,
3536 uint64_t off)
3537{
3538 tracepoint(librados, rados_writesame_enter, io, o, buf, data_len, write_len, off);
3539 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3540 object_t oid(o);
3541 bufferlist bl;
3542 bl.append(buf, data_len);
3543 int retval = ctx->writesame(oid, bl, write_len, off);
3544 tracepoint(librados, rados_writesame_exit, retval);
3545 return retval;
3546}
3547
3548extern "C" int rados_trunc(rados_ioctx_t io, const char *o, uint64_t size)
3549{
3550 tracepoint(librados, rados_trunc_enter, io, o, size);
3551 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3552 object_t oid(o);
3553 int retval = ctx->trunc(oid, size);
3554 tracepoint(librados, rados_trunc_exit, retval);
3555 return retval;
3556}
3557
3558extern "C" int rados_remove(rados_ioctx_t io, const char *o)
3559{
3560 tracepoint(librados, rados_remove_enter, io, o);
3561 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3562 object_t oid(o);
3563 int retval = ctx->remove(oid);
3564 tracepoint(librados, rados_remove_exit, retval);
3565 return retval;
3566}
3567
3568extern "C" int rados_read(rados_ioctx_t io, const char *o, char *buf, size_t len, uint64_t off)
3569{
3570 tracepoint(librados, rados_read_enter, io, o, buf, len, off);
3571 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3572 int ret;
3573 object_t oid(o);
3574
3575 bufferlist bl;
3576 bufferptr bp = buffer::create_static(len, buf);
3577 bl.push_back(bp);
3578
3579 ret = ctx->read(oid, bl, len, off);
3580 if (ret >= 0) {
3581 if (bl.length() > len) {
3582 tracepoint(librados, rados_read_exit, -ERANGE, NULL);
3583 return -ERANGE;
3584 }
3585 if (!bl.is_provided_buffer(buf))
3586 bl.copy(0, bl.length(), buf);
3587 ret = bl.length(); // hrm :/
3588 }
3589
3590 tracepoint(librados, rados_read_exit, ret, buf);
3591 return ret;
3592}
3593
3594extern "C" int rados_checksum(rados_ioctx_t io, const char *o,
3595 rados_checksum_type_t type,
3596 const char *init_value, size_t init_value_len,
3597 size_t len, uint64_t off, size_t chunk_size,
3598 char *pchecksum, size_t checksum_len)
3599{
3600 tracepoint(librados, rados_checksum_enter, io, o, type, init_value,
3601 init_value_len, len, off, chunk_size);
3602 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3603 object_t oid(o);
3604
3605 bufferlist init_value_bl;
3606 init_value_bl.append(init_value, init_value_len);
3607
3608 bufferlist checksum_bl;
3609
3610 int retval = ctx->checksum(oid, get_checksum_op_type(type), init_value_bl,
3611 len, off, chunk_size, &checksum_bl);
3612 if (retval >= 0) {
3613 if (checksum_bl.length() > checksum_len) {
3614 tracepoint(librados, rados_checksum_exit, -ERANGE, NULL, 0);
3615 return -ERANGE;
3616 }
3617
3618 checksum_bl.copy(0, checksum_bl.length(), pchecksum);
3619 }
3620 tracepoint(librados, rados_checksum_exit, retval, pchecksum, checksum_len);
3621 return retval;
3622}
3623
3624extern "C" uint64_t rados_get_last_version(rados_ioctx_t io)
3625{
3626 tracepoint(librados, rados_get_last_version_enter, io);
3627 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3628 uint64_t retval = ctx->last_version();
3629 tracepoint(librados, rados_get_last_version_exit, retval);
3630 return retval;
3631}
3632
3633extern "C" int rados_pool_create(rados_t cluster, const char *name)
3634{
3635 tracepoint(librados, rados_pool_create_enter, cluster, name);
3636 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3637 string sname(name);
3638 int retval = radosp->pool_create(sname);
3639 tracepoint(librados, rados_pool_create_exit, retval);
3640 return retval;
3641}
3642
3643extern "C" int rados_pool_create_with_auid(rados_t cluster, const char *name,
3644 uint64_t auid)
3645{
3646 tracepoint(librados, rados_pool_create_with_auid_enter, cluster, name, auid);
3647 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3648 string sname(name);
3649 int retval = radosp->pool_create(sname, auid);
3650 tracepoint(librados, rados_pool_create_with_auid_exit, retval);
3651 return retval;
3652}
3653
3654extern "C" int rados_pool_create_with_crush_rule(rados_t cluster, const char *name,
3655 __u8 crush_rule_num)
3656{
3657 tracepoint(librados, rados_pool_create_with_crush_rule_enter, cluster, name, crush_rule_num);
3658 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3659 string sname(name);
3660 int retval = radosp->pool_create(sname, 0, crush_rule_num);
3661 tracepoint(librados, rados_pool_create_with_crush_rule_exit, retval);
3662 return retval;
3663}
3664
3665extern "C" int rados_pool_create_with_all(rados_t cluster, const char *name,
3666 uint64_t auid, __u8 crush_rule_num)
3667{
3668 tracepoint(librados, rados_pool_create_with_all_enter, cluster, name, auid, crush_rule_num);
3669 librados::RadosClient *radosp = (librados::RadosClient *)cluster;
3670 string sname(name);
3671 int retval = radosp->pool_create(sname, auid, crush_rule_num);
3672 tracepoint(librados, rados_pool_create_with_all_exit, retval);
3673 return retval;
3674}
3675
3676extern "C" int rados_pool_get_base_tier(rados_t cluster, int64_t pool_id, int64_t* base_tier)
3677{
3678 tracepoint(librados, rados_pool_get_base_tier_enter, cluster, pool_id);
3679 librados::RadosClient *client = (librados::RadosClient *)cluster;
3680 int retval = client->pool_get_base_tier(pool_id, base_tier);
3681 tracepoint(librados, rados_pool_get_base_tier_exit, retval, *base_tier);
3682 return retval;
3683}
3684
3685extern "C" int rados_pool_delete(rados_t cluster, const char *pool_name)
3686{
3687 tracepoint(librados, rados_pool_delete_enter, cluster, pool_name);
3688 librados::RadosClient *client = (librados::RadosClient *)cluster;
3689 int retval = client->pool_delete(pool_name);
3690 tracepoint(librados, rados_pool_delete_exit, retval);
3691 return retval;
3692}
3693
3694extern "C" int rados_ioctx_pool_set_auid(rados_ioctx_t io, uint64_t auid)
3695{
3696 tracepoint(librados, rados_ioctx_pool_set_auid_enter, io, auid);
3697 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3698 int retval = ctx->pool_change_auid(auid);
3699 tracepoint(librados, rados_ioctx_pool_set_auid_exit, retval);
3700 return retval;
3701}
3702
3703extern "C" int rados_ioctx_pool_get_auid(rados_ioctx_t io, uint64_t *auid)
3704{
3705 tracepoint(librados, rados_ioctx_pool_get_auid_enter, io);
3706 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3707 int retval = ctx->client->pool_get_auid(ctx->get_id(), (unsigned long long *)auid);
3708 tracepoint(librados, rados_ioctx_pool_get_auid_exit, retval, *auid);
3709 return retval;
3710}
3711
3712extern "C" int rados_ioctx_pool_requires_alignment(rados_ioctx_t io)
3713{
3714 tracepoint(librados, rados_ioctx_pool_requires_alignment_enter, io);
3715 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3716 int retval = ctx->client->pool_requires_alignment(ctx->get_id());
3717 tracepoint(librados, rados_ioctx_pool_requires_alignment_exit, retval);
3718 return retval;
3719}
3720
3721extern "C" int rados_ioctx_pool_requires_alignment2(rados_ioctx_t io,
3722 int *requires)
3723{
3724 tracepoint(librados, rados_ioctx_pool_requires_alignment_enter2, io);
3725 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3726 bool requires_alignment;
3727 int retval = ctx->client->pool_requires_alignment2(ctx->get_id(),
3728 &requires_alignment);
3729 tracepoint(librados, rados_ioctx_pool_requires_alignment_exit2, retval,
3730 requires_alignment);
3731 if (requires)
3732 *requires = requires_alignment;
3733 return retval;
3734}
3735
3736extern "C" uint64_t rados_ioctx_pool_required_alignment(rados_ioctx_t io)
3737{
3738 tracepoint(librados, rados_ioctx_pool_required_alignment_enter, io);
3739 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3740 uint64_t retval = ctx->client->pool_required_alignment(ctx->get_id());
3741 tracepoint(librados, rados_ioctx_pool_required_alignment_exit, retval);
3742 return retval;
3743}
3744
3745extern "C" int rados_ioctx_pool_required_alignment2(rados_ioctx_t io,
3746 uint64_t *alignment)
3747{
3748 tracepoint(librados, rados_ioctx_pool_required_alignment_enter2, io);
3749 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3750 int retval = ctx->client->pool_required_alignment2(ctx->get_id(),
3751 alignment);
3752 tracepoint(librados, rados_ioctx_pool_required_alignment_exit2, retval,
3753 *alignment);
3754 return retval;
3755}
3756
3757extern "C" void rados_ioctx_locator_set_key(rados_ioctx_t io, const char *key)
3758{
3759 tracepoint(librados, rados_ioctx_locator_set_key_enter, io, key);
3760 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3761 if (key)
3762 ctx->oloc.key = key;
3763 else
3764 ctx->oloc.key = "";
3765 tracepoint(librados, rados_ioctx_locator_set_key_exit);
3766}
3767
3768extern "C" void rados_ioctx_set_namespace(rados_ioctx_t io, const char *nspace)
3769{
3770 tracepoint(librados, rados_ioctx_set_namespace_enter, io, nspace);
3771 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3772 if (nspace)
3773 ctx->oloc.nspace = nspace;
3774 else
3775 ctx->oloc.nspace = "";
3776 tracepoint(librados, rados_ioctx_set_namespace_exit);
3777}
3778
3779extern "C" rados_t rados_ioctx_get_cluster(rados_ioctx_t io)
3780{
3781 tracepoint(librados, rados_ioctx_get_cluster_enter, io);
3782 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3783 rados_t retval = (rados_t)ctx->client;
3784 tracepoint(librados, rados_ioctx_get_cluster_exit, retval);
3785 return retval;
3786}
3787
3788extern "C" int64_t rados_ioctx_get_id(rados_ioctx_t io)
3789{
3790 tracepoint(librados, rados_ioctx_get_id_enter, io);
3791 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3792 int64_t retval = ctx->get_id();
3793 tracepoint(librados, rados_ioctx_get_id_exit, retval);
3794 return retval;
3795}
3796
3797extern "C" int rados_ioctx_get_pool_name(rados_ioctx_t io, char *s, unsigned maxlen)
3798{
3799 tracepoint(librados, rados_ioctx_get_pool_name_enter, io, maxlen);
3800 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3801 std::string pool_name;
3802
3803 int err = ctx->client->pool_get_name(ctx->get_id(), &pool_name);
3804 if (err) {
3805 tracepoint(librados, rados_ioctx_get_pool_name_exit, err, "");
3806 return err;
3807 }
3808 if (pool_name.length() >= maxlen) {
3809 tracepoint(librados, rados_ioctx_get_pool_name_exit, -ERANGE, "");
3810 return -ERANGE;
3811 }
3812 strcpy(s, pool_name.c_str());
3813 int retval = pool_name.length();
3814 tracepoint(librados, rados_ioctx_get_pool_name_exit, retval, s);
3815 return retval;
3816}
3817
3818// snaps
3819
3820extern "C" int rados_ioctx_snap_create(rados_ioctx_t io, const char *snapname)
3821{
3822 tracepoint(librados, rados_ioctx_snap_create_enter, io, snapname);
3823 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3824 int retval = ctx->snap_create(snapname);
3825 tracepoint(librados, rados_ioctx_snap_create_exit, retval);
3826 return retval;
3827}
3828
3829extern "C" int rados_ioctx_snap_remove(rados_ioctx_t io, const char *snapname)
3830{
3831 tracepoint(librados, rados_ioctx_snap_remove_enter, io, snapname);
3832 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3833 int retval = ctx->snap_remove(snapname);
3834 tracepoint(librados, rados_ioctx_snap_remove_exit, retval);
3835 return retval;
3836}
3837
3838extern "C" int rados_ioctx_snap_rollback(rados_ioctx_t io, const char *oid,
3839 const char *snapname)
3840{
3841 tracepoint(librados, rados_ioctx_snap_rollback_enter, io, oid, snapname);
3842 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3843 int retval = ctx->rollback(oid, snapname);
3844 tracepoint(librados, rados_ioctx_snap_rollback_exit, retval);
3845 return retval;
3846}
3847
3848// Deprecated name kept for backward compatibility
3849extern "C" int rados_rollback(rados_ioctx_t io, const char *oid,
3850 const char *snapname)
3851{
3852 return rados_ioctx_snap_rollback(io, oid, snapname);
3853}
3854
3855extern "C" int rados_ioctx_selfmanaged_snap_create(rados_ioctx_t io,
3856 uint64_t *snapid)
3857{
3858 tracepoint(librados, rados_ioctx_selfmanaged_snap_create_enter, io);
3859 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3860 int retval = ctx->selfmanaged_snap_create(snapid);
3861 tracepoint(librados, rados_ioctx_selfmanaged_snap_create_exit, retval, *snapid);
3862 return retval;
3863}
3864
3865extern "C" void
3866rados_aio_ioctx_selfmanaged_snap_create(rados_ioctx_t io,
3867 rados_snap_t *snapid,
3868 rados_completion_t completion)
3869{
3870 tracepoint(librados, rados_ioctx_selfmanaged_snap_create_enter, io);
3871 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3872 librados::AioCompletionImpl *c = (librados::AioCompletionImpl*)completion;
3873 ctx->aio_selfmanaged_snap_create(snapid, c);
3874 tracepoint(librados, rados_ioctx_selfmanaged_snap_create_exit, 0, 0);
3875}
3876
3877extern "C" int rados_ioctx_selfmanaged_snap_remove(rados_ioctx_t io,
3878 uint64_t snapid)
3879{
3880 tracepoint(librados, rados_ioctx_selfmanaged_snap_remove_enter, io, snapid);
3881 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3882 int retval = ctx->selfmanaged_snap_remove(snapid);
3883 tracepoint(librados, rados_ioctx_selfmanaged_snap_remove_exit, retval);
3884 return retval;
3885}
3886
3887extern "C" void
3888rados_aio_ioctx_selfmanaged_snap_remove(rados_ioctx_t io,
3889 rados_snap_t snapid,
3890 rados_completion_t completion)
3891{
3892 tracepoint(librados, rados_ioctx_selfmanaged_snap_remove_enter, io, snapid);
3893 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3894 librados::AioCompletionImpl *c = (librados::AioCompletionImpl*)completion;
3895 ctx->aio_selfmanaged_snap_remove(snapid, c);
3896 tracepoint(librados, rados_ioctx_selfmanaged_snap_remove_exit, 0);
3897}
3898
3899extern "C" int rados_ioctx_selfmanaged_snap_rollback(rados_ioctx_t io,
3900 const char *oid,
3901 uint64_t snapid)
3902{
3903 tracepoint(librados, rados_ioctx_selfmanaged_snap_rollback_enter, io, oid, snapid);
3904 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3905 int retval = ctx->selfmanaged_snap_rollback_object(oid, ctx->snapc, snapid);
3906 tracepoint(librados, rados_ioctx_selfmanaged_snap_rollback_exit, retval);
3907 return retval;
3908}
3909
3910extern "C" int rados_ioctx_snap_list(rados_ioctx_t io, rados_snap_t *snaps,
3911 int maxlen)
3912{
3913 tracepoint(librados, rados_ioctx_snap_list_enter, io, maxlen);
3914 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3915 vector<uint64_t> snapvec;
3916 int r = ctx->snap_list(&snapvec);
3917 if (r < 0) {
3918 tracepoint(librados, rados_ioctx_snap_list_exit, r, snaps, 0);
3919 return r;
3920 }
3921 if ((int)snapvec.size() <= maxlen) {
3922 for (unsigned i=0; i<snapvec.size(); i++) {
3923 snaps[i] = snapvec[i];
3924 }
3925 int retval = snapvec.size();
3926 tracepoint(librados, rados_ioctx_snap_list_exit, retval, snaps, retval);
3927 return retval;
3928 }
3929 int retval = -ERANGE;
3930 tracepoint(librados, rados_ioctx_snap_list_exit, retval, snaps, 0);
3931 return retval;
3932}
3933
3934extern "C" int rados_ioctx_snap_lookup(rados_ioctx_t io, const char *name,
3935 rados_snap_t *id)
3936{
3937 tracepoint(librados, rados_ioctx_snap_lookup_enter, io, name);
3938 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3939 int retval = ctx->snap_lookup(name, (uint64_t *)id);
3940 tracepoint(librados, rados_ioctx_snap_lookup_exit, retval, *id);
3941 return retval;
3942}
3943
3944extern "C" int rados_ioctx_snap_get_name(rados_ioctx_t io, rados_snap_t id,
3945 char *name, int maxlen)
3946{
3947 tracepoint(librados, rados_ioctx_snap_get_name_enter, io, id, maxlen);
3948 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3949 std::string sname;
3950 int r = ctx->snap_get_name(id, &sname);
3951 if (r < 0) {
3952 tracepoint(librados, rados_ioctx_snap_get_name_exit, r, "");
3953 return r;
3954 }
3955 if ((int)sname.length() >= maxlen) {
3956 int retval = -ERANGE;
3957 tracepoint(librados, rados_ioctx_snap_get_name_exit, retval, "");
3958 return retval;
3959 }
3960 strncpy(name, sname.c_str(), maxlen);
3961 tracepoint(librados, rados_ioctx_snap_get_name_exit, 0, name);
3962 return 0;
3963}
3964
3965extern "C" int rados_ioctx_snap_get_stamp(rados_ioctx_t io, rados_snap_t id, time_t *t)
3966{
3967 tracepoint(librados, rados_ioctx_snap_get_stamp_enter, io, id);
3968 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3969 int retval = ctx->snap_get_stamp(id, t);
3970 tracepoint(librados, rados_ioctx_snap_get_stamp_exit, retval, *t);
3971 return retval;
3972}
3973
3974extern "C" int rados_cmpext(rados_ioctx_t io, const char *o,
3975 const char *cmp_buf, size_t cmp_len, uint64_t off)
3976{
3977 tracepoint(librados, rados_cmpext_enter, io, o, cmp_buf, cmp_len, off);
3978 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3979 int ret;
3980 object_t oid(o);
3981
3982 bufferlist cmp_bl;
3983 cmp_bl.append(cmp_buf, cmp_len);
3984
3985 ret = ctx->cmpext(oid, off, cmp_bl);
3986 tracepoint(librados, rados_cmpext_exit, ret);
3987
3988 return ret;
3989}
3990
3991extern "C" int rados_getxattr(rados_ioctx_t io, const char *o, const char *name,
3992 char *buf, size_t len)
3993{
3994 tracepoint(librados, rados_getxattr_enter, io, o, name, len);
3995 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
3996 int ret;
3997 object_t oid(o);
3998 bufferlist bl;
3999 bl.push_back(buffer::create_static(len, buf));
4000 ret = ctx->getxattr(oid, name, bl);
4001 if (ret >= 0) {
4002 if (bl.length() > len) {
4003 tracepoint(librados, rados_getxattr_exit, -ERANGE, buf, 0);
4004 return -ERANGE;
4005 }
4006 if (!bl.is_provided_buffer(buf))
4007 bl.copy(0, bl.length(), buf);
4008 ret = bl.length();
4009 }
4010
4011 tracepoint(librados, rados_getxattr_exit, ret, buf, ret);
4012 return ret;
4013}
4014
4015extern "C" int rados_getxattrs(rados_ioctx_t io, const char *oid,
4016 rados_xattrs_iter_t *iter)
4017{
4018 tracepoint(librados, rados_getxattrs_enter, io, oid);
4019 librados::RadosXattrsIter *it = new librados::RadosXattrsIter();
4020 if (!it) {
4021 tracepoint(librados, rados_getxattrs_exit, -ENOMEM, NULL);
4022 return -ENOMEM;
4023 }
4024 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4025 object_t obj(oid);
4026 int ret = ctx->getxattrs(obj, it->attrset);
4027 if (ret) {
4028 delete it;
4029 tracepoint(librados, rados_getxattrs_exit, ret, NULL);
4030 return ret;
4031 }
4032 it->i = it->attrset.begin();
4033
4034 librados::RadosXattrsIter **iret = (librados::RadosXattrsIter**)iter;
4035 *iret = it;
4036 *iter = it;
4037 tracepoint(librados, rados_getxattrs_exit, 0, *iter);
4038 return 0;
4039}
4040
4041extern "C" int rados_getxattrs_next(rados_xattrs_iter_t iter,
4042 const char **name, const char **val, size_t *len)
4043{
4044 tracepoint(librados, rados_getxattrs_next_enter, iter);
4045 librados::RadosXattrsIter *it = static_cast<librados::RadosXattrsIter*>(iter);
4046 if (it->i == it->attrset.end()) {
4047 *name = NULL;
4048 *val = NULL;
4049 *len = 0;
4050 tracepoint(librados, rados_getxattrs_next_exit, 0, NULL, NULL, 0);
4051 return 0;
4052 }
4053 free(it->val);
4054 const std::string &s(it->i->first);
4055 *name = s.c_str();
4056 bufferlist &bl(it->i->second);
4057 size_t bl_len = bl.length();
4058 if (!bl_len) {
4059 // malloc(0) is not guaranteed to return a valid pointer
4060 *val = (char *)NULL;
4061 } else {
4062 it->val = (char*)malloc(bl_len);
4063 if (!it->val) {
4064 tracepoint(librados, rados_getxattrs_next_exit, -ENOMEM, *name, NULL, 0);
4065 return -ENOMEM;
4066 }
4067 memcpy(it->val, bl.c_str(), bl_len);
4068 *val = it->val;
4069 }
4070 *len = bl_len;
4071 ++it->i;
4072 tracepoint(librados, rados_getxattrs_next_exit, 0, *name, *val, *len);
4073 return 0;
4074}
4075
4076extern "C" void rados_getxattrs_end(rados_xattrs_iter_t iter)
4077{
4078 tracepoint(librados, rados_getxattrs_end_enter, iter);
4079 librados::RadosXattrsIter *it = static_cast<librados::RadosXattrsIter*>(iter);
4080 delete it;
4081 tracepoint(librados, rados_getxattrs_end_exit);
4082}
4083
4084extern "C" int rados_setxattr(rados_ioctx_t io, const char *o, const char *name, const char *buf, size_t len)
4085{
4086 tracepoint(librados, rados_setxattr_enter, io, o, name, buf, len);
4087 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4088 object_t oid(o);
4089 bufferlist bl;
4090 bl.append(buf, len);
4091 int retval = ctx->setxattr(oid, name, bl);
4092 tracepoint(librados, rados_setxattr_exit, retval);
4093 return retval;
4094}
4095
4096extern "C" int rados_rmxattr(rados_ioctx_t io, const char *o, const char *name)
4097{
4098 tracepoint(librados, rados_rmxattr_enter, io, o, name);
4099 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4100 object_t oid(o);
4101 int retval = ctx->rmxattr(oid, name);
4102 tracepoint(librados, rados_rmxattr_exit, retval);
4103 return retval;
4104}
4105
4106extern "C" int rados_stat(rados_ioctx_t io, const char *o, uint64_t *psize, time_t *pmtime)
4107{
4108 tracepoint(librados, rados_stat_enter, io, o);
4109 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4110 object_t oid(o);
4111 int retval = ctx->stat(oid, psize, pmtime);
4112 tracepoint(librados, rados_stat_exit, retval, psize, pmtime);
4113 return retval;
4114}
4115
4116extern "C" int rados_tmap_update(rados_ioctx_t io, const char *o, const char *cmdbuf, size_t cmdbuflen)
4117{
4118 tracepoint(librados, rados_tmap_update_enter, io, o, cmdbuf, cmdbuflen);
4119 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4120 object_t oid(o);
4121 bufferlist cmdbl;
4122 cmdbl.append(cmdbuf, cmdbuflen);
4123 int retval = ctx->tmap_update(oid, cmdbl);
4124 tracepoint(librados, rados_tmap_update_exit, retval);
4125 return retval;
4126}
4127
4128extern "C" int rados_tmap_put(rados_ioctx_t io, const char *o, const char *buf, size_t buflen)
4129{
4130 tracepoint(librados, rados_tmap_put_enter, io, o, buf, buflen);
4131 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4132 object_t oid(o);
4133 bufferlist bl;
4134 bl.append(buf, buflen);
4135 int retval = ctx->tmap_put(oid, bl);
4136 tracepoint(librados, rados_tmap_put_exit, retval);
4137 return retval;
4138}
4139
4140extern "C" int rados_tmap_get(rados_ioctx_t io, const char *o, char *buf, size_t buflen)
4141{
4142 tracepoint(librados, rados_tmap_get_enter, io, o, buflen);
4143 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4144 object_t oid(o);
4145 bufferlist bl;
4146 int r = ctx->tmap_get(oid, bl);
4147 if (r < 0) {
4148 tracepoint(librados, rados_tmap_get_exit, r, buf, 0);
4149 return r;
4150 }
4151 if (bl.length() > buflen) {
4152 tracepoint(librados, rados_tmap_get_exit, -ERANGE, buf, 0);
4153 return -ERANGE;
4154 }
4155 bl.copy(0, bl.length(), buf);
4156 int retval = bl.length();
4157 tracepoint(librados, rados_tmap_get_exit, retval, buf, retval);
4158 return retval;
4159}
4160
4161extern "C" int rados_tmap_to_omap(rados_ioctx_t io, const char *o, bool nullok)
4162{
4163 tracepoint(librados, rados_tmap_to_omap_enter, io, o, nullok);
4164 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4165 object_t oid(o);
4166 int retval = ctx->tmap_to_omap(oid, nullok);
4167 tracepoint(librados, rados_tmap_to_omap_exit, retval);
4168 return retval;
4169}
4170
4171extern "C" int rados_exec(rados_ioctx_t io, const char *o, const char *cls, const char *method,
4172 const char *inbuf, size_t in_len, char *buf, size_t out_len)
4173{
4174 tracepoint(librados, rados_exec_enter, io, o, cls, method, inbuf, in_len, out_len);
4175 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4176 object_t oid(o);
4177 bufferlist inbl, outbl;
4178 int ret;
4179 inbl.append(inbuf, in_len);
4180 ret = ctx->exec(oid, cls, method, inbl, outbl);
4181 if (ret >= 0) {
4182 if (outbl.length()) {
4183 if (outbl.length() > out_len) {
4184 tracepoint(librados, rados_exec_exit, -ERANGE, buf, 0);
4185 return -ERANGE;
4186 }
4187 outbl.copy(0, outbl.length(), buf);
4188 ret = outbl.length(); // hrm :/
4189 }
4190 }
4191 tracepoint(librados, rados_exec_exit, ret, buf, ret);
4192 return ret;
4193}
4194
4195extern "C" rados_object_list_cursor rados_object_list_begin(rados_ioctx_t io)
4196{
4197 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4198
4199 hobject_t *result = new hobject_t(ctx->objecter->enumerate_objects_begin());
4200 return (rados_object_list_cursor)result;
4201}
4202
4203extern "C" rados_object_list_cursor rados_object_list_end(rados_ioctx_t io)
4204{
4205 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4206
4207 hobject_t *result = new hobject_t(ctx->objecter->enumerate_objects_end());
4208 return (rados_object_list_cursor)result;
4209}
4210
4211extern "C" int rados_object_list_is_end(
4212 rados_ioctx_t io, rados_object_list_cursor cur)
4213{
4214 hobject_t *hobj = (hobject_t*)cur;
4215 return hobj->is_max();
4216}
4217
4218extern "C" void rados_object_list_cursor_free(
4219 rados_ioctx_t io, rados_object_list_cursor cur)
4220{
4221 hobject_t *hobj = (hobject_t*)cur;
4222 delete hobj;
4223}
4224
4225extern "C" int rados_object_list_cursor_cmp(
4226 rados_ioctx_t io,
4227 rados_object_list_cursor lhs_cur,
4228 rados_object_list_cursor rhs_cur)
4229{
4230 hobject_t *lhs = (hobject_t*)lhs_cur;
4231 hobject_t *rhs = (hobject_t*)rhs_cur;
4232 return cmp(*lhs, *rhs);
4233}
4234
4235extern "C" int rados_object_list(rados_ioctx_t io,
4236 const rados_object_list_cursor start,
4237 const rados_object_list_cursor finish,
4238 const size_t result_item_count,
4239 const char *filter_buf,
4240 const size_t filter_buf_len,
4241 rados_object_list_item *result_items,
4242 rados_object_list_cursor *next)
4243{
4244 assert(next);
4245
4246 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4247
4248 // Zero out items so that they will be safe to free later
4249 memset(result_items, 0, sizeof(rados_object_list_item) * result_item_count);
4250
4251 std::list<librados::ListObjectImpl> result;
4252 hobject_t next_hash;
4253
4254 bufferlist filter_bl;
4255 if (filter_buf != nullptr) {
4256 filter_bl.append(filter_buf, filter_buf_len);
4257 }
4258
4259 C_SaferCond cond;
4260 ctx->objecter->enumerate_objects(
4261 ctx->poolid,
4262 ctx->oloc.nspace,
4263 *((hobject_t*)start),
4264 *((hobject_t*)finish),
4265 result_item_count,
4266 filter_bl,
4267 &result,
4268 &next_hash,
4269 &cond);
4270
4271 hobject_t *next_hobj = (hobject_t*)(*next);
4272 assert(next_hobj);
4273
4274 int r = cond.wait();
4275 if (r < 0) {
4276 *next_hobj = hobject_t::get_max();
4277 return r;
4278 }
4279
4280 assert(result.size() <= result_item_count); // Don't overflow!
4281
4282 int k = 0;
4283 for (std::list<librados::ListObjectImpl>::iterator i = result.begin();
4284 i != result.end(); ++i) {
4285 rados_object_list_item &item = result_items[k++];
4286 do_out_buffer(i->oid, &item.oid, &item.oid_length);
4287 do_out_buffer(i->nspace, &item.nspace, &item.nspace_length);
4288 do_out_buffer(i->locator, &item.locator, &item.locator_length);
4289 }
4290
4291 *next_hobj = next_hash;
4292
4293 return result.size();
4294}
4295
4296extern "C" void rados_object_list_free(
4297 const size_t result_size,
4298 rados_object_list_item *results)
4299{
4300 assert(results);
4301
4302 for (unsigned int i = 0; i < result_size; ++i) {
4303 rados_buffer_free(results[i].oid);
4304 rados_buffer_free(results[i].locator);
4305 rados_buffer_free(results[i].nspace);
4306 }
4307}
4308
4309/* list objects */
4310
4311extern "C" int rados_nobjects_list_open(rados_ioctx_t io, rados_list_ctx_t *listh)
4312{
4313 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4314
4315 tracepoint(librados, rados_nobjects_list_open_enter, io);
4316
4317 Objecter::NListContext *h = new Objecter::NListContext;
4318 h->pool_id = ctx->poolid;
4319 h->pool_snap_seq = ctx->snap_seq;
4320 h->nspace = ctx->oloc.nspace; // After dropping compatibility need nspace
4321 *listh = (void *)new librados::ObjListCtx(ctx, h);
4322 tracepoint(librados, rados_nobjects_list_open_exit, 0, *listh);
4323 return 0;
4324}
4325
4326extern "C" void rados_nobjects_list_close(rados_list_ctx_t h)
4327{
4328 tracepoint(librados, rados_nobjects_list_close_enter, h);
4329 librados::ObjListCtx *lh = (librados::ObjListCtx *)h;
4330 delete lh;
4331 tracepoint(librados, rados_nobjects_list_close_exit);
4332}
4333
4334extern "C" uint32_t rados_nobjects_list_seek(rados_list_ctx_t listctx,
4335 uint32_t pos)
4336{
4337 librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
4338 tracepoint(librados, rados_nobjects_list_seek_enter, listctx, pos);
4339 uint32_t r = lh->ctx->nlist_seek(lh->nlc, pos);
4340 tracepoint(librados, rados_nobjects_list_seek_exit, r);
4341 return r;
4342}
4343
4344extern "C" uint32_t rados_nobjects_list_seek_cursor(rados_list_ctx_t listctx,
4345 rados_object_list_cursor cursor)
4346{
4347 librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
4348
4349 tracepoint(librados, rados_nobjects_list_seek_cursor_enter, listctx);
4350 uint32_t r = lh->ctx->nlist_seek(lh->nlc, cursor);
4351 tracepoint(librados, rados_nobjects_list_seek_cursor_exit, r);
4352 return r;
4353}
4354
4355extern "C" int rados_nobjects_list_get_cursor(rados_list_ctx_t listctx,
4356 rados_object_list_cursor *cursor)
4357{
4358 librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
4359
4360 tracepoint(librados, rados_nobjects_list_get_cursor_enter, listctx);
4361 *cursor = lh->ctx->nlist_get_cursor(lh->nlc);
4362 tracepoint(librados, rados_nobjects_list_get_cursor_exit, 0);
4363 return 0;
4364}
4365
4366extern "C" uint32_t rados_nobjects_list_get_pg_hash_position(
4367 rados_list_ctx_t listctx)
4368{
4369 librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
4370 tracepoint(librados, rados_nobjects_list_get_pg_hash_position_enter, listctx);
4371 uint32_t retval = lh->nlc->get_pg_hash_position();
4372 tracepoint(librados, rados_nobjects_list_get_pg_hash_position_exit, retval);
4373 return retval;
4374}
4375
4376extern "C" int rados_nobjects_list_next(rados_list_ctx_t listctx, const char **entry, const char **key, const char **nspace)
4377{
4378 tracepoint(librados, rados_nobjects_list_next_enter, listctx);
4379 librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
4380 Objecter::NListContext *h = lh->nlc;
4381
4382 // if the list is non-empty, this method has been called before
4383 if (!h->list.empty())
4384 // so let's kill the previously-returned object
4385 h->list.pop_front();
4386
4387 if (h->list.empty()) {
4388 int ret = lh->ctx->nlist(lh->nlc, RADOS_LIST_MAX_ENTRIES);
4389 if (ret < 0) {
4390 tracepoint(librados, rados_nobjects_list_next_exit, ret, NULL, NULL, NULL);
4391 return ret;
4392 }
4393 if (h->list.empty()) {
4394 tracepoint(librados, rados_nobjects_list_next_exit, -ENOENT, NULL, NULL, NULL);
4395 return -ENOENT;
4396 }
4397 }
4398
4399 *entry = h->list.front().oid.c_str();
4400
4401 if (key) {
4402 if (h->list.front().locator.size())
4403 *key = h->list.front().locator.c_str();
4404 else
4405 *key = NULL;
4406 }
4407 if (nspace)
4408 *nspace = h->list.front().nspace.c_str();
4409 tracepoint(librados, rados_nobjects_list_next_exit, 0, *entry, key, nspace);
4410 return 0;
4411}
4412
4413
4414/*
4415 * removed legacy v2 list objects stubs
4416 *
4417 * thse return -ENOTSUP where possible.
4418 */
4419extern "C" int rados_objects_list_open(
4420 rados_ioctx_t io,
4421 rados_list_ctx_t *ctx)
4422{
4423 return -ENOTSUP;
4424}
4425
4426extern "C" uint32_t rados_objects_list_get_pg_hash_position(
4427 rados_list_ctx_t ctx)
4428{
4429 return 0;
4430}
4431
4432extern "C" uint32_t rados_objects_list_seek(
4433 rados_list_ctx_t ctx,
4434 uint32_t pos)
4435{
4436 return 0;
4437}
4438
4439extern "C" int rados_objects_list_next(
4440 rados_list_ctx_t ctx,
4441 const char **entry,
4442 const char **key)
4443{
4444 return -ENOTSUP;
4445}
4446
4447extern "C" void rados_objects_list_close(
4448 rados_list_ctx_t ctx)
4449{
4450}
4451
4452
4453// -------------------------
4454// aio
4455
4456extern "C" int rados_aio_create_completion(void *cb_arg,
4457 rados_callback_t cb_complete,
4458 rados_callback_t cb_safe,
4459 rados_completion_t *pc)
4460{
4461 tracepoint(librados, rados_aio_create_completion_enter, cb_arg, cb_complete, cb_safe);
4462 librados::AioCompletionImpl *c = new librados::AioCompletionImpl;
4463 if (cb_complete)
4464 c->set_complete_callback(cb_arg, cb_complete);
4465 if (cb_safe)
4466 c->set_safe_callback(cb_arg, cb_safe);
4467 *pc = c;
4468 tracepoint(librados, rados_aio_create_completion_exit, 0, *pc);
4469 return 0;
4470}
4471
4472extern "C" int rados_aio_wait_for_complete(rados_completion_t c)
4473{
4474 tracepoint(librados, rados_aio_wait_for_complete_enter, c);
4475 int retval = ((librados::AioCompletionImpl*)c)->wait_for_complete();
4476 tracepoint(librados, rados_aio_wait_for_complete_exit, retval);
4477 return retval;
4478}
4479
4480extern "C" int rados_aio_wait_for_safe(rados_completion_t c)
4481{
4482 tracepoint(librados, rados_aio_wait_for_safe_enter, c);
4483 int retval = ((librados::AioCompletionImpl*)c)->wait_for_safe();
4484 tracepoint(librados, rados_aio_wait_for_safe_exit, retval);
4485 return retval;
4486}
4487
4488extern "C" int rados_aio_is_complete(rados_completion_t c)
4489{
4490 tracepoint(librados, rados_aio_is_complete_enter, c);
4491 int retval = ((librados::AioCompletionImpl*)c)->is_complete();
4492 tracepoint(librados, rados_aio_is_complete_exit, retval);
4493 return retval;
4494}
4495
4496extern "C" int rados_aio_is_safe(rados_completion_t c)
4497{
4498 tracepoint(librados, rados_aio_is_safe_enter, c);
4499 int retval = ((librados::AioCompletionImpl*)c)->is_safe();
4500 tracepoint(librados, rados_aio_is_safe_exit, retval);
4501 return retval;
4502}
4503
4504extern "C" int rados_aio_wait_for_complete_and_cb(rados_completion_t c)
4505{
4506 tracepoint(librados, rados_aio_wait_for_complete_and_cb_enter, c);
4507 int retval = ((librados::AioCompletionImpl*)c)->wait_for_complete_and_cb();
4508 tracepoint(librados, rados_aio_wait_for_complete_and_cb_exit, retval);
4509 return retval;
4510}
4511
4512extern "C" int rados_aio_wait_for_safe_and_cb(rados_completion_t c)
4513{
4514 tracepoint(librados, rados_aio_wait_for_safe_and_cb_enter, c);
4515 int retval = ((librados::AioCompletionImpl*)c)->wait_for_safe_and_cb();
4516 tracepoint(librados, rados_aio_wait_for_safe_and_cb_exit, retval);
4517 return retval;
4518}
4519
4520extern "C" int rados_aio_is_complete_and_cb(rados_completion_t c)
4521{
4522 tracepoint(librados, rados_aio_is_complete_and_cb_enter, c);
4523 int retval = ((librados::AioCompletionImpl*)c)->is_complete_and_cb();
4524 tracepoint(librados, rados_aio_is_complete_and_cb_exit, retval);
4525 return retval;
4526}
4527
4528extern "C" int rados_aio_is_safe_and_cb(rados_completion_t c)
4529{
4530 tracepoint(librados, rados_aio_is_safe_and_cb_enter, c);
4531 int retval = ((librados::AioCompletionImpl*)c)->is_safe_and_cb();
4532 tracepoint(librados, rados_aio_is_safe_and_cb_exit, retval);
4533 return retval;
4534}
4535
4536extern "C" int rados_aio_get_return_value(rados_completion_t c)
4537{
4538 tracepoint(librados, rados_aio_get_return_value_enter, c);
4539 int retval = ((librados::AioCompletionImpl*)c)->get_return_value();
4540 tracepoint(librados, rados_aio_get_return_value_exit, retval);
4541 return retval;
4542}
4543
4544extern "C" uint64_t rados_aio_get_version(rados_completion_t c)
4545{
4546 tracepoint(librados, rados_aio_get_version_enter, c);
4547 uint64_t retval = ((librados::AioCompletionImpl*)c)->get_version();
4548 tracepoint(librados, rados_aio_get_version_exit, retval);
4549 return retval;
4550}
4551
4552extern "C" void rados_aio_release(rados_completion_t c)
4553{
4554 tracepoint(librados, rados_aio_release_enter, c);
4555 ((librados::AioCompletionImpl*)c)->put();
4556 tracepoint(librados, rados_aio_release_exit);
4557}
4558
4559extern "C" int rados_aio_read(rados_ioctx_t io, const char *o,
4560 rados_completion_t completion,
4561 char *buf, size_t len, uint64_t off)
4562{
4563 tracepoint(librados, rados_aio_read_enter, io, o, completion, len, off);
4564 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4565 object_t oid(o);
4566 int retval = ctx->aio_read(oid, (librados::AioCompletionImpl*)completion,
4567 buf, len, off, ctx->snap_seq);
4568 tracepoint(librados, rados_aio_read_exit, retval);
4569 return retval;
4570}
4571
4572#ifdef WITH_BLKIN
4573extern "C" int rados_aio_read_traced(rados_ioctx_t io, const char *o,
4574 rados_completion_t completion,
4575 char *buf, size_t len, uint64_t off,
4576 struct blkin_trace_info *info)
4577{
4578 tracepoint(librados, rados_aio_read_enter, io, o, completion, len, off);
4579 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4580 object_t oid(o);
4581 int retval = ctx->aio_read(oid, (librados::AioCompletionImpl*)completion,
4582 buf, len, off, ctx->snap_seq, info);
4583 tracepoint(librados, rados_aio_read_exit, retval);
4584 return retval;
4585}
4586#endif
4587
4588extern "C" int rados_aio_write(rados_ioctx_t io, const char *o,
4589 rados_completion_t completion,
4590 const char *buf, size_t len, uint64_t off)
4591{
4592 tracepoint(librados, rados_aio_write_enter, io, o, completion, buf, len, off);
4593 if (len > UINT_MAX/2)
4594 return -E2BIG;
4595 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4596 object_t oid(o);
4597 bufferlist bl;
4598 bl.append(buf, len);
4599 int retval = ctx->aio_write(oid, (librados::AioCompletionImpl*)completion,
4600 bl, len, off);
4601 tracepoint(librados, rados_aio_write_exit, retval);
4602 return retval;
4603}
4604
4605#ifdef WITH_BLKIN
4606extern "C" int rados_aio_write_traced(rados_ioctx_t io, const char *o,
4607 rados_completion_t completion,
4608 const char *buf, size_t len, uint64_t off,
4609 struct blkin_trace_info *info)
4610{
4611 tracepoint(librados, rados_aio_write_enter, io, o, completion, buf, len, off);
4612 if (len > UINT_MAX/2)
4613 return -E2BIG;
4614 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4615 object_t oid(o);
4616 bufferlist bl;
4617 bl.append(buf, len);
4618 int retval = ctx->aio_write(oid, (librados::AioCompletionImpl*)completion,
4619 bl, len, off, info);
4620 tracepoint(librados, rados_aio_write_exit, retval);
4621 return retval;
4622}
4623#endif
4624
4625extern "C" int rados_aio_append(rados_ioctx_t io, const char *o,
4626 rados_completion_t completion,
4627 const char *buf, size_t len)
4628{
4629 tracepoint(librados, rados_aio_append_enter, io, o, completion, buf, len);
4630 if (len > UINT_MAX/2)
4631 return -E2BIG;
4632 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4633 object_t oid(o);
4634 bufferlist bl;
4635 bl.append(buf, len);
4636 int retval = ctx->aio_append(oid, (librados::AioCompletionImpl*)completion,
4637 bl, len);
4638 tracepoint(librados, rados_aio_append_exit, retval);
4639 return retval;
4640}
4641
4642extern "C" int rados_aio_write_full(rados_ioctx_t io, const char *o,
4643 rados_completion_t completion,
4644 const char *buf, size_t len)
4645{
4646 tracepoint(librados, rados_aio_write_full_enter, io, o, completion, buf, len);
4647 if (len > UINT_MAX/2)
4648 return -E2BIG;
4649 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4650 object_t oid(o);
4651 bufferlist bl;
4652 bl.append(buf, len);
4653 int retval = ctx->aio_write_full(oid, (librados::AioCompletionImpl*)completion, bl);
4654 tracepoint(librados, rados_aio_write_full_exit, retval);
4655 return retval;
4656}
4657
4658extern "C" int rados_aio_writesame(rados_ioctx_t io, const char *o,
4659 rados_completion_t completion,
4660 const char *buf, size_t data_len,
4661 size_t write_len, uint64_t off)
4662{
4663 tracepoint(librados, rados_aio_writesame_enter, io, o, completion, buf,
4664 data_len, write_len, off);
4665 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4666 object_t oid(o);
4667 bufferlist bl;
4668 bl.append(buf, data_len);
4669 int retval = ctx->aio_writesame(o, (librados::AioCompletionImpl*)completion,
4670 bl, write_len, off);
4671 tracepoint(librados, rados_aio_writesame_exit, retval);
4672 return retval;
4673}
4674
4675extern "C" int rados_aio_remove(rados_ioctx_t io, const char *o,
4676 rados_completion_t completion)
4677{
4678 tracepoint(librados, rados_aio_remove_enter, io, o, completion);
4679 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4680 object_t oid(o);
4681 int retval = ctx->aio_remove(oid, (librados::AioCompletionImpl*)completion);
4682 tracepoint(librados, rados_aio_remove_exit, retval);
4683 return retval;
4684}
4685
4686extern "C" int rados_aio_flush_async(rados_ioctx_t io,
4687 rados_completion_t completion)
4688{
4689 tracepoint(librados, rados_aio_flush_async_enter, io, completion);
4690 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4691 ctx->flush_aio_writes_async((librados::AioCompletionImpl*)completion);
4692 tracepoint(librados, rados_aio_flush_async_exit, 0);
4693 return 0;
4694}
4695
4696extern "C" int rados_aio_flush(rados_ioctx_t io)
4697{
4698 tracepoint(librados, rados_aio_flush_enter, io);
4699 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4700 ctx->flush_aio_writes();
4701 tracepoint(librados, rados_aio_flush_exit, 0);
4702 return 0;
4703}
4704
4705struct AioGetxattrData {
4706 AioGetxattrData(char* buf, rados_completion_t c, size_t l) :
4707 user_buf(buf), len(l), user_completion((librados::AioCompletionImpl*)c) {}
4708 bufferlist bl;
4709 char* user_buf;
4710 size_t len;
4711 struct librados::C_AioCompleteAndSafe user_completion;
4712};
4713
4714static void rados_aio_getxattr_complete(rados_completion_t c, void *arg) {
4715 AioGetxattrData *cdata = reinterpret_cast<AioGetxattrData*>(arg);
4716 int rc = rados_aio_get_return_value(c);
4717 if (rc >= 0) {
4718 if (cdata->bl.length() > cdata->len) {
4719 rc = -ERANGE;
4720 } else {
4721 if (!cdata->bl.is_provided_buffer(cdata->user_buf))
4722 cdata->bl.copy(0, cdata->bl.length(), cdata->user_buf);
4723 rc = cdata->bl.length();
4724 }
4725 }
4726 cdata->user_completion.finish(rc);
4727 delete cdata;
4728}
4729
4730extern "C" int rados_aio_getxattr(rados_ioctx_t io, const char *o,
4731 rados_completion_t completion,
4732 const char *name, char *buf, size_t len)
4733{
4734 tracepoint(librados, rados_aio_getxattr_enter, io, o, completion, name, len);
4735 // create data object to be passed to async callback
4736 AioGetxattrData *cdata = new AioGetxattrData(buf, completion, len);
4737 if (!cdata) {
4738 tracepoint(librados, rados_aio_getxattr_exit, -ENOMEM, NULL, 0);
4739 return -ENOMEM;
4740 }
4741 cdata->bl.push_back(buffer::create_static(len, buf));
4742 // create completion callback
4743 librados::AioCompletionImpl *c = new librados::AioCompletionImpl;
4744 c->set_complete_callback(cdata, rados_aio_getxattr_complete);
4745 // call async getxattr of IoCtx
4746 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4747 object_t oid(o);
4748 int ret = ctx->aio_getxattr(oid, c, name, cdata->bl);
4749 tracepoint(librados, rados_aio_getxattr_exit, ret, buf, ret);
4750 return ret;
4751}
4752
4753namespace {
4754struct AioGetxattrsData {
4755 AioGetxattrsData(rados_completion_t c, rados_xattrs_iter_t *_iter) :
4756 iter(_iter), user_completion((librados::AioCompletionImpl*)c) {
4757 it = new librados::RadosXattrsIter();
4758 }
4759 ~AioGetxattrsData() {
4760 if (it) delete it;
4761 }
4762 librados::RadosXattrsIter *it;
4763 rados_xattrs_iter_t *iter;
4764 struct librados::C_AioCompleteAndSafe user_completion;
4765};
4766}
4767
4768static void rados_aio_getxattrs_complete(rados_completion_t c, void *arg) {
4769 AioGetxattrsData *cdata = reinterpret_cast<AioGetxattrsData*>(arg);
4770 int rc = rados_aio_get_return_value(c);
4771 if (rc) {
4772 cdata->user_completion.finish(rc);
4773 } else {
4774 cdata->it->i = cdata->it->attrset.begin();
4775 *cdata->iter = cdata->it;
4776 cdata->it = 0;
4777 cdata->user_completion.finish(0);
4778 }
4779 delete cdata;
4780}
4781
4782extern "C" int rados_aio_getxattrs(rados_ioctx_t io, const char *oid,
4783 rados_completion_t completion,
4784 rados_xattrs_iter_t *iter)
4785{
4786 tracepoint(librados, rados_aio_getxattrs_enter, io, oid, completion);
4787 // create data object to be passed to async callback
4788 AioGetxattrsData *cdata = new AioGetxattrsData(completion, iter);
4789 if (!cdata) {
4790 tracepoint(librados, rados_getxattrs_exit, -ENOMEM, NULL);
4791 return -ENOMEM;
4792 }
4793 // create completion callback
4794 librados::AioCompletionImpl *c = new librados::AioCompletionImpl;
4795 c->set_complete_callback(cdata, rados_aio_getxattrs_complete);
4796 // call async getxattrs of IoCtx
4797 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4798 object_t obj(oid);
4799 int ret = ctx->aio_getxattrs(obj, c, cdata->it->attrset);
4800 tracepoint(librados, rados_aio_getxattrs_exit, ret, cdata->it);
4801 return ret;
4802}
4803
4804extern "C" int rados_aio_setxattr(rados_ioctx_t io, const char *o,
4805 rados_completion_t completion,
4806 const char *name, const char *buf, size_t len)
4807{
4808 tracepoint(librados, rados_aio_setxattr_enter, io, o, completion, name, buf, len);
4809 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4810 object_t oid(o);
4811 bufferlist bl;
4812 bl.append(buf, len);
4813 int retval = ctx->aio_setxattr(oid, (librados::AioCompletionImpl*)completion, name, bl);
4814 tracepoint(librados, rados_aio_setxattr_exit, retval);
4815 return retval;
4816}
4817
4818extern "C" int rados_aio_rmxattr(rados_ioctx_t io, const char *o,
4819 rados_completion_t completion,
4820 const char *name)
4821{
4822 tracepoint(librados, rados_aio_rmxattr_enter, io, o, completion, name);
4823 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4824 object_t oid(o);
4825 int retval = ctx->aio_rmxattr(oid, (librados::AioCompletionImpl*)completion, name);
4826 tracepoint(librados, rados_aio_rmxattr_exit, retval);
4827 return retval;
4828}
4829
4830extern "C" int rados_aio_stat(rados_ioctx_t io, const char *o,
4831 rados_completion_t completion,
4832 uint64_t *psize, time_t *pmtime)
4833{
4834 tracepoint(librados, rados_aio_stat_enter, io, o, completion);
4835 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4836 object_t oid(o);
4837 int retval = ctx->aio_stat(oid, (librados::AioCompletionImpl*)completion,
4838 psize, pmtime);
4839 tracepoint(librados, rados_aio_stat_exit, retval);
4840 return retval;
4841}
4842
4843extern "C" int rados_aio_cmpext(rados_ioctx_t io, const char *o,
4844 rados_completion_t completion, const char *cmp_buf,
4845 size_t cmp_len, uint64_t off)
4846{
4847 tracepoint(librados, rados_aio_cmpext_enter, io, o, completion, cmp_buf,
4848 cmp_len, off);
4849 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4850 object_t oid(o);
4851 int retval = ctx->aio_cmpext(oid, (librados::AioCompletionImpl*)completion,
4852 cmp_buf, cmp_len, off);
4853 tracepoint(librados, rados_aio_cmpext_exit, retval);
4854 return retval;
4855}
4856
4857extern "C" int rados_aio_cancel(rados_ioctx_t io, rados_completion_t completion)
4858{
4859 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4860 return ctx->aio_cancel((librados::AioCompletionImpl*)completion);
4861}
4862
4863extern "C" int rados_aio_exec(rados_ioctx_t io, const char *o,
4864 rados_completion_t completion,
4865 const char *cls, const char *method,
4866 const char *inbuf, size_t in_len,
4867 char *buf, size_t out_len)
4868{
4869 tracepoint(librados, rados_aio_exec_enter, io, o, completion);
4870 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4871 object_t oid(o);
4872 bufferlist inbl;
4873 inbl.append(inbuf, in_len);
4874 int retval = ctx->aio_exec(oid, (librados::AioCompletionImpl*)completion,
4875 cls, method, inbl, buf, out_len);
4876 tracepoint(librados, rados_aio_exec_exit, retval);
4877 return retval;
4878}
4879
4880struct C_WatchCB : public librados::WatchCtx {
4881 rados_watchcb_t wcb;
4882 void *arg;
4883 C_WatchCB(rados_watchcb_t _wcb, void *_arg) : wcb(_wcb), arg(_arg) {}
4884 void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) override {
4885 wcb(opcode, ver, arg);
4886 }
4887};
4888
4889extern "C" int rados_watch(rados_ioctx_t io, const char *o, uint64_t ver,
4890 uint64_t *handle,
4891 rados_watchcb_t watchcb, void *arg)
4892{
4893 tracepoint(librados, rados_watch_enter, io, o, ver, watchcb, arg);
4894 uint64_t *cookie = handle;
4895 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4896 object_t oid(o);
4897 C_WatchCB *wc = new C_WatchCB(watchcb, arg);
4898 int retval = ctx->watch(oid, cookie, wc, NULL, true);
4899 tracepoint(librados, rados_watch_exit, retval, *handle);
4900 return retval;
4901}
4902
4903struct C_WatchCB2 : public librados::WatchCtx2 {
4904 rados_watchcb2_t wcb;
4905 rados_watcherrcb_t errcb;
4906 void *arg;
4907 C_WatchCB2(rados_watchcb2_t _wcb,
4908 rados_watcherrcb_t _errcb,
4909 void *_arg) : wcb(_wcb), errcb(_errcb), arg(_arg) {}
4910 void handle_notify(uint64_t notify_id,
4911 uint64_t cookie,
4912 uint64_t notifier_gid,
4913 bufferlist& bl) override {
4914 wcb(arg, notify_id, cookie, notifier_gid, bl.c_str(), bl.length());
4915 }
4916 void handle_error(uint64_t cookie, int err) override {
4917 if (errcb)
4918 errcb(arg, cookie, err);
4919 }
4920};
4921
4922extern "C" int rados_watch2(rados_ioctx_t io, const char *o, uint64_t *handle,
4923 rados_watchcb2_t watchcb,
4924 rados_watcherrcb_t watcherrcb,
4925 void *arg) {
4926 return rados_watch3(io, o, handle, watchcb, watcherrcb, 0, arg);
4927}
4928
4929extern "C" int rados_watch3(rados_ioctx_t io, const char *o, uint64_t *handle,
4930 rados_watchcb2_t watchcb,
4931 rados_watcherrcb_t watcherrcb,
4932 uint32_t timeout,
4933 void *arg)
4934{
4935 tracepoint(librados, rados_watch3_enter, io, o, handle, watchcb, timeout, arg);
4936 int ret;
4937 if (!watchcb || !o || !handle) {
4938 ret = -EINVAL;
4939 } else {
4940 uint64_t *cookie = handle;
4941 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4942 object_t oid(o);
4943 C_WatchCB2 *wc = new C_WatchCB2(watchcb, watcherrcb, arg);
4944 ret = ctx->watch(oid, cookie, NULL, wc, timeout, true);
4945 }
4946 tracepoint(librados, rados_watch3_exit, ret, handle ? *handle : 0);
4947 return ret;
4948}
4949
4950extern "C" int rados_aio_watch(rados_ioctx_t io, const char *o,
4951 rados_completion_t completion,
4952 uint64_t *handle,
4953 rados_watchcb2_t watchcb,
4954 rados_watcherrcb_t watcherrcb, void *arg) {
4955 return rados_aio_watch2(io, o, completion, handle, watchcb, watcherrcb, 0, arg);
4956}
4957
4958extern "C" int rados_aio_watch2(rados_ioctx_t io, const char *o,
4959 rados_completion_t completion,
4960 uint64_t *handle,
4961 rados_watchcb2_t watchcb,
4962 rados_watcherrcb_t watcherrcb,
4963 uint32_t timeout, void *arg)
4964{
4965 tracepoint(librados, rados_aio_watch2_enter, io, o, completion, handle, watchcb, timeout, arg);
4966 int ret;
4967 if (!completion || !watchcb || !o || !handle) {
4968 ret = -EINVAL;
4969 } else {
4970 uint64_t *cookie = handle;
4971 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4972 object_t oid(o);
4973 librados::AioCompletionImpl *c =
4974 reinterpret_cast<librados::AioCompletionImpl*>(completion);
4975 C_WatchCB2 *wc = new C_WatchCB2(watchcb, watcherrcb, arg);
4976 ret = ctx->aio_watch(oid, c, cookie, NULL, wc, timeout, true);
4977 }
4978 tracepoint(librados, rados_aio_watch2_exit, ret, handle ? *handle : 0);
4979 return ret;
4980}
4981
4982
4983extern "C" int rados_unwatch(rados_ioctx_t io, const char *o, uint64_t handle)
4984{
4985 tracepoint(librados, rados_unwatch_enter, io, o, handle);
4986 uint64_t cookie = handle;
4987 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4988 int retval = ctx->unwatch(cookie);
4989 tracepoint(librados, rados_unwatch_exit, retval);
4990 return retval;
4991}
4992
4993extern "C" int rados_unwatch2(rados_ioctx_t io, uint64_t handle)
4994{
4995 tracepoint(librados, rados_unwatch2_enter, io, handle);
4996 uint64_t cookie = handle;
4997 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
4998 int retval = ctx->unwatch(cookie);
4999 tracepoint(librados, rados_unwatch2_exit, retval);
5000 return retval;
5001}
5002
5003extern "C" int rados_aio_unwatch(rados_ioctx_t io, uint64_t handle,
5004 rados_completion_t completion)
5005{
5006 tracepoint(librados, rados_aio_unwatch_enter, io, handle, completion);
5007 uint64_t cookie = handle;
5008 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5009 librados::AioCompletionImpl *c =
5010 reinterpret_cast<librados::AioCompletionImpl*>(completion);
5011 int retval = ctx->aio_unwatch(cookie, c);
5012 tracepoint(librados, rados_aio_unwatch_exit, retval);
5013 return retval;
5014}
5015
5016extern "C" int rados_watch_check(rados_ioctx_t io, uint64_t handle)
5017{
5018 tracepoint(librados, rados_watch_check_enter, io, handle);
5019 uint64_t cookie = handle;
5020 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5021 int retval = ctx->watch_check(cookie);
5022 tracepoint(librados, rados_watch_check_exit, retval);
5023 return retval;
5024}
5025
5026extern "C" int rados_notify(rados_ioctx_t io, const char *o,
5027 uint64_t ver, const char *buf, int buf_len)
5028{
5029 tracepoint(librados, rados_notify_enter, io, o, ver, buf, buf_len);
5030 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5031 object_t oid(o);
5032 bufferlist bl;
5033 if (buf) {
5034 bufferptr p = buffer::create(buf_len);
5035 memcpy(p.c_str(), buf, buf_len);
5036 bl.push_back(p);
5037 }
5038 int retval = ctx->notify(oid, bl, 0, NULL, NULL, NULL);
5039 tracepoint(librados, rados_notify_exit, retval);
5040 return retval;
5041}
5042
5043extern "C" int rados_notify2(rados_ioctx_t io, const char *o,
5044 const char *buf, int buf_len,
5045 uint64_t timeout_ms,
5046 char **reply_buffer,
5047 size_t *reply_buffer_len)
5048{
5049 tracepoint(librados, rados_notify2_enter, io, o, buf, buf_len, timeout_ms);
5050 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5051 object_t oid(o);
5052 bufferlist bl;
5053 if (buf) {
5054 bufferptr p = buffer::create(buf_len);
5055 memcpy(p.c_str(), buf, buf_len);
5056 bl.push_back(p);
5057 }
5058 int ret = ctx->notify(oid, bl, timeout_ms, NULL, reply_buffer, reply_buffer_len);
5059 tracepoint(librados, rados_notify2_exit, ret);
5060 return ret;
5061}
5062
5063extern "C" int rados_aio_notify(rados_ioctx_t io, const char *o,
5064 rados_completion_t completion,
5065 const char *buf, int buf_len,
5066 uint64_t timeout_ms, char **reply_buffer,
5067 size_t *reply_buffer_len)
5068{
5069 tracepoint(librados, rados_aio_notify_enter, io, o, completion, buf, buf_len,
5070 timeout_ms);
5071 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5072 object_t oid(o);
5073 bufferlist bl;
5074 if (buf) {
5075 bl.push_back(buffer::copy(buf, buf_len));
5076 }
5077 librados::AioCompletionImpl *c =
5078 reinterpret_cast<librados::AioCompletionImpl*>(completion);
5079 int ret = ctx->aio_notify(oid, c, bl, timeout_ms, NULL, reply_buffer,
5080 reply_buffer_len);
5081 tracepoint(librados, rados_aio_notify_exit, ret);
5082 return ret;
5083}
5084
5085extern "C" int rados_notify_ack(rados_ioctx_t io, const char *o,
5086 uint64_t notify_id, uint64_t handle,
5087 const char *buf, int buf_len)
5088{
5089 tracepoint(librados, rados_notify_ack_enter, io, o, notify_id, handle, buf, buf_len);
5090 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5091 object_t oid(o);
5092 bufferlist bl;
5093 if (buf) {
5094 bufferptr p = buffer::create(buf_len);
5095 memcpy(p.c_str(), buf, buf_len);
5096 bl.push_back(p);
5097 }
5098 ctx->notify_ack(oid, notify_id, handle, bl);
5099 tracepoint(librados, rados_notify_ack_exit, 0);
5100 return 0;
5101}
5102
5103extern "C" int rados_watch_flush(rados_t cluster)
5104{
5105 tracepoint(librados, rados_watch_flush_enter, cluster);
5106 librados::RadosClient *client = (librados::RadosClient *)cluster;
5107 int retval = client->watch_flush();
5108 tracepoint(librados, rados_watch_flush_exit, retval);
5109 return retval;
5110}
5111
5112extern "C" int rados_aio_watch_flush(rados_t cluster, rados_completion_t completion)
5113{
5114 tracepoint(librados, rados_aio_watch_flush_enter, cluster, completion);
5115 librados::RadosClient *client = (librados::RadosClient *)cluster;
5116 librados::AioCompletionImpl *c = (librados::AioCompletionImpl*)completion;
5117 int retval = client->async_watch_flush(c);
5118 tracepoint(librados, rados_aio_watch_flush_exit, retval);
5119 return retval;
5120}
5121
5122extern "C" int rados_set_alloc_hint(rados_ioctx_t io, const char *o,
5123 uint64_t expected_object_size,
5124 uint64_t expected_write_size)
5125{
5126 tracepoint(librados, rados_set_alloc_hint_enter, io, o, expected_object_size, expected_write_size);
5127 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5128 object_t oid(o);
5129 int retval = ctx->set_alloc_hint(oid, expected_object_size,
5130 expected_write_size, 0);
5131 tracepoint(librados, rados_set_alloc_hint_exit, retval);
5132 return retval;
5133}
5134
5135extern "C" int rados_set_alloc_hint2(rados_ioctx_t io, const char *o,
5136 uint64_t expected_object_size,
5137 uint64_t expected_write_size,
5138 uint32_t flags)
5139{
5140 tracepoint(librados, rados_set_alloc_hint2_enter, io, o, expected_object_size, expected_write_size, flags);
5141 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5142 object_t oid(o);
5143 int retval = ctx->set_alloc_hint(oid, expected_object_size,
5144 expected_write_size, flags);
5145 tracepoint(librados, rados_set_alloc_hint2_exit, retval);
5146 return retval;
5147}
5148
5149extern "C" int rados_lock_exclusive(rados_ioctx_t io, const char * o,
5150 const char * name, const char * cookie,
5151 const char * desc, struct timeval * duration,
5152 uint8_t flags)
5153{
5154 tracepoint(librados, rados_lock_exclusive_enter, io, o, name, cookie, desc, duration, flags);
5155 librados::IoCtx ctx;
5156 librados::IoCtx::from_rados_ioctx_t(io, ctx);
5157
5158 int retval = ctx.lock_exclusive(o, name, cookie, desc, duration, flags);
5159 tracepoint(librados, rados_lock_exclusive_exit, retval);
5160 return retval;
5161}
5162
5163extern "C" int rados_lock_shared(rados_ioctx_t io, const char * o,
5164 const char * name, const char * cookie,
5165 const char * tag, const char * desc,
5166 struct timeval * duration, uint8_t flags)
5167{
5168 tracepoint(librados, rados_lock_shared_enter, io, o, name, cookie, tag, desc, duration, flags);
5169 librados::IoCtx ctx;
5170 librados::IoCtx::from_rados_ioctx_t(io, ctx);
5171
5172 int retval = ctx.lock_shared(o, name, cookie, tag, desc, duration, flags);
5173 tracepoint(librados, rados_lock_shared_exit, retval);
5174 return retval;
5175}
5176extern "C" int rados_unlock(rados_ioctx_t io, const char *o, const char *name,
5177 const char *cookie)
5178{
5179 tracepoint(librados, rados_unlock_enter, io, o, name, cookie);
5180 librados::IoCtx ctx;
5181 librados::IoCtx::from_rados_ioctx_t(io, ctx);
5182
5183 int retval = ctx.unlock(o, name, cookie);
5184 tracepoint(librados, rados_unlock_exit, retval);
5185 return retval;
5186}
5187
5188extern "C" int rados_aio_unlock(rados_ioctx_t io, const char *o, const char *name,
5189 const char *cookie, rados_completion_t completion)
5190{
5191 tracepoint(librados, rados_aio_unlock_enter, io, o, name, cookie, completion);
5192 librados::IoCtx ctx;
5193 librados::IoCtx::from_rados_ioctx_t(io, ctx);
5194 librados::AioCompletionImpl *comp = (librados::AioCompletionImpl*)completion;
5195 librados::AioCompletion c(comp);
5196 int retval = ctx.aio_unlock(o, name, cookie, &c);
5197 tracepoint(librados, rados_aio_unlock_exit, retval);
5198 return retval;
5199}
5200
5201extern "C" ssize_t rados_list_lockers(rados_ioctx_t io, const char *o,
5202 const char *name, int *exclusive,
5203 char *tag, size_t *tag_len,
5204 char *clients, size_t *clients_len,
5205 char *cookies, size_t *cookies_len,
5206 char *addrs, size_t *addrs_len)
5207{
5208 tracepoint(librados, rados_list_lockers_enter, io, o, name, *tag_len, *clients_len, *cookies_len, *addrs_len);
5209 librados::IoCtx ctx;
5210 librados::IoCtx::from_rados_ioctx_t(io, ctx);
5211 std::string name_str = name;
5212 std::string oid = o;
5213 std::string tag_str;
5214 int tmp_exclusive;
5215 std::list<librados::locker_t> lockers;
5216 int r = ctx.list_lockers(oid, name_str, &tmp_exclusive, &tag_str, &lockers);
5217 if (r < 0) {
5218 tracepoint(librados, rados_list_lockers_exit, r, *exclusive, "", *tag_len, *clients_len, *cookies_len, *addrs_len);
5219 return r;
5220 }
5221
5222 size_t clients_total = 0;
5223 size_t cookies_total = 0;
5224 size_t addrs_total = 0;
5225 list<librados::locker_t>::const_iterator it;
5226 for (it = lockers.begin(); it != lockers.end(); ++it) {
5227 clients_total += it->client.length() + 1;
5228 cookies_total += it->cookie.length() + 1;
5229 addrs_total += it->address.length() + 1;
5230 }
5231
5232 bool too_short = ((clients_total > *clients_len) ||
5233 (cookies_total > *cookies_len) ||
5234 (addrs_total > *addrs_len) ||
5235 (tag_str.length() + 1 > *tag_len));
5236 *clients_len = clients_total;
5237 *cookies_len = cookies_total;
5238 *addrs_len = addrs_total;
5239 *tag_len = tag_str.length() + 1;
5240 if (too_short) {
5241 tracepoint(librados, rados_list_lockers_exit, -ERANGE, *exclusive, "", *tag_len, *clients_len, *cookies_len, *addrs_len);
5242 return -ERANGE;
5243 }
5244
5245 strcpy(tag, tag_str.c_str());
5246 char *clients_p = clients;
5247 char *cookies_p = cookies;
5248 char *addrs_p = addrs;
5249 for (it = lockers.begin(); it != lockers.end(); ++it) {
5250 strcpy(clients_p, it->client.c_str());
5251 strcpy(cookies_p, it->cookie.c_str());
5252 strcpy(addrs_p, it->address.c_str());
5253 tracepoint(librados, rados_list_lockers_locker, clients_p, cookies_p, addrs_p);
5254 clients_p += it->client.length() + 1;
5255 cookies_p += it->cookie.length() + 1;
5256 addrs_p += it->address.length() + 1;
5257 }
5258 if (tmp_exclusive)
5259 *exclusive = 1;
5260 else
5261 *exclusive = 0;
5262
5263 int retval = lockers.size();
5264 tracepoint(librados, rados_list_lockers_exit, retval, *exclusive, tag, *tag_len, *clients_len, *cookies_len, *addrs_len);
5265 return retval;
5266}
5267
5268extern "C" int rados_break_lock(rados_ioctx_t io, const char *o,
5269 const char *name, const char *client,
5270 const char *cookie)
5271{
5272 tracepoint(librados, rados_break_lock_enter, io, o, name, client, cookie);
5273 librados::IoCtx ctx;
5274 librados::IoCtx::from_rados_ioctx_t(io, ctx);
5275
5276 int retval = ctx.break_lock(o, name, client, cookie);
5277 tracepoint(librados, rados_break_lock_exit, retval);
5278 return retval;
5279}
5280
5281extern "C" rados_write_op_t rados_create_write_op()
5282{
5283 tracepoint(librados, rados_create_write_op_enter);
5284 rados_write_op_t retval = new (std::nothrow)::ObjectOperation;
5285 tracepoint(librados, rados_create_write_op_exit, retval);
5286 return retval;
5287}
5288
5289extern "C" void rados_release_write_op(rados_write_op_t write_op)
5290{
5291 tracepoint(librados, rados_release_write_op_enter, write_op);
5292 delete (::ObjectOperation*)write_op;
5293 tracepoint(librados, rados_release_write_op_exit);
5294}
5295
5296extern "C" void rados_write_op_set_flags(rados_write_op_t write_op, int flags)
5297{
5298 tracepoint(librados, rados_write_op_set_flags_enter, write_op, flags);
5299 set_op_flags((::ObjectOperation *)write_op, flags);
5300 tracepoint(librados, rados_write_op_set_flags_exit);
5301}
5302
5303extern "C" void rados_write_op_assert_version(rados_write_op_t write_op, uint64_t ver)
5304{
5305 tracepoint(librados, rados_write_op_assert_version_enter, write_op, ver);
5306 ((::ObjectOperation *)write_op)->assert_version(ver);
5307 tracepoint(librados, rados_write_op_assert_version_exit);
5308}
5309
5310extern "C" void rados_write_op_assert_exists(rados_write_op_t write_op)
5311{
5312 tracepoint(librados, rados_write_op_assert_exists_enter, write_op);
5313 ((::ObjectOperation *)write_op)->stat(NULL, (ceph::real_time *)NULL, NULL);
5314 tracepoint(librados, rados_write_op_assert_exists_exit);
5315}
5316
5317extern "C" void rados_write_op_cmpext(rados_write_op_t write_op,
5318 const char *cmp_buf,
5319 size_t cmp_len,
5320 uint64_t off,
5321 int *prval)
5322{
5323 tracepoint(librados, rados_write_op_cmpext_enter, write_op, cmp_buf,
5324 cmp_len, off, prval);
5325 ((::ObjectOperation *)write_op)->cmpext(off, cmp_len, cmp_buf, prval);
5326 tracepoint(librados, rados_write_op_cmpext_exit);
5327}
5328
5329extern "C" void rados_write_op_cmpxattr(rados_write_op_t write_op,
5330 const char *name,
5331 uint8_t comparison_operator,
5332 const char *value,
5333 size_t value_len)
5334{
5335 tracepoint(librados, rados_write_op_cmpxattr_enter, write_op, name, comparison_operator, value, value_len);
5336 bufferlist bl;
5337 bl.append(value, value_len);
5338 ((::ObjectOperation *)write_op)->cmpxattr(name,
5339 comparison_operator,
5340 CEPH_OSD_CMPXATTR_MODE_STRING,
5341 bl);
5342 tracepoint(librados, rados_write_op_cmpxattr_exit);
5343}
5344
5345static void rados_c_omap_cmp(ObjectOperation *op,
5346 const char *key,
5347 uint8_t comparison_operator,
5348 const char *val,
5349 size_t val_len,
5350 int *prval)
5351{
5352 bufferlist bl;
5353 bl.append(val, val_len);
5354 std::map<std::string, pair<bufferlist, int> > assertions;
5355 assertions[key] = std::make_pair(bl, comparison_operator);
5356 op->omap_cmp(assertions, prval);
5357}
5358
5359extern "C" void rados_write_op_omap_cmp(rados_write_op_t write_op,
5360 const char *key,
5361 uint8_t comparison_operator,
5362 const char *val,
5363 size_t val_len,
5364 int *prval)
5365{
5366 tracepoint(librados, rados_write_op_omap_cmp_enter, write_op, key, comparison_operator, val, val_len, prval);
5367 rados_c_omap_cmp((::ObjectOperation *)write_op, key, comparison_operator,
5368 val, val_len, prval);
5369 tracepoint(librados, rados_write_op_omap_cmp_exit);
5370}
5371
5372extern "C" void rados_write_op_setxattr(rados_write_op_t write_op,
5373 const char *name,
5374 const char *value,
5375 size_t value_len)
5376{
5377 tracepoint(librados, rados_write_op_setxattr_enter, write_op, name, value, value_len);
5378 bufferlist bl;
5379 bl.append(value, value_len);
5380 ((::ObjectOperation *)write_op)->setxattr(name, bl);
5381 tracepoint(librados, rados_write_op_setxattr_exit);
5382}
5383
5384extern "C" void rados_write_op_rmxattr(rados_write_op_t write_op,
5385 const char *name)
5386{
5387 tracepoint(librados, rados_write_op_rmxattr_enter, write_op, name);
5388 ((::ObjectOperation *)write_op)->rmxattr(name);
5389 tracepoint(librados, rados_write_op_rmxattr_exit);
5390}
5391
5392extern "C" void rados_write_op_create(rados_write_op_t write_op,
5393 int exclusive,
5394 const char* category) // unused
5395{
5396 tracepoint(librados, rados_write_op_create_enter, write_op, exclusive);
5397 ::ObjectOperation *oo = (::ObjectOperation *) write_op;
5398 oo->create(!!exclusive);
5399 tracepoint(librados, rados_write_op_create_exit);
5400}
5401
5402extern "C" void rados_write_op_write(rados_write_op_t write_op,
5403 const char *buffer,
5404 size_t len,
5405 uint64_t offset)
5406{
5407 tracepoint(librados, rados_write_op_write_enter, write_op, buffer, len, offset);
5408 bufferlist bl;
5409 bl.append(buffer,len);
5410 ((::ObjectOperation *)write_op)->write(offset, bl);
5411 tracepoint(librados, rados_write_op_write_exit);
5412}
5413
5414extern "C" void rados_write_op_write_full(rados_write_op_t write_op,
5415 const char *buffer,
5416 size_t len)
5417{
5418 tracepoint(librados, rados_write_op_write_full_enter, write_op, buffer, len);
5419 bufferlist bl;
5420 bl.append(buffer,len);
5421 ((::ObjectOperation *)write_op)->write_full(bl);
5422 tracepoint(librados, rados_write_op_write_full_exit);
5423}
5424
5425extern "C" void rados_write_op_writesame(rados_write_op_t write_op,
5426 const char *buffer,
5427 size_t data_len,
5428 size_t write_len,
5429 uint64_t offset)
5430{
5431 tracepoint(librados, rados_write_op_writesame_enter, write_op, buffer, data_len, write_len, offset);
5432 bufferlist bl;
5433 bl.append(buffer, data_len);
5434 ((::ObjectOperation *)write_op)->writesame(offset, write_len, bl);
5435 tracepoint(librados, rados_write_op_writesame_exit);
5436}
5437
5438extern "C" void rados_write_op_append(rados_write_op_t write_op,
5439 const char *buffer,
5440 size_t len)
5441{
5442 tracepoint(librados, rados_write_op_append_enter, write_op, buffer, len);
5443 bufferlist bl;
5444 bl.append(buffer,len);
5445 ((::ObjectOperation *)write_op)->append(bl);
5446 tracepoint(librados, rados_write_op_append_exit);
5447}
5448
5449extern "C" void rados_write_op_remove(rados_write_op_t write_op)
5450{
5451 tracepoint(librados, rados_write_op_remove_enter, write_op);
5452 ((::ObjectOperation *)write_op)->remove();
5453 tracepoint(librados, rados_write_op_remove_exit);
5454}
5455
5456extern "C" void rados_write_op_truncate(rados_write_op_t write_op,
5457 uint64_t offset)
5458{
5459 tracepoint(librados, rados_write_op_truncate_enter, write_op, offset);
5460 ((::ObjectOperation *)write_op)->truncate(offset);
5461 tracepoint(librados, rados_write_op_truncate_exit);
5462}
5463
5464extern "C" void rados_write_op_zero(rados_write_op_t write_op,
5465 uint64_t offset,
5466 uint64_t len)
5467{
5468 tracepoint(librados, rados_write_op_zero_enter, write_op, offset, len);
5469 ((::ObjectOperation *)write_op)->zero(offset, len);
5470 tracepoint(librados, rados_write_op_zero_exit);
5471}
5472
5473extern "C" void rados_write_op_exec(rados_write_op_t write_op,
5474 const char *cls,
5475 const char *method,
5476 const char *in_buf,
5477 size_t in_len,
5478 int *prval)
5479{
5480 tracepoint(librados, rados_write_op_exec_enter, write_op, cls, method, in_buf, in_len, prval);
5481 bufferlist inbl;
5482 inbl.append(in_buf, in_len);
5483 ((::ObjectOperation *)write_op)->call(cls, method, inbl, NULL, NULL, prval);
5484 tracepoint(librados, rados_write_op_exec_exit);
5485}
5486
5487extern "C" void rados_write_op_omap_set(rados_write_op_t write_op,
5488 char const* const* keys,
5489 char const* const* vals,
5490 const size_t *lens,
5491 size_t num)
5492{
5493 tracepoint(librados, rados_write_op_omap_set_enter, write_op, num);
5494 std::map<std::string, bufferlist> entries;
5495 for (size_t i = 0; i < num; ++i) {
5496 tracepoint(librados, rados_write_op_omap_set_entry, keys[i], vals[i], lens[i]);
5497 bufferlist bl(lens[i]);
5498 bl.append(vals[i], lens[i]);
5499 entries[keys[i]] = bl;
5500 }
5501 ((::ObjectOperation *)write_op)->omap_set(entries);
5502 tracepoint(librados, rados_write_op_omap_set_exit);
5503}
5504
5505extern "C" void rados_write_op_omap_rm_keys(rados_write_op_t write_op,
5506 char const* const* keys,
5507 size_t keys_len)
5508{
5509 tracepoint(librados, rados_write_op_omap_rm_keys_enter, write_op, keys_len);
5510 for(size_t i = 0; i < keys_len; i++) {
5511 tracepoint(librados, rados_write_op_omap_rm_keys_entry, keys[i]);
5512 }
5513 std::set<std::string> to_remove(keys, keys + keys_len);
5514 ((::ObjectOperation *)write_op)->omap_rm_keys(to_remove);
5515 tracepoint(librados, rados_write_op_omap_rm_keys_exit);
5516}
5517
5518extern "C" void rados_write_op_omap_clear(rados_write_op_t write_op)
5519{
5520 tracepoint(librados, rados_write_op_omap_clear_enter, write_op);
5521 ((::ObjectOperation *)write_op)->omap_clear();
5522 tracepoint(librados, rados_write_op_omap_clear_exit);
5523}
5524
5525extern "C" void rados_write_op_set_alloc_hint(rados_write_op_t write_op,
5526 uint64_t expected_object_size,
5527 uint64_t expected_write_size)
5528{
5529 tracepoint(librados, rados_write_op_set_alloc_hint_enter, write_op, expected_object_size, expected_write_size);
5530 ((::ObjectOperation *)write_op)->set_alloc_hint(expected_object_size,
5531 expected_write_size, 0);
5532 tracepoint(librados, rados_write_op_set_alloc_hint_exit);
5533}
5534
5535extern "C" void rados_write_op_set_alloc_hint2(rados_write_op_t write_op,
5536 uint64_t expected_object_size,
5537 uint64_t expected_write_size,
5538 uint32_t flags)
5539{
5540 tracepoint(librados, rados_write_op_set_alloc_hint2_enter, write_op, expected_object_size, expected_write_size, flags);
5541 ((::ObjectOperation *)write_op)->set_alloc_hint(expected_object_size,
5542 expected_write_size,
5543 flags);
5544 tracepoint(librados, rados_write_op_set_alloc_hint2_exit);
5545}
5546
5547extern "C" int rados_write_op_operate(rados_write_op_t write_op,
5548 rados_ioctx_t io,
5549 const char *oid,
5550 time_t *mtime,
5551 int flags)
5552{
5553 tracepoint(librados, rados_write_op_operate_enter, write_op, io, oid, mtime, flags);
5554 object_t obj(oid);
5555 ::ObjectOperation *oo = (::ObjectOperation *) write_op;
5556 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5557
5558 ceph::real_time *prt = NULL;
5559 ceph::real_time rt;
5560
5561 if (mtime) {
5562 rt = ceph::real_clock::from_time_t(*mtime);
5563 prt = &rt;
5564 }
5565
5566 int retval = ctx->operate(obj, oo, prt, translate_flags(flags));
5567 tracepoint(librados, rados_write_op_operate_exit, retval);
5568 return retval;
5569}
5570
5571extern "C" int rados_write_op_operate2(rados_write_op_t write_op,
5572 rados_ioctx_t io,
5573 const char *oid,
5574 struct timespec *ts,
5575 int flags)
5576{
5577 tracepoint(librados, rados_write_op_operate2_enter, write_op, io, oid, ts, flags);
5578 object_t obj(oid);
5579 ::ObjectOperation *oo = (::ObjectOperation *) write_op;
5580 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5581
5582 ceph::real_time *prt = NULL;
5583 ceph::real_time rt;
5584
5585 if (ts) {
5586 rt = ceph::real_clock::from_timespec(*ts);
5587 prt = &rt;
5588 }
5589
5590 int retval = ctx->operate(obj, oo, prt, translate_flags(flags));
5591 tracepoint(librados, rados_write_op_operate_exit, retval);
5592 return retval;
5593}
5594
5595extern "C" int rados_aio_write_op_operate(rados_write_op_t write_op,
5596 rados_ioctx_t io,
5597 rados_completion_t completion,
5598 const char *oid,
5599 time_t *mtime,
5600 int flags)
5601{
5602 tracepoint(librados, rados_aio_write_op_operate_enter, write_op, io, completion, oid, mtime, flags);
5603 object_t obj(oid);
5604 ::ObjectOperation *oo = (::ObjectOperation *) write_op;
5605 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
5606 librados::AioCompletionImpl *c = (librados::AioCompletionImpl*)completion;
5607 int retval = ctx->aio_operate(obj, oo, c, ctx->snapc, translate_flags(flags));
5608 tracepoint(librados, rados_aio_write_op_operate_exit, retval);
5609 return retval;
5610}
5611
5612extern "C" rados_read_op_t rados_create_read_op()
5613{
5614 tracepoint(librados, rados_create_read_op_enter);
5615 rados_read_op_t retval = new (std::nothrow)::ObjectOperation;
5616 tracepoint(librados, rados_create_read_op_exit, retval);
5617 return retval;
5618}
5619
5620extern "C" void rados_release_read_op(rados_read_op_t read_op)
5621{
5622 tracepoint(librados, rados_release_read_op_enter, read_op);
5623 delete (::ObjectOperation *)read_op;
5624 tracepoint(librados, rados_release_read_op_exit);
5625}
5626
5627extern "C" void rados_read_op_set_flags(rados_read_op_t read_op, int flags)
5628{
5629 tracepoint(librados, rados_read_op_set_flags_enter, read_op, flags);
5630 set_op_flags((::ObjectOperation *)read_op, flags);
5631 tracepoint(librados, rados_read_op_set_flags_exit);
5632}
5633
5634extern "C" void rados_read_op_assert_version(rados_read_op_t read_op, uint64_t ver)
5635{
5636 tracepoint(librados, rados_read_op_assert_version_enter, read_op, ver);
5637 ((::ObjectOperation *)read_op)->assert_version(ver);
5638 tracepoint(librados, rados_read_op_assert_version_exit);
5639}
5640
5641extern "C" void rados_read_op_assert_exists(rados_read_op_t read_op)
5642{
5643 tracepoint(librados, rados_read_op_assert_exists_enter, read_op);
5644 ((::ObjectOperation *)read_op)->stat(NULL, (ceph::real_time *)NULL, NULL);
5645 tracepoint(librados, rados_read_op_assert_exists_exit);
5646}
5647
5648extern "C" void rados_read_op_cmpext(rados_read_op_t read_op,
5649 const char *cmp_buf,
5650 size_t cmp_len,
5651 uint64_t off,
5652 int *prval)
5653{
5654 tracepoint(librados, rados_read_op_cmpext_enter, read_op, cmp_buf,
5655 cmp_len, off, prval);
5656 ((::ObjectOperation *)read_op)->cmpext(off, cmp_len, cmp_buf, prval);
5657 tracepoint(librados, rados_read_op_cmpext_exit);
5658}
5659
5660extern "C" void rados_read_op_cmpxattr(rados_read_op_t read_op,
5661 const char *name,
5662 uint8_t comparison_operator,
5663 const char *value,
5664 size_t value_len)
5665{
5666 tracepoint(librados, rados_read_op_cmpxattr_enter, read_op, name, comparison_operator, value, value_len);
5667 bufferlist bl;
5668 bl.append(value, value_len);
5669 ((::ObjectOperation *)read_op)->cmpxattr(name,
5670 comparison_operator,
5671 CEPH_OSD_CMPXATTR_MODE_STRING,
5672 bl);
5673 tracepoint(librados, rados_read_op_cmpxattr_exit);
5674}
5675
5676extern "C" void rados_read_op_omap_cmp(rados_read_op_t read_op,
5677 const char *key,
5678 uint8_t comparison_operator,
5679 const char *val,
5680 size_t val_len,
5681 int *prval)
5682{
5683 tracepoint(librados, rados_read_op_omap_cmp_enter, read_op, key, comparison_operator, val, val_len, prval);
5684 rados_c_omap_cmp((::ObjectOperation *)read_op, key, comparison_operator,
5685 val, val_len, prval);
5686 tracepoint(librados, rados_read_op_omap_cmp_exit);
5687}
5688
5689extern "C" void rados_read_op_stat(rados_read_op_t read_op,
5690 uint64_t *psize,
5691 time_t *pmtime,
5692 int *prval)
5693{
5694 tracepoint(librados, rados_read_op_stat_enter, read_op, psize, pmtime, prval);
5695 ((::ObjectOperation *)read_op)->stat(psize, pmtime, prval);
5696 tracepoint(librados, rados_read_op_stat_exit);
5697}
5698
5699class C_bl_to_buf : public Context {
5700 char *out_buf;
5701 size_t out_len;
5702 size_t *bytes_read;
5703 int *prval;
5704public:
5705 bufferlist out_bl;
5706 C_bl_to_buf(char *out_buf,
5707 size_t out_len,
5708 size_t *bytes_read,
5709 int *prval) : out_buf(out_buf), out_len(out_len),
5710 bytes_read(bytes_read), prval(prval) {}
5711 void finish(int r) override {
5712 if (out_bl.length() > out_len) {
5713 if (prval)
5714 *prval = -ERANGE;
5715 if (bytes_read)
5716 *bytes_read = 0;
5717 return;
5718 }
5719 if (bytes_read)
5720 *bytes_read = out_bl.length();
5721 if (out_buf && !out_bl.is_provided_buffer(out_buf))
5722 out_bl.copy(0, out_bl.length(), out_buf);
5723 }
5724};
5725
5726extern "C" void rados_read_op_read(rados_read_op_t read_op,
5727 uint64_t offset,
5728 size_t len,
5729 char *buf,
5730 size_t *bytes_read,
5731 int *prval)
5732{
5733 tracepoint(librados, rados_read_op_read_enter, read_op, offset, len, buf, bytes_read, prval);
5734 C_bl_to_buf *ctx = new C_bl_to_buf(buf, len, bytes_read, prval);
5735 ctx->out_bl.push_back(buffer::create_static(len, buf));
5736 ((::ObjectOperation *)read_op)->read(offset, len, &ctx->out_bl, prval, ctx);
5737 tracepoint(librados, rados_read_op_read_exit);
5738}
5739
5740extern "C" void rados_read_op_checksum(rados_read_op_t read_op,
5741 rados_checksum_type_t type,
5742 const char *init_value,
5743 size_t init_value_len,
5744 uint64_t offset, size_t len,
5745 size_t chunk_size, char *pchecksum,
5746 size_t checksum_len, int *prval)
5747{
5748 tracepoint(librados, rados_read_op_checksum_enter, read_op, type, init_value,
5749 init_value_len, offset, len, chunk_size);
5750 bufferlist init_value_bl;
5751 init_value_bl.append(init_value, init_value_len);
5752
5753 C_bl_to_buf *ctx = nullptr;
5754 if (pchecksum != nullptr) {
5755 ctx = new C_bl_to_buf(pchecksum, checksum_len, nullptr, prval);
5756 }
5757 ((::ObjectOperation *)read_op)->checksum(get_checksum_op_type(type),
5758 init_value_bl, offset, len,
5759 chunk_size,
5760 (ctx ? &ctx->out_bl : nullptr),
5761 prval, ctx);
5762 tracepoint(librados, rados_read_op_checksum_exit);
5763}
5764
5765class C_out_buffer : public Context {
5766 char **out_buf;
5767 size_t *out_len;
5768public:
5769 bufferlist out_bl;
5770 C_out_buffer(char **out_buf, size_t *out_len) : out_buf(out_buf),
5771 out_len(out_len) {}
5772 void finish(int r) override {
5773 // ignore r since we don't know the meaning of return values
5774 // from custom class methods
5775 do_out_buffer(out_bl, out_buf, out_len);
5776 }
5777};
5778
5779extern "C" void rados_read_op_exec(rados_read_op_t read_op,
5780 const char *cls,
5781 const char *method,
5782 const char *in_buf,
5783 size_t in_len,
5784 char **out_buf,
5785 size_t *out_len,
5786 int *prval)
5787{
5788 tracepoint(librados, rados_read_op_exec_enter, read_op, cls, method, in_buf, in_len, out_buf, out_len, prval);
5789 bufferlist inbl;
5790 inbl.append(in_buf, in_len);
5791 C_out_buffer *ctx = new C_out_buffer(out_buf, out_len);
5792 ((::ObjectOperation *)read_op)->call(cls, method, inbl, &ctx->out_bl, ctx,
5793 prval);
5794 tracepoint(librados, rados_read_op_exec_exit);
5795}
5796
5797extern "C" void rados_read_op_exec_user_buf(rados_read_op_t read_op,
5798 const char *cls,
5799 const char *method,
5800 const char *in_buf,
5801 size_t in_len,
5802 char *out_buf,
5803 size_t out_len,
5804 size_t *used_len,
5805 int *prval)
5806{
5807 tracepoint(librados, rados_read_op_exec_user_buf_enter, read_op, cls, method, in_buf, in_len, out_buf, out_len, used_len, prval);
5808 C_bl_to_buf *ctx = new C_bl_to_buf(out_buf, out_len, used_len, prval);
5809 bufferlist inbl;
5810 inbl.append(in_buf, in_len);
5811 ((::ObjectOperation *)read_op)->call(cls, method, inbl, &ctx->out_bl, ctx,
5812 prval);
5813 tracepoint(librados, rados_read_op_exec_user_buf_exit);
5814}
5815
5816struct RadosOmapIter {
5817 std::map<std::string, bufferlist> values;
5818 std::map<std::string, bufferlist>::iterator i;
5819};
5820
5821class C_OmapIter : public Context {
5822 RadosOmapIter *iter;
5823public:
5824 explicit C_OmapIter(RadosOmapIter *iter) : iter(iter) {}
5825 void finish(int r) override {
5826 iter->i = iter->values.begin();
5827 }
5828};
5829
5830class C_XattrsIter : public Context {
5831 librados::RadosXattrsIter *iter;
5832public:
5833 explicit C_XattrsIter(librados::RadosXattrsIter *iter) : iter(iter) {}
5834 void finish(int r) override {
5835 iter->i = iter->attrset.begin();
5836 }
5837};
5838
5839extern "C" void rados_read_op_getxattrs(rados_read_op_t read_op,
5840 rados_xattrs_iter_t *iter,
5841 int *prval)
5842{
5843 tracepoint(librados, rados_read_op_getxattrs_enter, read_op, prval);
5844 librados::RadosXattrsIter *xattrs_iter = new librados::RadosXattrsIter;
5845 ((::ObjectOperation *)read_op)->getxattrs(&xattrs_iter->attrset, prval);
5846 ((::ObjectOperation *)read_op)->add_handler(new C_XattrsIter(xattrs_iter));
5847 *iter = xattrs_iter;
5848 tracepoint(librados, rados_read_op_getxattrs_exit, *iter);
5849}
5850
5851extern "C" void rados_read_op_omap_get_vals(rados_read_op_t read_op,
5852 const char *start_after,
5853 const char *filter_prefix,
5854 uint64_t max_return,
5855 rados_omap_iter_t *iter,
5856 int *prval)
5857{
5858 tracepoint(librados, rados_read_op_omap_get_vals_enter, read_op, start_after, filter_prefix, max_return, prval);
5859 RadosOmapIter *omap_iter = new RadosOmapIter;
5860 const char *start = start_after ? start_after : "";
5861 const char *filter = filter_prefix ? filter_prefix : "";
5862 ((::ObjectOperation *)read_op)->omap_get_vals(
5863 start,
5864 filter,
5865 max_return,
5866 &omap_iter->values,
5867 nullptr,
5868 prval);
5869 ((::ObjectOperation *)read_op)->add_handler(new C_OmapIter(omap_iter));
5870 *iter = omap_iter;
5871 tracepoint(librados, rados_read_op_omap_get_vals_exit, *iter);
5872}
5873
5874extern "C" void rados_read_op_omap_get_vals2(rados_read_op_t read_op,
5875 const char *start_after,
5876 const char *filter_prefix,
5877 uint64_t max_return,
5878 rados_omap_iter_t *iter,
5879 unsigned char *pmore,
5880 int *prval)
5881{
5882 tracepoint(librados, rados_read_op_omap_get_vals_enter, read_op, start_after, filter_prefix, max_return, prval);
5883 RadosOmapIter *omap_iter = new RadosOmapIter;
5884 const char *start = start_after ? start_after : "";
5885 const char *filter = filter_prefix ? filter_prefix : "";
5886 ((::ObjectOperation *)read_op)->omap_get_vals(
5887 start,
5888 filter,
5889 max_return,
5890 &omap_iter->values,
5891 (bool*)pmore,
5892 prval);
5893 ((::ObjectOperation *)read_op)->add_handler(new C_OmapIter(omap_iter));
5894 *iter = omap_iter;
5895 tracepoint(librados, rados_read_op_omap_get_vals_exit, *iter);
5896}
5897
5898struct C_OmapKeysIter : public Context {
5899 RadosOmapIter *iter;
5900 std::set<std::string> keys;
5901 explicit C_OmapKeysIter(RadosOmapIter *iter) : iter(iter) {}
5902 void finish(int r) override {
5903 // map each key to an empty bl
5904 for (std::set<std::string>::const_iterator i = keys.begin();
5905 i != keys.end(); ++i) {
5906 iter->values[*i];
5907 }
5908 iter->i = iter->values.begin();
5909 }
5910};
5911
5912extern "C" void rados_read_op_omap_get_keys(rados_read_op_t read_op,
5913 const char *start_after,
5914 uint64_t max_return,
5915 rados_omap_iter_t *iter,
5916 int *prval)
5917{
5918 tracepoint(librados, rados_read_op_omap_get_keys_enter, read_op, start_after, max_return, prval);
5919 RadosOmapIter *omap_iter = new RadosOmapIter;
5920 C_OmapKeysIter *ctx = new C_OmapKeysIter(omap_iter);
5921 ((::ObjectOperation *)read_op)->omap_get_keys(
5922 start_after ? start_after : "",
5923 max_return, &ctx->keys, nullptr, prval);
5924 ((::ObjectOperation *)read_op)->add_handler(ctx);
5925 *iter = omap_iter;
5926 tracepoint(librados, rados_read_op_omap_get_keys_exit, *iter);
5927}
5928
5929extern "C" void rados_read_op_omap_get_keys2(rados_read_op_t read_op,
5930 const char *start_after,
5931 uint64_t max_return,
5932 rados_omap_iter_t *iter,
5933 unsigned char *pmore,
5934 int *prval)
5935{
5936 tracepoint(librados, rados_read_op_omap_get_keys_enter, read_op, start_after, max_return, prval);
5937 RadosOmapIter *omap_iter = new RadosOmapIter;
5938 C_OmapKeysIter *ctx = new C_OmapKeysIter(omap_iter);
5939 ((::ObjectOperation *)read_op)->omap_get_keys(
5940 start_after ? start_after : "",
5941 max_return, &ctx->keys,
5942 (bool*)pmore, prval);
5943 ((::ObjectOperation *)read_op)->add_handler(ctx);
5944 *iter = omap_iter;
5945 tracepoint(librados, rados_read_op_omap_get_keys_exit, *iter);
5946}
5947
5948extern "C" void rados_read_op_omap_get_vals_by_keys(rados_read_op_t read_op,
5949 char const* const* keys,
5950 size_t keys_len,
5951 rados_omap_iter_t *iter,
5952 int *prval)
5953{
5954 tracepoint(librados, rados_read_op_omap_get_vals_by_keys_enter, read_op, keys, keys_len, iter, prval);
5955 std::set<std::string> to_get(keys, keys + keys_len);
5956
5957 RadosOmapIter *omap_iter = new RadosOmapIter;
5958 ((::ObjectOperation *)read_op)->omap_get_vals_by_keys(to_get,
5959 &omap_iter->values,
5960 prval);
5961 ((::ObjectOperation *)read_op)->add_handler(new C_OmapIter(omap_iter));
5962 *iter = omap_iter;
5963 tracepoint(librados, rados_read_op_omap_get_vals_by_keys_exit, *iter);
5964}
5965
5966extern "C" int rados_omap_get_next(rados_omap_iter_t iter,
5967 char **key,
5968 char **val,
5969 size_t *len)
5970{
5971 tracepoint(librados, rados_omap_get_next_enter, iter);
5972 RadosOmapIter *it = static_cast<RadosOmapIter *>(iter);
5973 if (it->i == it->values.end()) {
5974 *key = NULL;
5975 *val = NULL;
5976 *len = 0;
5977 tracepoint(librados, rados_omap_get_next_exit, 0, key, val, len);
5978 return 0;
5979 }
5980 if (key)
5981 *key = (char*)it->i->first.c_str();
5982 if (val)
5983 *val = it->i->second.c_str();
5984 if (len)
5985 *len = it->i->second.length();
5986 ++it->i;
5987 tracepoint(librados, rados_omap_get_next_exit, 0, key, val, len);
5988 return 0;
5989}
5990
5991extern "C" void rados_omap_get_end(rados_omap_iter_t iter)
5992{
5993 tracepoint(librados, rados_omap_get_end_enter, iter);
5994 RadosOmapIter *it = static_cast<RadosOmapIter *>(iter);
5995 delete it;
5996 tracepoint(librados, rados_omap_get_end_exit);
5997}
5998
5999extern "C" int rados_read_op_operate(rados_read_op_t read_op,
6000 rados_ioctx_t io,
6001 const char *oid,
6002 int flags)
6003{
6004 tracepoint(librados, rados_read_op_operate_enter, read_op, io, oid, flags);
6005 object_t obj(oid);
6006 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
6007 int retval = ctx->operate_read(obj, (::ObjectOperation *)read_op, NULL,
6008 translate_flags(flags));
6009 tracepoint(librados, rados_read_op_operate_exit, retval);
6010 return retval;
6011}
6012
6013extern "C" int rados_aio_read_op_operate(rados_read_op_t read_op,
6014 rados_ioctx_t io,
6015 rados_completion_t completion,
6016 const char *oid,
6017 int flags)
6018{
6019 tracepoint(librados, rados_aio_read_op_operate_enter, read_op, io, completion, oid, flags);
6020 object_t obj(oid);
6021 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
6022 librados::AioCompletionImpl *c = (librados::AioCompletionImpl*)completion;
6023 int retval = ctx->aio_operate_read(obj, (::ObjectOperation *)read_op,
6024 c, translate_flags(flags), NULL);
6025 tracepoint(librados, rados_aio_read_op_operate_exit, retval);
6026 return retval;
6027}
6028
6029extern "C" int rados_cache_pin(rados_ioctx_t io, const char *o)
6030{
6031 tracepoint(librados, rados_cache_pin_enter, io, o);
6032 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
6033 object_t oid(o);
6034 int retval = ctx->cache_pin(oid);
6035 tracepoint(librados, rados_cache_pin_exit, retval);
6036 return retval;
6037}
6038
6039extern "C" int rados_cache_unpin(rados_ioctx_t io, const char *o)
6040{
6041 tracepoint(librados, rados_cache_unpin_enter, io, o);
6042 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
6043 object_t oid(o);
6044 int retval = ctx->cache_unpin(oid);
6045 tracepoint(librados, rados_cache_unpin_exit, retval);
6046 return retval;
6047}
6048
6049
6050///////////////////////////// ListObject //////////////////////////////
6051librados::ListObject::ListObject() : impl(NULL)
6052{
6053}
6054
6055librados::ListObject::ListObject(librados::ListObjectImpl *i): impl(i)
6056{
6057}
6058
6059librados::ListObject::ListObject(const ListObject& rhs)
6060{
6061 if (rhs.impl == NULL) {
6062 impl = NULL;
6063 return;
6064 }
6065 impl = new ListObjectImpl();
6066 *impl = *(rhs.impl);
6067}
6068
6069librados::ListObject& librados::ListObject::operator=(const ListObject& rhs)
6070{
6071 if (rhs.impl == NULL) {
6072 delete impl;
6073 impl = NULL;
6074 return *this;
6075 }
6076 if (impl == NULL)
6077 impl = new ListObjectImpl();
6078 *impl = *(rhs.impl);
6079 return *this;
6080}
6081
6082librados::ListObject::~ListObject()
6083{
6084 if (impl)
6085 delete impl;
6086 impl = NULL;
6087}
6088
6089const std::string& librados::ListObject::get_nspace() const
6090{
6091 return impl->get_nspace();
6092}
6093
6094const std::string& librados::ListObject::get_oid() const
6095{
6096 return impl->get_oid();
6097}
6098
6099const std::string& librados::ListObject::get_locator() const
6100{
6101 return impl->get_locator();
6102}
6103
6104std::ostream& librados::operator<<(std::ostream& out, const librados::ListObject& lop)
6105{
6106 out << *(lop.impl);
6107 return out;
6108}
6109
6110CEPH_RADOS_API void rados_object_list_slice(
6111 rados_ioctx_t io,
6112 const rados_object_list_cursor start,
6113 const rados_object_list_cursor finish,
6114 const size_t n,
6115 const size_t m,
6116 rados_object_list_cursor *split_start,
6117 rados_object_list_cursor *split_finish)
6118{
6119 librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
6120
6121 assert(split_start);
6122 assert(split_finish);
6123 hobject_t *split_start_hobj = (hobject_t*)(*split_start);
6124 hobject_t *split_finish_hobj = (hobject_t*)(*split_finish);
6125 assert(split_start_hobj);
6126 assert(split_finish_hobj);
6127 hobject_t *start_hobj = (hobject_t*)(start);
6128 hobject_t *finish_hobj = (hobject_t*)(finish);
6129
6130 ctx->object_list_slice(
6131 *start_hobj,
6132 *finish_hobj,
6133 n,
6134 m,
6135 split_start_hobj,
6136 split_finish_hobj);
6137}
6138
6139librados::ObjectCursor::ObjectCursor()
6140{
6141 c_cursor = (rados_object_list_cursor)new hobject_t();
6142}
6143
6144librados::ObjectCursor::~ObjectCursor()
6145{
6146 hobject_t *h = (hobject_t *)c_cursor;
6147 delete h;
6148}
6149
6150librados::ObjectCursor::ObjectCursor(rados_object_list_cursor c)
6151{
6152 if (!c) {
6153 c_cursor = nullptr;
6154 } else {
6155 c_cursor = (rados_object_list_cursor)new hobject_t(*(hobject_t *)c);
6156 }
6157}
6158
6159librados::ObjectCursor& librados::ObjectCursor::operator=(const librados::ObjectCursor& rhs)
6160{
6161 if (rhs.c_cursor != nullptr) {
6162 hobject_t *h = (hobject_t*)rhs.c_cursor;
6163 c_cursor = (rados_object_list_cursor)(new hobject_t(*h));
6164 } else {
6165 c_cursor = nullptr;
6166 }
6167 return *this;
6168}
6169
6170bool librados::ObjectCursor::operator<(const librados::ObjectCursor &rhs) const
6171{
6172 const hobject_t lhs_hobj = (c_cursor == nullptr) ? hobject_t() : *((hobject_t*)c_cursor);
6173 const hobject_t rhs_hobj = (rhs.c_cursor == nullptr) ? hobject_t() : *((hobject_t*)(rhs.c_cursor));
6174 return lhs_hobj < rhs_hobj;
6175}
6176
6177bool librados::ObjectCursor::operator==(const librados::ObjectCursor &rhs) const
6178{
6179 const hobject_t lhs_hobj = (c_cursor == nullptr) ? hobject_t() : *((hobject_t*)c_cursor);
6180 const hobject_t rhs_hobj = (rhs.c_cursor == nullptr) ? hobject_t() : *((hobject_t*)(rhs.c_cursor));
6181 return cmp(lhs_hobj, rhs_hobj) == 0;
6182}
6183librados::ObjectCursor::ObjectCursor(const librados::ObjectCursor &rhs)
6184{
6185 *this = rhs;
6186}
6187
6188librados::ObjectCursor librados::IoCtx::object_list_begin()
6189{
6190 hobject_t *h = new hobject_t(io_ctx_impl->objecter->enumerate_objects_begin());
6191 ObjectCursor oc;
6192 oc.set((rados_object_list_cursor)h);
6193 return oc;
6194}
6195
6196
6197librados::ObjectCursor librados::IoCtx::object_list_end()
6198{
6199 hobject_t *h = new hobject_t(io_ctx_impl->objecter->enumerate_objects_end());
6200 librados::ObjectCursor oc;
6201 oc.set((rados_object_list_cursor)h);
6202 return oc;
6203}
6204
6205
6206void librados::ObjectCursor::set(rados_object_list_cursor c)
6207{
6208 delete (hobject_t*)c_cursor;
6209 c_cursor = c;
6210}
6211
6212string librados::ObjectCursor::to_str() const
6213{
6214 stringstream ss;
6215 ss << *(hobject_t *)c_cursor;
6216 return ss.str();
6217}
6218
6219bool librados::ObjectCursor::from_str(const string& s)
6220{
6221 if (s.empty()) {
6222 *(hobject_t *)c_cursor = hobject_t();
6223 return true;
6224 }
6225 return ((hobject_t *)c_cursor)->parse(s);
6226}
6227
6228CEPH_RADOS_API std::ostream& librados::operator<<(std::ostream& os, const librados::ObjectCursor& oc)
6229{
6230 if (oc.c_cursor) {
6231 os << *(hobject_t *)oc.c_cursor;
6232 } else {
6233 os << hobject_t();
6234 }
6235 return os;
6236}
6237
6238bool librados::IoCtx::object_list_is_end(const ObjectCursor &oc)
6239{
6240 hobject_t *h = (hobject_t *)oc.c_cursor;
6241 return h->is_max();
6242}
6243
6244int librados::IoCtx::object_list(const ObjectCursor &start,
6245 const ObjectCursor &finish,
6246 const size_t result_item_count,
6247 const bufferlist &filter,
6248 std::vector<ObjectItem> *result,
6249 ObjectCursor *next)
6250{
6251 assert(result != nullptr);
6252 assert(next != nullptr);
6253 result->clear();
6254
6255 C_SaferCond cond;
6256 hobject_t next_hash;
6257 std::list<librados::ListObjectImpl> obj_result;
6258 io_ctx_impl->objecter->enumerate_objects(
6259 io_ctx_impl->poolid,
6260 io_ctx_impl->oloc.nspace,
6261 *((hobject_t*)start.c_cursor),
6262 *((hobject_t*)finish.c_cursor),
6263 result_item_count,
6264 filter,
6265 &obj_result,
6266 &next_hash,
6267 &cond);
6268
6269 int r = cond.wait();
6270 if (r < 0) {
6271 next->set((rados_object_list_cursor)(new hobject_t(hobject_t::get_max())));
6272 return r;
6273 }
6274
6275 next->set((rados_object_list_cursor)(new hobject_t(next_hash)));
6276
6277 for (std::list<librados::ListObjectImpl>::iterator i = obj_result.begin();
6278 i != obj_result.end(); ++i) {
6279 ObjectItem oi;
6280 oi.oid = i->oid;
6281 oi.nspace = i->nspace;
6282 oi.locator = i->locator;
6283 result->push_back(oi);
6284 }
6285
6286 return obj_result.size();
6287}
6288
6289void librados::IoCtx::object_list_slice(
6290 const ObjectCursor start,
6291 const ObjectCursor finish,
6292 const size_t n,
6293 const size_t m,
6294 ObjectCursor *split_start,
6295 ObjectCursor *split_finish)
6296{
6297 assert(split_start != nullptr);
6298 assert(split_finish != nullptr);
6299
6300 io_ctx_impl->object_list_slice(
6301 *((hobject_t*)(start.c_cursor)),
6302 *((hobject_t*)(finish.c_cursor)),
6303 n,
6304 m,
6305 (hobject_t*)(split_start->c_cursor),
6306 (hobject_t*)(split_finish->c_cursor));
6307}
6308