]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: expose PGLSFilter in objclass interface
authorJohn Spray <john.spray@redhat.com>
Tue, 11 Aug 2015 12:16:57 +0000 (13:16 +0100)
committerJohn Spray <john.spray@redhat.com>
Wed, 26 Aug 2015 11:56:18 +0000 (12:56 +0100)
Signed-off-by: John Spray <john.spray@redhat.com>
src/objclass/class_api.cc
src/objclass/objclass.h
src/osd/ClassHandler.cc
src/osd/ClassHandler.h
src/osd/ReplicatedPG.cc
src/osd/ReplicatedPG.h

index 5137448292b9cee3afc06db053ef11483804058f..09b7f4f93c2184d1c341c8e30876d8ed6bb328ea 100644 (file)
@@ -82,6 +82,14 @@ int cls_unregister_method(cls_method_handle_t handle)
   return 1;
 }
 
+int cls_register_cxx_filter(cls_handle_t hclass, const std::string &filter_name,
+                           cls_cxx_filter_factory_t fn)
+{
+  ClassHandler::ClassData *cls = (ClassHandler::ClassData *)hclass;
+  cls->register_cxx_filter(filter_name, fn);
+  return 0;
+}
+
 int cls_call(cls_method_context_t hctx, const char *cls, const char *method,
                                  char *indata, int datalen,
                                  char **outdata, int *outdatalen)
index 6f0de2825c25380567e800face7ef15886447203..e14d6a6dc4b58d59d08fed9e9c7a9c1fba0c7f6b 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "../include/types.h"
 #include "msg/msg_types.h"
+#include "common/hobject.h"
 
 extern "C" {
 #endif
@@ -94,9 +95,41 @@ extern void class_fini(void);
 typedef int (*cls_method_cxx_call_t)(cls_method_context_t ctx,
                                     class buffer::list *inbl, class buffer::list *outbl);
 
+class PGLSFilter {
+protected:
+  string xattr;
+public:
+  PGLSFilter();
+  virtual ~PGLSFilter();
+  virtual bool filter(const hobject_t &obj, bufferlist& xattr_data,
+                      bufferlist& outdata) = 0;
+
+  /**
+   * xattr key, or empty string.  If non-empty, this xattr will be fetched
+   * and the value passed into ::filter
+   */
+   virtual string& get_xattr() { return xattr; }
+
+  /**
+   * If true, objects without the named xattr (if xattr name is not empty)
+   * will be rejected without calling ::filter
+   */
+  virtual bool reject_empty_xattr() { return true; }
+};
+
+// Classes expose a filter constructor that returns a subclass of PGLSFilter
+typedef PGLSFilter* (*cls_cxx_filter_factory_t)(
+    bufferlist::iterator *args);
+
+
+
 extern int cls_register_cxx_method(cls_handle_t hclass, const char *method, int flags,
                                   cls_method_cxx_call_t class_call, cls_method_handle_t *handle);
 
+extern int cls_register_cxx_filter(cls_handle_t hclass,
+                                   const std::string &filter_name,
+                                  cls_cxx_filter_factory_t fn);
+
 extern int cls_cxx_create(cls_method_context_t hctx, bool exclusive);
 extern int cls_cxx_remove(cls_method_context_t hctx);
 extern int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime);
index c52177b7e169038528b98c6c3843a7a75b4b2dee..ea6fed89fd6f36873e619533810e3b0a14d87c3e 100644 (file)
@@ -221,6 +221,13 @@ ClassHandler::ClassMethod *ClassHandler::ClassData::register_cxx_method(const ch
   return &method;
 }
 
+void ClassHandler::ClassData::register_cxx_filter(
+    const std::string &filter_name,
+    cls_cxx_filter_factory_t fn)
+{
+  filters_map[filter_name] = fn;
+}
+
 ClassHandler::ClassMethod *ClassHandler::ClassData::_get_method(const char *mname)
 {
   map<string, ClassHandler::ClassMethod>::iterator iter = methods_map.find(mname);
index 93cf3c07fbcb978312cb0c773b49e08d6a588370..843214d8d527dc7395030ce24372cc44fd7d1b61 100644 (file)
@@ -49,6 +49,7 @@ public:
     void *handle;
 
     map<string, ClassMethod> methods_map;
+    map<string, cls_cxx_filter_factory_t> filters_map;
 
     set<ClassData *> dependencies;         /* our dependencies */
     set<ClassData *> missing_dependencies; /* only missing dependencies */
@@ -64,11 +65,21 @@ public:
     ClassMethod *register_cxx_method(const char *mname, int flags, cls_method_cxx_call_t func);
     void unregister_method(ClassMethod *method);
 
+    void register_cxx_filter(
+        const std::string &filter_name,
+        cls_cxx_filter_factory_t fn);
+
     ClassMethod *get_method(const char *mname) {
       Mutex::Locker l(handler->mutex);
       return _get_method(mname);
     }
     int get_method_flags(const char *mname);
+
+    cls_cxx_filter_factory_t get_filter(const std::string &filter_name)
+    {
+      Mutex::Locker l(handler->mutex);
+      return filters_map[filter_name];
+    }
   };
 
 private:
index 08a29c735af7af4c2a4ca50cda023444f567e8f5..20087794d4fdc51c338c42b76877fb62732db39b 100644 (file)
@@ -20,6 +20,7 @@
 #include "ReplicatedPG.h"
 #include "OSD.h"
 #include "OpRequest.h"
+#include "objclass/objclass.h"
 
 #include "common/errno.h"
 #include "common/perf_counters.h"
@@ -508,6 +509,31 @@ void ReplicatedPG::wait_for_blocked_object(const hobject_t& soid, OpRequestRef o
   op->mark_delayed("waiting for blocked object");
 }
 
+class PGLSPlainFilter : public PGLSFilter {
+  string val;
+public:
+  PGLSPlainFilter(bufferlist::iterator& params) {
+    ::decode(xattr, params);
+    ::decode(val, params);
+  }
+  virtual ~PGLSPlainFilter() {}
+  virtual bool filter(const hobject_t &obj, bufferlist& xattr_data,
+                      bufferlist& outdata);
+};
+
+class PGLSParentFilter : public PGLSFilter {
+  inodeno_t parent_ino;
+public:
+  PGLSParentFilter(bufferlist::iterator& params) {
+    xattr = "_parent";
+    ::decode(parent_ino, params);
+    generic_dout(0) << "parent_ino=" << parent_ino << dendl;
+  }
+  virtual ~PGLSParentFilter() {}
+  virtual bool filter(const hobject_t &obj, bufferlist& xattr_data,
+                      bufferlist& outdata);
+};
+
 bool PGLSParentFilter::filter(const hobject_t &obj,
                               bufferlist& xattr_data, bufferlist& outdata)
 {
@@ -580,7 +606,31 @@ int ReplicatedPG::get_pgls_filter(bufferlist::iterator& iter, PGLSFilter **pfilt
   } else if (type.compare("plain") == 0) {
     filter = new PGLSPlainFilter(iter);
   } else {
-    return -EINVAL;
+    std::size_t dot = type.find(".");
+    if (dot == std::string::npos || dot == 0 || dot == type.size() - 1) {
+      return -EINVAL;
+    }
+
+    const std::string class_name = type.substr(0, dot);
+    const std::string filter_name = type.substr(dot + 1);
+    ClassHandler::ClassData *cls = NULL;
+    int r = osd->class_handler->open_class(class_name, &cls);
+    if (r != 0) {
+      derr << "Error opening class '" << class_name << "': "
+           << cpp_strerror(r) << dendl;
+      return -EINVAL;
+    } else {
+      assert(cls);
+    }
+
+    cls_cxx_filter_factory_t fn = cls->get_filter(filter_name);
+    if (fn == NULL) {
+      derr << "Error finding filter '" << filter_name << "' in class "
+           << class_name << dendl;
+      return -EINVAL;
+    }
+    filter = fn(&iter);
+    assert(filter);
   }
 
   *pfilter = filter;
index ab24da4199f1c6dd11fdb5f0ff9c0cc19f56e1be..8fd426fea01ed21d2cb0b8d676cfae105f86eff1 100644 (file)
@@ -46,6 +46,7 @@ class CopyFromCallback;
 class PromoteCallback;
 
 class ReplicatedPG;
+class PGLSFilter;
 void intrusive_ptr_add_ref(ReplicatedPG *pg);
 void intrusive_ptr_release(ReplicatedPG *pg);
 uint64_t get_with_id(ReplicatedPG *pg);
@@ -57,53 +58,6 @@ void put_with_id(ReplicatedPG *pg, uint64_t id);
   typedef boost::intrusive_ptr<ReplicatedPG> ReplicatedPGRef;
 #endif
 
-class PGLSFilter {
-protected:
-  string xattr;
-public:
-  PGLSFilter();
-  virtual ~PGLSFilter();
-  virtual bool filter(const hobject_t &obj, bufferlist& xattr_data,
-                      bufferlist& outdata) = 0;
-
-  /**
-   * xattr key, or empty string.  If non-empty, this xattr will be fetched
-   * and the value passed into ::filter
-   */
-   virtual string& get_xattr() { return xattr; }
-
-  /**
-   * If true, objects without the named xattr (if xattr name is not empty)
-   * will be rejected without calling ::filter
-   */
-  virtual bool reject_empty_xattr() { return true; }
-};
-
-class PGLSPlainFilter : public PGLSFilter {
-  string val;
-public:
-  PGLSPlainFilter(bufferlist::iterator& params) {
-    ::decode(xattr, params);
-    ::decode(val, params);
-  }
-  virtual ~PGLSPlainFilter() {}
-  virtual bool filter(const hobject_t &obj, bufferlist& xattr_data,
-                      bufferlist& outdata);
-};
-
-class PGLSParentFilter : public PGLSFilter {
-  inodeno_t parent_ino;
-public:
-  PGLSParentFilter(bufferlist::iterator& params) {
-    xattr = "_parent";
-    ::decode(parent_ino, params);
-    generic_dout(0) << "parent_ino=" << parent_ino << dendl;
-  }
-  virtual ~PGLSParentFilter() {}
-  virtual bool filter(const hobject_t &obj, bufferlist& xattr_data,
-                      bufferlist& outdata);
-};
-
 class ReplicatedPG : public PG, public PGBackend::Listener {
   friend class OSD;
   friend class Watch;