From: Sage Weil Date: Sat, 11 Apr 2015 14:45:07 +0000 (-0700) Subject: common: PluginRegistry X-Git-Tag: v10.0.2~104^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5eb64dd324a0e0ec609acf2b178c02dee901aa5d;p=ceph.git common: PluginRegistry Generic plugin loader. Based on the ErasureCodePlugin. Signed-off-by: Sage Weil Conflicts: src/common/Makefile.am src/common/ceph_context.cc src/common/ceph_context.h missing files --- diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 83b64985d78b..2dfcd46d025b 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -68,7 +68,8 @@ libcommon_internal_la_SOURCES = \ common/Readahead.cc \ common/Cycles.cc \ common/ContextCompletion.cc \ - common/TracepointProvider.cc + common/TracepointProvider.cc \ + common/PluginRegistry.cc if ENABLE_SERVER libcommon_internal_la_SOURCES += \ @@ -260,7 +261,7 @@ noinst_HEADERS += \ common/SubProcess.h \ common/valgrind.h \ common/TracepointProvider.h \ - common/event_socket.h + common/PluginRegistry.h if ENABLE_XIO noinst_HEADERS += \ diff --git a/src/common/PluginRegistry.cc b/src/common/PluginRegistry.cc new file mode 100644 index 000000000000..dbf20fa30280 --- /dev/null +++ b/src/common/PluginRegistry.cc @@ -0,0 +1,208 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2013,2014 Cloudwatt + * Copyright (C) 2014 Red Hat + * + * Author: Loic Dachary + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include +#include + +#include "PluginRegistry.h" +#include "ceph_ver.h" +#include "common/ceph_context.h" +#include "common/errno.h" +#include "include/str_list.h" + +#include "common/debug.h" + +#define PLUGIN_PREFIX "libceph_" +#define PLUGIN_SUFFIX ".so" +#define PLUGIN_INIT_FUNCTION "__ceph_plugin_init" +#define PLUGIN_VERSION_FUNCTION "__ceph_version" + +#define dout_subsys ceph_subsys_context + +PluginRegistry::PluginRegistry(CephContext *cct) : + cct(cct), + lock("PluginRegistry::lock"), + loading(false), + disable_dlclose(false) +{ +} + +PluginRegistry::~PluginRegistry() +{ + if (disable_dlclose) + return; + + for (std::map >::iterator i = + plugins.begin(); + i != plugins.end(); + ++i) { + for (std::map::iterator j = i->second.begin(); + j != i->second.end(); ++j) { + void *library = j->second->library; + delete j->second; + dlclose(library); + } + } +} + +int PluginRegistry::remove(const std::string& type, const std::string& name) +{ + assert(lock.is_locked()); + + std::map >::iterator i = + plugins.find(type); + if (i == plugins.end()) + return -ENOENT; + std::map::iterator j = i->second.find(type); + if (j == i->second.end()) + return -ENOENT; + + ldout(cct, 1) << __func__ << " " << type << " " << name << dendl; + void *library = j->second->library; + delete j->second; + dlclose(library); + i->second.erase(j); + if (i->second.empty()) + plugins.erase(i); + + return 0; +} + +int PluginRegistry::add(const std::string& type, + const std::string& name, + Plugin* plugin) +{ + assert(lock.is_locked()); + if (plugins.count(type) && + plugins[type].count(name)) { + return -EEXIST; + } + ldout(cct, 1) << __func__ << " " << type << " " << name + << " " << plugin << dendl; + plugins[type][name] = plugin; + return 0; +} + +Plugin *PluginRegistry::get(const std::string& type, + const std::string& name) +{ + assert(lock.is_locked()); + Plugin *ret = 0; + + std::map::iterator j; + std::map >::iterator i = + plugins.find(type); + if (i == plugins.end()) + goto out; + j = i->second.find(type); + if (j == i->second.end()) + goto out; + ret = j->second; + + out: + ldout(cct, 1) << __func__ << " " << type << " " << name + << " = " << ret << dendl; + return ret; +} + +int PluginRegistry::load(const std::string &type, + const std::string &name) +{ + assert(lock.is_locked()); + ldout(cct, 10) << __func__ << " " << type << " " << name << dendl; + + std::string fname = cct->_conf->plugin_dir + "/" + type + "/" PLUGIN_PREFIX + + name + PLUGIN_SUFFIX; + void *library = dlopen(fname.c_str(), RTLD_NOW); + if (!library) { + lderr(cct) << __func__ << " failed dlopen(" << fname << "): " + << dlerror() << dendl; + return -EIO; + } + + const char * (*code_version)() = + (const char *(*)())dlsym(library, PLUGIN_VERSION_FUNCTION); + if (code_version == NULL) { + return -EXDEV; + } + if (code_version() != string(CEPH_GIT_NICE_VER)) { + lderr(cct) << __func__ << " plugin " << fname << " version " + << code_version() << " != expected " + << CEPH_GIT_NICE_VER << dendl; + dlclose(library); + return -EXDEV; + } + + int (*code_init)(CephContext *, + const std::string& type, + const std::string& name) = + (int (*)(CephContext *, + const std::string& type, + const std::string& name))dlsym(library, PLUGIN_INIT_FUNCTION); + if (code_init) { + int r = code_init(cct, type, name); + if (r != 0) { + lderr(cct) << __func__ << " " << fname << " " + << PLUGIN_INIT_FUNCTION << "(" << cct + << "," << type << "," << name << "): " << cpp_strerror(r) + << dendl; + dlclose(library); + return r; + } + } else { + lderr(cct) << __func__ << " " << fname << " dlsym(" << PLUGIN_INIT_FUNCTION + << "): " << dlerror() << dendl; + dlclose(library); + return -ENOENT; + } + + Plugin *plugin = get(type, name); + if (plugin == 0) { + lderr(cct) << __func__ << " " << fname << " " + << PLUGIN_INIT_FUNCTION << "()" + << "did not register plugin type " << type << " name " << name + << dendl; + dlclose(library); + return -EBADF; + } + + plugin->library = library; + + ldout(cct, 1) << __func__ << ": " << type << " " << name + << " loaded and registered" << dendl; + return 0; +} + +/* +int ErasureCodePluginRegistry::preload(const std::string &plugins, + const std::string &directory, + ostream &ss) +{ + Mutex::Locker l(lock); + list plugins_list; + get_str_list(plugins, plugins_list); + for (list::iterator i = plugins_list.begin(); + i != plugins_list.end(); + ++i) { + ErasureCodePlugin *plugin; + int r = load(*i, directory, &plugin, ss); + if (r) + return r; + } + return 0; +} +*/ diff --git a/src/common/PluginRegistry.h b/src/common/PluginRegistry.h new file mode 100644 index 000000000000..b54fc6d3c1a1 --- /dev/null +++ b/src/common/PluginRegistry.h @@ -0,0 +1,69 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2013,2014 Cloudwatt + * Copyright (C) 2014 Red Hat + * + * Author: Loic Dachary + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#ifndef CEPH_COMMON_PLUGINREGISTRY_H +#define CEPH_COMMON_PLUGINREGISTERY_H + +#include +#include + +#include "common/Mutex.h" + +class CephContext; + +extern "C" { + const char *__ceph_plugin_version(); + int __ceph_plugin_init(CephContext *cct, + const std::string& type, + const std::string& name); +} + +namespace ceph { + + class Plugin { + public: + void *library; + CephContext *cct; + + Plugin(CephContext *cct) : cct(cct) {} + virtual ~Plugin() {} + }; + + class PluginRegistry { + public: + CephContext *cct; + Mutex lock; + bool loading; + bool disable_dlclose; + std::map > plugins; + + PluginRegistry(CephContext *cct); + ~PluginRegistry(); + + int add(const std::string& type, const std::string& name, + Plugin *factory); + int remove(const std::string& type, const std::string& name); + Plugin *get(const std::string& type, const std::string& name); + + int load(const std::string& type, + const std::string& name); + int preload(); + int preload(const std::string& type); + }; +} + +#endif diff --git a/src/common/ceph_context.cc b/src/common/ceph_context.cc index 6e60cf7a2165..71a00eca674f 100644 --- a/src/common/ceph_context.cc +++ b/src/common/ceph_context.cc @@ -32,6 +32,7 @@ #include "include/str_list.h" #include "common/Mutex.h" #include "common/Cond.h" +#include "common/PluginRegistry.h" #include #include @@ -414,7 +415,8 @@ CephContext::CephContext(uint32_t module_type_, int init_flags_) _crypto_none(NULL), _crypto_aes(NULL), _lockdep_obs(NULL), - _cct_perf(NULL) + _cct_perf(NULL), + plugin_registry(NULL) { ceph_spin_init(&_service_thread_lock); ceph_spin_init(&_associated_objs_lock); @@ -438,6 +440,8 @@ CephContext::CephContext(uint32_t module_type_, int init_flags_) _admin_socket = new AdminSocket(this); _heartbeat_map = new HeartbeatMap(this); + _plugin_registry = new PluginRegistry(this); + _admin_hook = new CephContextHook(this); _admin_socket->register_command("perfcounters_dump", "perfcounters_dump", _admin_hook, ""); _admin_socket->register_command("1", "1", _admin_hook, ""); @@ -474,6 +478,8 @@ CephContext::~CephContext() _cct_perf = NULL; } + delete _plugin_registry; + _admin_socket->unregister_command("perfcounters_dump"); _admin_socket->unregister_command("perf dump"); _admin_socket->unregister_command("1"); @@ -587,11 +593,6 @@ uint32_t CephContext::get_module_type() const return _module_type; } -int CephContext::get_init_flags() const -{ - return _init_flags; -} - PerfCountersCollection *CephContext::get_perfcounters_collection() { return _perf_counters_collection; diff --git a/src/common/ceph_context.h b/src/common/ceph_context.h index 3820a2355ead..cc029b4a1f85 100644 --- a/src/common/ceph_context.h +++ b/src/common/ceph_context.h @@ -38,6 +38,7 @@ class CephContextObs; class CryptoHandler; namespace ceph { + class PluginRegistry; class HeartbeatMap; namespace log { class Log; @@ -151,6 +152,10 @@ public: bool check_experimental_feature_enabled(const std::string& feature, std::ostream *message); + PluginRegistry *get_plugin_registry() { + return _plugin_registry; + } + private: struct SingletonWrapper : boost::noncopyable { virtual ~SingletonWrapper() {} @@ -213,6 +218,8 @@ private: ceph_spinlock_t _feature_lock; std::set _experimental_features; + PluginRegistry *_plugin_registry; + md_config_obs_t *_lockdep_obs; enum { diff --git a/src/common/config_opts.h b/src/common/config_opts.h index a19cc5d8ff78..8092f385c677 100644 --- a/src/common/config_opts.h +++ b/src/common/config_opts.h @@ -69,6 +69,8 @@ OPTION(mon_cluster_log_file_level, OPT_STR, "info") OPTION(enable_experimental_unrecoverable_data_corrupting_features, OPT_STR, "") +OPTION(plugin_dir, OPT_STR, CEPH_PKGLIBDIR) + OPTION(xio_trace_mempool, OPT_BOOL, false) // mempool allocation counters OPTION(xio_trace_msgcnt, OPT_BOOL, false) // incoming/outgoing msg counters OPTION(xio_trace_xcon, OPT_BOOL, false) // Xio message encode/decode trace