]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
ceph_json: json encoding filter
authorYehuda Sadeh <yehuda@redhat.com>
Sat, 16 Nov 2019 02:32:17 +0000 (18:32 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Tue, 28 Jan 2020 18:20:38 +0000 (10:20 -0800)
Can create and register a filter (that will be pointed at by the formatter
as an external feature), that could be then used to replace default
encoders for specific data types. This can be useful in cases where
we want to mutate the output (for example: translate zone ids to zone
names on the fly).

Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
src/common/Formatter.h
src/common/ceph_json.h

index c4cdd552373b0a5ac9e650c10c80e84734bd2bb3..d2a1d55c480bc4d702726f59713b544117653dcb 100644 (file)
@@ -114,6 +114,10 @@ namespace ceph {
     {
       dump_string(name, s);
     }
+
+    virtual void *get_external_feature_handler(const std::string& feature) {
+      return nullptr;
+    }
   };
 
   class copyable_sstream : public std::stringstream {
index 27d2dddd139b2bee1d581866309fe83a443668f2..207babc1f15a2045e69eabb34807aa5b7c7e2cfb 100644 (file)
@@ -2,6 +2,7 @@
 #define CEPH_JSON_H
 
 #include <stdexcept>
+#include <typeindex>
 #include <include/types.h>
 #include <boost/container/flat_map.hpp>
 
@@ -411,14 +412,66 @@ bool JSONDecoder::decode_json(const char *name, std::optional<T>& val, JSONObj *
   return true;
 }
 
+class JSONEncodeFilter
+{
+public:
+  class HandlerBase {
+  public:
+    virtual ~HandlerBase() {}
+
+    virtual std::type_index get_type() = 0;
+    virtual void encode_json(const char *name, const void *pval, ceph::Formatter *) const = 0;
+  };
+
+  template <class T>
+  class Handler : public HandlerBase {
+  public:
+    virtual ~Handler() {}
+
+    std::type_index get_type() override {
+      return std::type_index(typeid(const T&));
+    }
+  };
+
+private:
+  std::map<std::type_index, HandlerBase *> handlers;
+
+public:
+  void register_type(HandlerBase *h) {
+    handlers[h->get_type()] = h;
+  }
+
+  template <class T>
+  bool encode_json(const char *name, const T& val, ceph::Formatter *f) {
+    auto iter = handlers.find(std::type_index(typeid(val)));
+    if (iter == handlers.end()) {
+      return false;
+    }
+
+    iter->second->encode_json(name, (const void *)&val, f);
+    return true;
+  }
+};
+
 template<class T>
-static void encode_json(const char *name, const T& val, ceph::Formatter *f)
+static void encode_json_impl(const char *name, const T& val, ceph::Formatter *f)
 {
   f->open_object_section(name);
   val.dump(f);
   f->close_section();
 }
 
+template<class T>
+static void encode_json(const char *name, const T& val, ceph::Formatter *f)
+{
+  JSONEncodeFilter *filter = static_cast<JSONEncodeFilter *>(f->get_external_feature_handler("JSONEncodeFilter"));
+
+  if (!filter ||
+      !filter->encode_json(name, val, f)) {
+    encode_json_impl(name, val, f);
+  }
+}
+
 class utime_t;
 
 void encode_json(const char *name, const std::string& val, ceph::Formatter *f);