From: John Spray Date: Tue, 11 Aug 2015 12:16:57 +0000 (+0100) Subject: osd: expose PGLSFilter in objclass interface X-Git-Tag: v9.1.0~287^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=df21a6e212a99599bbeafa2fb6c3ec97deac6739;p=ceph.git osd: expose PGLSFilter in objclass interface Signed-off-by: John Spray --- diff --git a/src/objclass/class_api.cc b/src/objclass/class_api.cc index 5137448292b9..09b7f4f93c21 100644 --- a/src/objclass/class_api.cc +++ b/src/objclass/class_api.cc @@ -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) diff --git a/src/objclass/objclass.h b/src/objclass/objclass.h index 6f0de2825c25..e14d6a6dc4b5 100644 --- a/src/objclass/objclass.h +++ b/src/objclass/objclass.h @@ -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); diff --git a/src/osd/ClassHandler.cc b/src/osd/ClassHandler.cc index c52177b7e169..ea6fed89fd6f 100644 --- a/src/osd/ClassHandler.cc +++ b/src/osd/ClassHandler.cc @@ -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::iterator iter = methods_map.find(mname); diff --git a/src/osd/ClassHandler.h b/src/osd/ClassHandler.h index 93cf3c07fbcb..843214d8d527 100644 --- a/src/osd/ClassHandler.h +++ b/src/osd/ClassHandler.h @@ -49,6 +49,7 @@ public: void *handle; map methods_map; + map filters_map; set dependencies; /* our dependencies */ set 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: diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index 08a29c735af7..20087794d4fd 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -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; diff --git a/src/osd/ReplicatedPG.h b/src/osd/ReplicatedPG.h index ab24da4199f1..8fd426fea01e 100644 --- a/src/osd/ReplicatedPG.h +++ b/src/osd/ReplicatedPG.h @@ -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 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;