]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librados: add get_inconsistent_pgs() to librados
authorKefu Chai <kchai@redhat.com>
Fri, 11 Dec 2015 10:13:20 +0000 (18:13 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 25 Feb 2016 04:40:17 +0000 (12:40 +0800)
to list the inconsistent PGs of given pool, it's a wrapper
around the "ceph pg ls" command.

Fixes: #13505
Signed-off-by: Kefu Chai <kchai@redhat.com>
src/include/rados/librados.h
src/include/rados/librados.hpp
src/librados/librados.cc

index 087b4c68a49089424173b44fc074748ba0141c6a..0239061cd810ec68a6ecb35147f202ea6d79be7a 100644 (file)
@@ -614,6 +614,25 @@ CEPH_RADOS_API int rados_wait_for_latest_osdmap(rados_t cluster);
  */
 CEPH_RADOS_API int rados_pool_list(rados_t cluster, char *buf, size_t len);
 
+/**
+ * List inconsistent placement groups of the given pool
+ *
+ * Gets a list of inconsistent placement groups as NULL-terminated strings.
+ * The placement group names will be placed in the supplied buffer one after
+ * another. After the last name, there will be two 0 types in a row.
+ *
+ * If len is too short to fit all the placement group entries we need, we  will
+ * fill as much as we can.
+ *
+ * @param cluster cluster handle
+ * @param pool pool ID
+ * @param buf output buffer
+ * @param len output buffer length
+ * @returns length of the buffer we would need to list all pools
+ */
+CEPH_RADOS_API int rados_inconsistent_pg_list(rados_t cluster, int64_t pool,
+                                             char *buf, size_t len);
+
 /**
  * Get a configuration handle for a rados cluster handle
  *
index 22ba38b6180e8892097f1d2628786c1e9e4d0c43..e1593db3cbef0e2f98f3921e6fa521ade35a6b64 100644 (file)
@@ -1117,6 +1117,17 @@ namespace librados
     IoCtxImpl *io_ctx_impl;
   };
 
+  struct PlacementGroupImpl;
+  struct CEPH_RADOS_API PlacementGroup {
+    PlacementGroup();
+    PlacementGroup(const PlacementGroup&);
+    ~PlacementGroup();
+    bool parse(const char*);
+    std::unique_ptr<PlacementGroupImpl> impl;
+  };
+
+  CEPH_RADOS_API std::ostream& operator<<(std::ostream&, const PlacementGroup&);
+
   class CEPH_RADOS_API Rados
   {
   public:
@@ -1185,6 +1196,15 @@ namespace librados
     int cluster_stat(cluster_stat_t& result);
     int cluster_fsid(std::string *fsid);
 
+    /**
+     * List inconsistent placement groups in the given pool
+     *
+     * @param pool_id the pool id
+     * @param pgs [out] the inconsistent PGs
+     */
+    int get_inconsistent_pgs(int64_t pool_id,
+                             std::vector<PlacementGroup>* pgs);
+
     /// get/wait for the most recent osdmap
     int wait_for_latest_osdmap();
 
index e9014b5ac3d999350e58064b7b3c59caf8c089a2..31b795dc39044bb19ccdf271659e4019120249a3 100644 (file)
@@ -17,6 +17,7 @@
 #include "common/config.h"
 #include "common/errno.h"
 #include "common/ceph_argparse.h"
+#include "common/ceph_json.h"
 #include "common/common_init.h"
 #include "common/TracepointProvider.h"
 #include "common/hobject.h"
@@ -2301,6 +2302,97 @@ int librados::Rados::cluster_fsid(string *fsid)
   return client->get_fsid(fsid);
 }
 
+namespace librados {
+  struct PlacementGroupImpl {
+    pg_t pgid;
+  };
+
+  PlacementGroup::PlacementGroup()
+    : impl{new PlacementGroupImpl}
+  {}
+
+  PlacementGroup::PlacementGroup(const PlacementGroup& pg)
+    : impl{new PlacementGroupImpl}
+  {
+    impl->pgid = pg.impl->pgid;
+  }
+
+  PlacementGroup::~PlacementGroup()
+  {}
+
+  bool PlacementGroup::parse(const char* s)
+  {
+    return impl->pgid.parse(s);
+  }
+}
+
+std::ostream& librados::operator<<(std::ostream& out,
+                                  const librados::PlacementGroup& pg)
+{
+  return out << pg.impl->pgid;
+}
+
+namespace {
+  int decode_json(JSONObj *obj, pg_t& pg)
+  {
+    string pg_str;
+    JSONDecoder::decode_json("pgid", pg_str, obj);
+    if (pg.parse(pg_str.c_str())) {
+      return 0;
+    } else {
+      return -EINVAL;
+    }
+  }
+
+  int get_inconsistent_pgs(librados::RadosClient& client,
+                          int64_t pool_id,
+                          std::vector<librados::PlacementGroup>* pgs)
+  {
+    vector<string> cmd = {
+      "{\"prefix\": \"pg ls\","
+      "\"pool\": " + std::to_string(pool_id) + ","
+      "\"states\": [\"inconsistent\"],"
+      "\"format\": \"json\"}"
+    };
+    bufferlist inbl, outbl;
+    string outstring;
+    int ret = client.mon_command(cmd, inbl, &outbl, &outstring);
+    if (ret) {
+      return ret;
+    }
+    if (!outbl.length()) {
+      // no pg returned
+      return ret;
+    }
+    JSONParser parser;
+    if (!parser.parse(outbl.c_str(), outbl.length())) {
+      return -EINVAL;
+    }
+    if (!parser.is_array()) {
+      return -EINVAL;
+    }
+    vector<string> v = parser.get_array_elements();
+    for (auto i : v) {
+      JSONParser pg_json;
+      if (!pg_json.parse(i.c_str(), i.length())) {
+       return -EINVAL;
+      }
+      librados::PlacementGroup pg;
+      if (decode_json(&pg_json, pg.impl->pgid)) {
+       return -EINVAL;
+      }
+      pgs->emplace_back(pg);
+    }
+    return 0;
+  }
+}
+
+int librados::Rados::get_inconsistent_pgs(int64_t pool_id,
+                                         std::vector<PlacementGroup>* pgs)
+{
+  return ::get_inconsistent_pgs(*client, pool_id, pgs);
+}
+
 int librados::Rados::wait_for_latest_osdmap()
 {
   return client->wait_for_latest_osdmap();
@@ -2714,6 +2806,45 @@ extern "C" int rados_pool_list(rados_t cluster, char *buf, size_t len)
   return retval;
 }
 
+CEPH_RADOS_API int rados_inconsistent_pg_list(rados_t cluster, int64_t pool_id,
+                                             char *buf, size_t len)
+{
+  tracepoint(librados, rados_inconsistent_pg_list_enter, cluster, len);
+  librados::RadosClient *client = (librados::RadosClient *)cluster;
+  std::vector<librados::PlacementGroup> pgs;
+  int r = ::get_inconsistent_pgs(*client, pool_id, &pgs);
+  if (r < 0) {
+    tracepoint(librados, rados_inconsistent_pg_list_exit, r);
+    return r;
+  }
+
+  if (len > 0 && !buf) {
+    tracepoint(librados, rados_inconsistent_pg_list_exit, -EINVAL);
+    return -EINVAL;
+  }
+
+  char *b = buf;
+  if (b)
+    memset(b, 0, len);
+  int needed = 0;
+  for (const auto pg : pgs) {
+    std::ostringstream ss;
+    ss << pg;
+    auto s = ss.str();
+    unsigned rl = s.length() + 1;
+    if (len >= rl) {
+      tracepoint(librados, rados_inconsistent_pg_list_pg, p);
+      strncat(b, s.c_str(), rl);
+      b += rl;
+      len -= rl;
+    }
+    needed += rl;
+  }
+  int retval = needed + 1;
+  tracepoint(librados, rados_inconsistent_pg_list_exit, retval);
+  return retval;
+}
+
 static void do_out_buffer(bufferlist& outbl, char **outbuf, size_t *outbuflen)
 {
   if (outbuf) {