1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2012 Sage Weil <sage@newdream.net>
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.
15 #include <sys/types.h>
25 #include "common/ceph_context.h"
26 #include "common/config.h"
27 #include "common/common_init.h"
28 #include "common/ceph_json.h"
29 #include "common/errno.h"
30 #include "common/ceph_json.h"
31 #include "include/buffer.h"
32 #include "include/stringify.h"
33 #include "include/util.h"
35 #include "messages/MLog.h"
36 #include "msg/Messenger.h"
38 // needed for static_cast
39 #include "messages/PaxosServiceMessage.h"
40 #include "messages/MPoolOpReply.h"
41 #include "messages/MStatfsReply.h"
42 #include "messages/MGetPoolStatsReply.h"
43 #include "messages/MOSDOpReply.h"
44 #include "messages/MOSDMap.h"
45 #include "messages/MCommandReply.h"
47 #include "AioCompletionImpl.h"
48 #include "IoCtxImpl.h"
49 #include "PoolAsyncCompletionImpl.h"
50 #include "RadosClient.h"
52 #include "include/ceph_assert.h"
53 #include "common/EventTrace.h"
55 #define dout_subsys ceph_subsys_rados
57 #define dout_prefix *_dout << "librados: "
59 bool librados::RadosClient::ms_get_authorizer(int dest_type
,
60 AuthAuthorizer
**authorizer
) {
61 //ldout(cct, 0) << "RadosClient::ms_get_authorizer type=" << dest_type << dendl;
62 /* monitor authorization is being handled on different layer */
63 if (dest_type
== CEPH_ENTITY_TYPE_MON
)
65 *authorizer
= monclient
.build_authorizer(dest_type
);
66 return *authorizer
!= NULL
;
69 librados::RadosClient::RadosClient(CephContext
*cct_
)
70 : Dispatcher(cct_
->get()),
71 cct_deleter
{cct_
, [](CephContext
*p
) {p
->put();}},
75 mgrclient(cct_
, nullptr),
79 lock("librados::RadosClient::lock"),
82 log_last_version(0), log_cb(NULL
), log_cb2(NULL
), log_cb_arg(NULL
),
83 finisher(cct
, "radosclient", "fn-radosclient")
87 int64_t librados::RadosClient::lookup_pool(const char *name
)
89 int r
= wait_for_osdmap();
94 int64_t ret
= objecter
->with_osdmap(std::mem_fn(&OSDMap::lookup_pg_pool_name
),
97 // Make sure we have the latest map
98 int r
= wait_for_latest_osdmap();
101 ret
= objecter
->with_osdmap(std::mem_fn(&OSDMap::lookup_pg_pool_name
),
108 bool librados::RadosClient::pool_requires_alignment(int64_t pool_id
)
111 int r
= pool_requires_alignment2(pool_id
, &requires
);
113 // Cast answer to false, this is a little bit problematic
114 // since we really don't know the answer yet, say.
121 // a safer version of pool_requires_alignment
122 int librados::RadosClient::pool_requires_alignment2(int64_t pool_id
,
128 int r
= wait_for_osdmap();
133 return objecter
->with_osdmap([requires
, pool_id
](const OSDMap
& o
) {
134 if (!o
.have_pg_pool(pool_id
)) {
137 *requires
= o
.get_pg_pool(pool_id
)->requires_aligned_append();
142 uint64_t librados::RadosClient::pool_required_alignment(int64_t pool_id
)
145 int r
= pool_required_alignment2(pool_id
, &alignment
);
153 // a safer version of pool_required_alignment
154 int librados::RadosClient::pool_required_alignment2(int64_t pool_id
,
160 int r
= wait_for_osdmap();
165 return objecter
->with_osdmap([alignment
, pool_id
](const OSDMap
&o
) {
166 if (!o
.have_pg_pool(pool_id
)) {
169 *alignment
= o
.get_pg_pool(pool_id
)->required_alignment();
174 int librados::RadosClient::pool_get_name(uint64_t pool_id
, std::string
*s
, bool wait_latest_map
)
176 int r
= wait_for_osdmap();
180 objecter
->with_osdmap([&](const OSDMap
& o
) {
181 if (!o
.have_pg_pool(pool_id
)) {
185 *s
= o
.get_pool_name(pool_id
);
188 if (r
== -ENOENT
&& wait_latest_map
) {
189 r
= wait_for_latest_osdmap();
192 wait_latest_map
= false;
199 int librados::RadosClient::get_fsid(std::string
*s
)
203 std::lock_guard
l(lock
);
205 oss
<< monclient
.get_fsid();
210 int librados::RadosClient::ping_monitor(const string mon_id
, string
*result
)
213 /* If we haven't yet connected, we have no way of telling whether we
214 * already built monc's initial monmap. IF we are in CONNECTED state,
215 * then it is safe to assume that we went through connect(), which does
218 if (state
!= CONNECTED
) {
219 ldout(cct
, 10) << __func__
<< " build monmap" << dendl
;
220 err
= monclient
.build_initial_monmap();
226 err
= monclient
.ping_monitor(mon_id
, result
);
230 int librados::RadosClient::connect()
234 // already connected?
235 if (state
== CONNECTING
)
237 if (state
== CONNECTED
)
241 if (cct
->_conf
->log_early
&&
242 !cct
->_log
->is_started()) {
247 MonClient
mc_bootstrap(cct
);
248 err
= mc_bootstrap
.get_monmap_and_config();
253 common_init_finish(cct
);
256 err
= monclient
.build_initial_monmap();
261 messenger
= Messenger::create_client_messenger(cct
, "radosclient");
265 // require OSDREPLYMUX feature. this means we will fail to talk to
266 // old servers. this is necessary because otherwise we won't know
267 // how to decompose the reply data into its constituent pieces.
268 messenger
->set_default_policy(Messenger::Policy::lossy_client(CEPH_FEATURE_OSDREPLYMUX
));
270 ldout(cct
, 1) << "starting msgr at " << messenger
->get_myaddrs() << dendl
;
272 ldout(cct
, 1) << "starting objecter" << dendl
;
274 objecter
= new (std::nothrow
) Objecter(cct
, messenger
, &monclient
,
276 cct
->_conf
->rados_mon_op_timeout
,
277 cct
->_conf
->rados_osd_op_timeout
);
280 objecter
->set_balanced_budget();
282 monclient
.set_messenger(messenger
);
283 mgrclient
.set_messenger(messenger
);
286 messenger
->add_dispatcher_head(&mgrclient
);
287 messenger
->add_dispatcher_tail(objecter
);
288 messenger
->add_dispatcher_tail(this);
292 ldout(cct
, 1) << "setting wanted keys" << dendl
;
293 monclient
.set_want_keys(
294 CEPH_ENTITY_TYPE_MON
| CEPH_ENTITY_TYPE_OSD
| CEPH_ENTITY_TYPE_MGR
);
295 ldout(cct
, 1) << "calling monclient init" << dendl
;
296 err
= monclient
.init();
298 ldout(cct
, 0) << conf
->name
<< " initialization error " << cpp_strerror(-err
) << dendl
;
303 err
= monclient
.authenticate(conf
->client_mount_timeout
);
305 ldout(cct
, 0) << conf
->name
<< " authentication error " << cpp_strerror(-err
) << dendl
;
309 messenger
->set_myname(entity_name_t::CLIENT(monclient
.get_global_id()));
311 // Detect older cluster, put mgrclient into compatible mode
312 mgrclient
.set_mgr_optional(
313 !get_required_monitor_features().contains_all(
314 ceph::features::mon::FEATURE_LUMINOUS
));
316 // MgrClient needs this (it doesn't have MonClient reference itself)
317 monclient
.sub_want("mgrmap", 0, 0);
318 monclient
.renew_subs();
320 if (service_daemon
) {
321 ldout(cct
, 10) << __func__
<< " registering as " << service_name
<< "."
322 << daemon_name
<< dendl
;
323 mgrclient
.service_daemon_register(service_name
, daemon_name
,
328 objecter
->set_client_incarnation(0);
337 instance_id
= monclient
.get_global_id();
341 ldout(cct
, 1) << "init done" << dendl
;
346 state
= DISCONNECTED
;
361 void librados::RadosClient::shutdown()
364 if (state
== DISCONNECTED
) {
369 bool need_objecter
= false;
370 if (objecter
&& objecter
->initialized
) {
371 need_objecter
= true;
374 if (state
== CONNECTED
) {
376 // make sure watch callbacks are flushed
379 finisher
.wait_for_empty();
382 state
= DISCONNECTED
;
384 timer
.shutdown(); // will drop+retake lock
387 objecter
->shutdown();
389 mgrclient
.shutdown();
391 monclient
.shutdown();
393 messenger
->shutdown();
396 ldout(cct
, 1) << "shutdown" << dendl
;
399 int librados::RadosClient::watch_flush()
401 ldout(cct
, 10) << __func__
<< " enter" << dendl
;
402 Mutex
mylock("RadosClient::watch_flush::mylock");
405 objecter
->linger_callback_flush(new C_SafeCond(&mylock
, &cond
, &done
));
412 ldout(cct
, 10) << __func__
<< " exit" << dendl
;
416 struct C_aio_watch_flush_Complete
: public Context
{
417 librados::RadosClient
*client
;
418 librados::AioCompletionImpl
*c
;
420 C_aio_watch_flush_Complete(librados::RadosClient
*_client
, librados::AioCompletionImpl
*_c
)
421 : client(_client
), c(_c
) {
425 void finish(int r
) override
{
431 if (c
->callback_complete
||
433 client
->finisher
.queue(new librados::C_AioComplete(c
));
439 int librados::RadosClient::async_watch_flush(AioCompletionImpl
*c
)
441 ldout(cct
, 10) << __func__
<< " enter" << dendl
;
442 Context
*oncomplete
= new C_aio_watch_flush_Complete(this, c
);
443 objecter
->linger_callback_flush(oncomplete
);
444 ldout(cct
, 10) << __func__
<< " exit" << dendl
;
448 uint64_t librados::RadosClient::get_instance_id()
453 int librados::RadosClient::get_min_compatible_osd(int8_t* require_osd_release
)
455 int r
= wait_for_osdmap();
460 objecter
->with_osdmap(
461 [require_osd_release
](const OSDMap
& o
) {
462 *require_osd_release
= o
.require_osd_release
;
467 int librados::RadosClient::get_min_compatible_client(int8_t* min_compat_client
,
468 int8_t* require_min_compat_client
)
470 int r
= wait_for_osdmap();
475 objecter
->with_osdmap(
476 [min_compat_client
, require_min_compat_client
](const OSDMap
& o
) {
477 *min_compat_client
= o
.get_min_compat_client();
478 *require_min_compat_client
= o
.get_require_min_compat_client();
483 librados::RadosClient::~RadosClient()
492 int librados::RadosClient::create_ioctx(const char *name
, IoCtxImpl
**io
)
494 int64_t poolid
= lookup_pool(name
);
499 *io
= new librados::IoCtxImpl(this, objecter
, poolid
, CEPH_NOSNAP
);
503 int librados::RadosClient::create_ioctx(int64_t pool_id
, IoCtxImpl
**io
)
505 std::string pool_name
;
506 int r
= pool_get_name(pool_id
, &pool_name
, true);
509 *io
= new librados::IoCtxImpl(this, objecter
, pool_id
, CEPH_NOSNAP
);
513 bool librados::RadosClient::ms_dispatch(Message
*m
)
517 std::lock_guard
l(lock
);
518 if (state
== DISCONNECTED
) {
519 ldout(cct
, 10) << "disconnected, discarding " << *m
<< dendl
;
528 void librados::RadosClient::ms_handle_connect(Connection
*con
)
532 bool librados::RadosClient::ms_handle_reset(Connection
*con
)
537 void librados::RadosClient::ms_handle_remote_reset(Connection
*con
)
541 bool librados::RadosClient::ms_handle_refused(Connection
*con
)
546 bool librados::RadosClient::_dispatch(Message
*m
)
548 ceph_assert(lock
.is_locked());
549 switch (m
->get_type()) {
551 case CEPH_MSG_OSD_MAP
:
556 case CEPH_MSG_MDS_MAP
:
561 handle_log(static_cast<MLog
*>(m
));
572 int librados::RadosClient::wait_for_osdmap()
574 ceph_assert(!lock
.is_locked_by_me());
576 if (state
!= CONNECTED
) {
580 bool need_map
= false;
581 objecter
->with_osdmap([&](const OSDMap
& o
) {
582 if (o
.get_epoch() == 0) {
588 std::lock_guard
l(lock
);
590 ceph::timespan timeout
{0};
591 if (cct
->_conf
->rados_mon_op_timeout
> 0) {
592 timeout
= ceph::make_timespan(cct
->_conf
->rados_mon_op_timeout
);
595 if (objecter
->with_osdmap(std::mem_fn(&OSDMap::get_epoch
)) == 0) {
596 ldout(cct
, 10) << __func__
<< " waiting" << dendl
;
597 while (objecter
->with_osdmap(std::mem_fn(&OSDMap::get_epoch
)) == 0) {
598 if (timeout
== timeout
.zero()) {
601 int r
= cond
.WaitInterval(lock
, timeout
);
602 if (r
== ETIMEDOUT
) {
603 lderr(cct
) << "timed out waiting for first osdmap from monitors"
609 ldout(cct
, 10) << __func__
<< " done waiting" << dendl
;
618 int librados::RadosClient::wait_for_latest_osdmap()
620 Mutex
mylock("RadosClient::wait_for_latest_osdmap");
624 objecter
->wait_for_latest_osdmap(new C_SafeCond(&mylock
, &cond
, &done
));
634 int librados::RadosClient::pool_list(std::list
<std::pair
<int64_t, string
> >& v
)
636 int r
= wait_for_osdmap();
640 objecter
->with_osdmap([&](const OSDMap
& o
) {
641 for (auto p
: o
.get_pools())
642 v
.push_back(std::make_pair(p
.first
, o
.get_pool_name(p
.first
)));
647 int librados::RadosClient::get_pool_stats(std::list
<string
>& pools
,
648 map
<string
,::pool_stat_t
>& result
)
650 Mutex
mylock("RadosClient::get_pool_stats::mylock");
655 objecter
->get_pool_stats(pools
, &result
, new C_SafeCond(&mylock
, &cond
, &done
,
666 bool librados::RadosClient::get_pool_is_selfmanaged_snaps_mode(
667 const std::string
& pool
)
670 objecter
->with_osdmap([&](const OSDMap
& osdmap
) {
671 int64_t poolid
= osdmap
.lookup_pg_pool_name(pool
);
673 ret
= osdmap
.get_pg_pool(poolid
)->is_unmanaged_snaps_mode();
678 int librados::RadosClient::get_fs_stats(ceph_statfs
& stats
)
680 Mutex
mylock ("RadosClient::get_fs_stats::mylock");
686 objecter
->get_fs_stats(stats
, boost::optional
<int64_t> (),
687 new C_SafeCond(&mylock
, &cond
, &done
, &ret
));
691 while (!done
) cond
.Wait(mylock
);
697 void librados::RadosClient::get() {
698 std::lock_guard
l(lock
);
699 ceph_assert(refcnt
> 0);
703 bool librados::RadosClient::put() {
704 std::lock_guard
l(lock
);
705 ceph_assert(refcnt
> 0);
707 return (refcnt
== 0);
710 int librados::RadosClient::pool_create(string
& name
,
716 int r
= wait_for_osdmap();
721 Mutex
mylock ("RadosClient::pool_create::mylock");
725 Context
*onfinish
= new C_SafeCond(&mylock
, &cond
, &done
, &reply
);
726 reply
= objecter
->create_pool(name
, onfinish
, crush_rule
);
739 int librados::RadosClient::pool_create_async(string
& name
,
740 PoolAsyncCompletionImpl
*c
,
743 int r
= wait_for_osdmap();
747 Context
*onfinish
= new C_PoolAsync_Safe(c
);
748 r
= objecter
->create_pool(name
, onfinish
, crush_rule
);
755 int librados::RadosClient::pool_get_base_tier(int64_t pool_id
, int64_t* base_tier
)
757 int r
= wait_for_osdmap();
762 objecter
->with_osdmap([&](const OSDMap
& o
) {
763 const pg_pool_t
* pool
= o
.get_pg_pool(pool_id
);
765 if (pool
->tier_of
< 0) {
766 *base_tier
= pool_id
;
768 *base_tier
= pool
->tier_of
;
778 int librados::RadosClient::pool_delete(const char *name
)
780 int r
= wait_for_osdmap();
785 Mutex
mylock("RadosClient::pool_delete::mylock");
789 Context
*onfinish
= new C_SafeCond(&mylock
, &cond
, &done
, &ret
);
790 ret
= objecter
->delete_pool(name
, onfinish
);
803 int librados::RadosClient::pool_delete_async(const char *name
, PoolAsyncCompletionImpl
*c
)
805 int r
= wait_for_osdmap();
809 Context
*onfinish
= new C_PoolAsync_Safe(c
);
810 r
= objecter
->delete_pool(name
, onfinish
);
817 void librados::RadosClient::blacklist_self(bool set
) {
818 std::lock_guard
l(lock
);
819 objecter
->blacklist_self(set
);
822 int librados::RadosClient::blacklist_add(const string
& client_address
,
823 uint32_t expire_seconds
)
826 if (!addr
.parse(client_address
.c_str(), 0)) {
827 lderr(cct
) << "unable to parse address " << client_address
<< dendl
;
831 std::stringstream cmd
;
833 << "\"prefix\": \"osd blacklist\", "
834 << "\"blacklistop\": \"add\", "
835 << "\"addr\": \"" << client_address
<< "\"";
836 if (expire_seconds
!= 0) {
837 cmd
<< ", \"expire\": " << expire_seconds
<< ".0";
841 std::vector
<std::string
> cmds
;
842 cmds
.push_back(cmd
.str());
844 int r
= mon_command(cmds
, inbl
, NULL
, NULL
);
849 // ensure we have the latest osd map epoch before proceeding
850 r
= wait_for_latest_osdmap();
854 int librados::RadosClient::mon_command(const vector
<string
>& cmd
,
855 const bufferlist
&inbl
,
856 bufferlist
*outbl
, string
*outs
)
859 mon_command_async(cmd
, inbl
, outbl
, outs
, &ctx
);
863 void librados::RadosClient::mon_command_async(const vector
<string
>& cmd
,
864 const bufferlist
&inbl
,
865 bufferlist
*outbl
, string
*outs
,
869 monclient
.start_mon_command(cmd
, inbl
, outbl
, outs
, on_finish
);
873 int librados::RadosClient::mgr_command(const vector
<string
>& cmd
,
874 const bufferlist
&inbl
,
875 bufferlist
*outbl
, string
*outs
)
877 std::lock_guard
l(lock
);
880 int r
= mgrclient
.start_command(cmd
, inbl
, outbl
, outs
, &cond
);
885 if (conf
->rados_mon_op_timeout
) {
886 r
= cond
.wait_for(conf
->rados_mon_op_timeout
);
896 int librados::RadosClient::mon_command(int rank
, const vector
<string
>& cmd
,
897 const bufferlist
&inbl
,
898 bufferlist
*outbl
, string
*outs
)
900 Mutex
mylock("RadosClient::mon_command::mylock");
905 monclient
.start_mon_command(rank
, cmd
, inbl
, outbl
, outs
,
906 new C_SafeCond(&mylock
, &cond
, &done
, &rval
));
915 int librados::RadosClient::mon_command(string name
, const vector
<string
>& cmd
,
916 const bufferlist
&inbl
,
917 bufferlist
*outbl
, string
*outs
)
919 Mutex
mylock("RadosClient::mon_command::mylock");
924 monclient
.start_mon_command(name
, cmd
, inbl
, outbl
, outs
,
925 new C_SafeCond(&mylock
, &cond
, &done
, &rval
));
934 int librados::RadosClient::osd_command(int osd
, vector
<string
>& cmd
,
935 const bufferlist
& inbl
,
936 bufferlist
*poutbl
, string
*prs
)
938 Mutex
mylock("RadosClient::osd_command::mylock");
948 // XXX do anything with tid?
949 objecter
->osd_command(osd
, cmd
, inbl
, &tid
, poutbl
, prs
,
950 new C_SafeCond(&mylock
, &cond
, &done
, &ret
));
959 int librados::RadosClient::pg_command(pg_t pgid
, vector
<string
>& cmd
,
960 const bufferlist
& inbl
,
961 bufferlist
*poutbl
, string
*prs
)
963 Mutex
mylock("RadosClient::pg_command::mylock");
969 objecter
->pg_command(pgid
, cmd
, inbl
, &tid
, poutbl
, prs
,
970 new C_SafeCond(&mylock
, &cond
, &done
, &ret
));
979 int librados::RadosClient::monitor_log(const string
& level
,
980 rados_log_callback_t cb
,
981 rados_log_callback2_t cb2
,
984 std::lock_guard
l(lock
);
986 if (state
!= CONNECTED
) {
990 if (cb
== NULL
&& cb2
== NULL
) {
992 ldout(cct
, 10) << __func__
<< " removing cb " << (void*)log_cb
993 << " " << (void*)log_cb2
<< dendl
;
994 monclient
.sub_unwant(log_watch
);
1003 if (level
== "debug") {
1004 watch_level
= "log-debug";
1005 } else if (level
== "info") {
1006 watch_level
= "log-info";
1007 } else if (level
== "warn" || level
== "warning") {
1008 watch_level
= "log-warn";
1009 } else if (level
== "err" || level
== "error") {
1010 watch_level
= "log-error";
1011 } else if (level
== "sec") {
1012 watch_level
= "log-sec";
1014 ldout(cct
, 10) << __func__
<< " invalid level " << level
<< dendl
;
1018 if (log_cb
|| log_cb2
)
1019 monclient
.sub_unwant(log_watch
);
1022 ldout(cct
, 10) << __func__
<< " add cb " << (void*)cb
<< " " << (void*)cb2
1023 << " level " << level
<< dendl
;
1024 monclient
.sub_want(watch_level
, 0, 0);
1026 monclient
.renew_subs();
1030 log_watch
= watch_level
;
1034 void librados::RadosClient::handle_log(MLog
*m
)
1036 ceph_assert(lock
.is_locked());
1037 ldout(cct
, 10) << __func__
<< " version " << m
->version
<< dendl
;
1039 if (log_last_version
< m
->version
) {
1040 log_last_version
= m
->version
;
1042 if (log_cb
|| log_cb2
) {
1043 for (std::deque
<LogEntry
>::iterator it
= m
->entries
.begin(); it
!= m
->entries
.end(); ++it
) {
1046 ss
<< e
.stamp
<< " " << e
.name
<< " " << e
.prio
<< " " << e
.msg
;
1047 string line
= ss
.str();
1048 string who
= stringify(e
.rank
) + " " + stringify(e
.addrs
);
1049 string name
= stringify(e
.name
);
1050 string level
= stringify(e
.prio
);
1051 struct timespec stamp
;
1052 e
.stamp
.to_timespec(&stamp
);
1054 ldout(cct
, 20) << __func__
<< " delivering " << ss
.str() << dendl
;
1056 log_cb(log_cb_arg
, line
.c_str(), who
.c_str(),
1057 stamp
.tv_sec
, stamp
.tv_nsec
,
1058 e
.seq
, level
.c_str(), e
.msg
.c_str());
1060 log_cb2(log_cb_arg
, line
.c_str(),
1062 who
.c_str(), name
.c_str(),
1063 stamp
.tv_sec
, stamp
.tv_nsec
,
1064 e
.seq
, level
.c_str(), e
.msg
.c_str());
1068 monclient
.sub_got(log_watch
, log_last_version
);
1074 int librados::RadosClient::service_daemon_register(
1075 const std::string
& service
, ///< service name (e.g., 'rgw')
1076 const std::string
& name
, ///< daemon name (e.g., 'gwfoo')
1077 const std::map
<std::string
,std::string
>& metadata
)
1079 if (service_daemon
) {
1082 if (service
== "osd" ||
1084 service
== "client" ||
1087 // normal ceph entity types are not allowed!
1090 if (service
.empty() || name
.empty()) {
1094 collect_sys_info(&daemon_metadata
, cct
);
1096 ldout(cct
,10) << __func__
<< " " << service
<< "." << name
<< dendl
;
1097 service_daemon
= true;
1098 service_name
= service
;
1100 daemon_metadata
.insert(metadata
.begin(), metadata
.end());
1102 if (state
== DISCONNECTED
) {
1105 if (state
== CONNECTING
) {
1108 mgrclient
.service_daemon_register(service_name
, daemon_name
,
1113 int librados::RadosClient::service_daemon_update_status(
1114 std::map
<std::string
,std::string
>&& status
)
1116 if (state
!= CONNECTED
) {
1119 return mgrclient
.service_daemon_update_status(std::move(status
));
1122 mon_feature_t
librados::RadosClient::get_required_monitor_features() const
1124 return monclient
.with_monmap([](const MonMap
&monmap
) {
1125 return monmap
.get_required_features(); } );
1128 int librados::RadosClient::get_inconsistent_pgs(int64_t pool_id
,
1129 std::vector
<std::string
>* pgs
)
1131 vector
<string
> cmd
= {
1132 "{\"prefix\": \"pg ls\","
1133 "\"pool\": " + std::to_string(pool_id
) + ","
1134 "\"states\": [\"inconsistent\"],"
1135 "\"format\": \"json\"}"
1137 bufferlist inbl
, outbl
;
1139 if (auto ret
= mgr_command(cmd
, inbl
, &outbl
, &outstring
); ret
) {
1142 if (!outbl
.length()) {
1147 if (!parser
.parse(outbl
.c_str(), outbl
.length())) {
1151 if (!parser
.is_array()) {
1152 JSONObj
*pgstat_obj
= parser
.find_obj("pg_stats");
1155 auto s
= pgstat_obj
->get_data();
1156 JSONParser pg_stats
;
1157 if (!pg_stats
.parse(s
.c_str(), s
.length())) {
1160 v
= pg_stats
.get_array_elements();
1162 v
= parser
.get_array_elements();
1166 if (!pg_json
.parse(i
.c_str(), i
.length())) {
1170 JSONDecoder::decode_json("pgid", pgid
, &pg_json
);
1171 pgs
->emplace_back(std::move(pgid
));