]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/ceph-dencoder: build dencoders as plugins 40451/head
authorKefu Chai <kchai@redhat.com>
Sat, 27 Mar 2021 16:56:39 +0000 (00:56 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 1 Apr 2021 07:46:22 +0000 (15:46 +0800)
to reduce the memory footprint when linking ceph-dencoder.

* src/tools/ceph-dencoder:
  * build dencoders as shared libraries named with the prefix of
    "den-mod-". so ceph-dencoder can find them
  * install dencoders into $prefix/lib/ceph/denc, so ceph-dencoder
    can find them
  * only expose "register_dencoders()" function from plugins.
  * load plugins in specified directory
* ceph.spec.in: package plugins
* debian: package plugins

Signed-off-by: Kefu Chai <kchai@redhat.com>
12 files changed:
ceph.spec.in
debian/ceph-common.install
src/CMakeLists.txt
src/test/CMakeLists.txt
src/tools/ceph-dencoder/CMakeLists.txt
src/tools/ceph-dencoder/ceph_dencoder.cc
src/tools/ceph-dencoder/common_types.cc
src/tools/ceph-dencoder/denc_registry.h
src/tools/ceph-dencoder/mds_types.cc
src/tools/ceph-dencoder/osd_types.cc
src/tools/ceph-dencoder/rbd_types.cc
src/tools/ceph-dencoder/rgw_types.cc

index 94ff292ecce0f88a80a1763e4106e5b298b4edc4..08000289c701a638966f135b5c24cef33d9a8f77 100644 (file)
@@ -1591,6 +1591,7 @@ exit 0
 %{_bindir}/rbd-replay-prep
 %endif
 %{_bindir}/ceph-post-file
+%{_libdir}/ceph/denc/denc-mod-*.so
 %{_tmpfilesdir}/ceph-common.conf
 %{_mandir}/man8/ceph-authtool.8*
 %{_mandir}/man8/ceph-conf.8*
index b84a3164d3ea22b6512fbac06156586853378868..b1c5769fd53e2969f3c828f48586f67b1338987d 100755 (executable)
@@ -23,6 +23,7 @@ usr/bin/rbd-replay*
 usr/bin/ceph-post-file
 usr/sbin/mount.ceph sbin
 usr/lib/ceph/compressor/*
+usr/lib/ceph/denc/*
 usr/lib/ceph/crypto/* [amd64]
 usr/share/man/man8/ceph-authtool.8
 usr/share/man/man8/ceph-conf.8
index b12e6036715a6f33345b2ce4145cecf7cb968e35..88d2d0eb5500a86c4f08e6ed23e2971f9912a170 100644 (file)
@@ -954,6 +954,7 @@ add_custom_target(cephfs_testing DEPENDS
     cls_cephfs
     ceph-fuse
     ceph-dencoder
+    ceph-dencoder-modules
     cephfs-journal-tool
     cephfs-meta-injection
     cephfs-data-scan
index 3c7625d93eba5e9270b03e7139baec3a90052562..da487ca6f2a7b736b604ab3ac7819997e5d7842c 100644 (file)
@@ -531,6 +531,7 @@ if(NOT WIN32)
   ceph-mon
   get_command_descriptions
   ceph-dencoder
+  ceph-dencoder-modules
   ceph-objectstore-tool
   ceph-kvstore-tool
   ceph-monstore-tool
index 869904ebb407d80c300ad515e7f1a519bea13ae3..dd5541cd93e91716cb9dfcb482f727421a893e03 100644 (file)
@@ -11,67 +11,93 @@ endif()
 set(dencoder_srcs
   denc_registry.cc
   ceph_dencoder.cc
-  common_types.cc
-  mds_types.cc
-  osd_types.cc
-  rbd_types.cc
-  rgw_types.cc
   ../../include/uuid.cc
   ../../include/utime.cc
   $<TARGET_OBJECTS:common_texttable_obj>)
-if(WITH_RADOSGW)
-  list(APPEND dencoder_srcs
-    ${CMAKE_SOURCE_DIR}/src/rgw/rgw_dencoder.cc)
-endif()
-
 add_executable(ceph-dencoder ${dencoder_srcs})
 
+set(denc_plugin_dir ${CEPH_INSTALL_PKGLIBDIR}/denc)
+add_custom_target(ceph-dencoder-modules)
+
+function(add_denc_mod name)
+  add_library(${name} SHARED
+    ${ARGN})
+  set_target_properties(${name} PROPERTIES
+    PREFIX ""
+    OUTPUT_NAME ${name}
+    CXX_VISIBILITY_PRESET hidden
+    VISIBILITY_INLINES_HIDDEN ON)
+  install(
+    TARGETS ${name}
+    DESTINATION ${denc_plugin_dir})
+  add_dependencies(ceph-dencoder-modules
+    ${name})
+endfunction()
+
+add_denc_mod(denc-mod-common
+  common_types.cc)
+target_link_libraries(denc-mod-common
+  journal
+  cls_cas_internal
+  cls_lock_client
+  cls_refcount_client
+  cls_timeindex_client)
+add_denc_mod(denc-mod-osd
+  osd_types.cc)
+target_link_libraries(denc-mod-osd
+  os
+  osd
+  mon)
+
 if(WITH_RADOSGW)
-  list(APPEND DENCODER_EXTRALIBS
+  add_denc_mod(denc-mod-rgw
+    rgw_types.cc
+    ${CMAKE_SOURCE_DIR}/src/rgw/rgw_dencoder.cc)
+  target_link_libraries(denc-mod-rgw
     rgw_a
-    cls_rgw_client)
+    cls_rgw_client
+    cls_journal_client)
   if(WITH_RADOSGW_AMQP_ENDPOINT)
-    list(APPEND DENCODER_EXTRALIBS
+    target_link_libraries(denc-mod-rgw
       rabbitmq ssl)
   endif()
   if(WITH_RADOSGW_KAFKA_ENDPOINT)
-    list(APPEND DENCODER_EXTRALIBS
+    target_link_libraries(denc-mod-rgw
       rdkafka)
   endif()
 endif()
 
 if(WITH_RBD)
-  list(APPEND DENCODER_EXTRALIBS
+  add_denc_mod(denc-mod-rbd
+    rbd_types.cc)
+  target_link_libraries(denc-mod-rbd
     cls_rbd_client
     rbd_mirror_types
     rbd_types
     rbd_replay_types)
   if(WITH_KRBD)
-    list(APPEND DENCODER_EXTRALIBS
+    target_link_libraries(denc-mod-rbd
       krbd)
   endif()
 endif()
 
 if(WITH_CEPHFS)
-  list(APPEND DENCODER_EXTRALIBS
+  add_denc_mod(denc-mod-cephfs
+    mds_types.cc)
+  target_link_libraries(denc-mod-cephfs
     mds)
 endif()
 
+target_compile_definitions(ceph-dencoder PRIVATE
+  "CEPH_DENC_MOD_DIR=\"${denc_plugin_dir}\"")
+
 target_link_libraries(ceph-dencoder
+  StdFilesystem::filesystem
   global
-  os
-  osd
-  mon
-  journal
   ${DENCODER_EXTRALIBS}
-  cls_lock_client
-  cls_refcount_client
   cls_log_client
   cls_version_client
   cls_user_client
-  cls_journal_client
-  cls_timeindex_client
-  cls_cas_internal
   cls_cas_client
   ${EXTRALIBS}
   ${CMAKE_DL_LIBS})
index 87091561b39a3370b645a26ed654b76b48157948..2bb73db0854e272f4b250b2c1ad64eb857b0ff6a 100644 (file)
  */
 
 
+#include <dlfcn.h>
 #include <errno.h>
+
+#if __has_include(<filesystem>)
+#include <filesystem>
+namespace fs = std::filesystem;
+#else
+#include <experimental/filesystem>
+namespace fs = std::experimental::filesystem;
+#endif
+
 #include "ceph_ver.h"
 #include "include/types.h"
 #include "common/Formatter.h"
@@ -52,15 +62,73 @@ void usage(ostream &out)
   out << "  select_test <n>     select generated test object as in-memory object\n";
   out << "  is_deterministic    exit w/ success if type encodes deterministically\n";
 }
-  
-int main(int argc, const char **argv)
+
+static constexpr string_view REGISTER_DENCODERS_FUNCTION = "register_dencoders\0";
+
+class DencoderPlugin {
+public:
+  DencoderPlugin(const fs::path& path) {
+    mod = dlopen(path.c_str(), RTLD_NOW);
+    if (mod == nullptr) {
+      std::cerr << "failed to dlopen(" << path << "): " << dlerror() << std::endl;
+    }
+  }
+  ~DencoderPlugin() {
+    if (mod) {
+      dlclose(mod);
+    }
+  }
+  int register_dencoders() {
+    assert(mod);
+    using register_dencoders_t = void (*)();
+    const auto register_dencoders =
+      reinterpret_cast<register_dencoders_t>(dlsym(mod, REGISTER_DENCODERS_FUNCTION.data()));
+    if (register_dencoders == nullptr) {
+      std::cerr << "failed to dlsym(" << REGISTER_DENCODERS_FUNCTION << ")" << std::endl;
+      return -1;
+    }
+    const unsigned nr_before = DencoderRegistry::instance().get().size();
+    register_dencoders();
+    const unsigned nr_after = DencoderRegistry::instance().get().size();
+    return nr_after - nr_before;
+  }
+  bool good() const {
+    return mod != nullptr;
+  }
+private:
+  void *mod = nullptr;
+};
+
+vector<DencoderPlugin> load_plugins()
 {
-  register_common_dencoders();
-  register_mds_dencoders();
-  register_osd_dencoders();
-  register_rbd_dencoders();
-  register_rgw_dencoders();
+  fs::path mod_dir{CEPH_DENC_MOD_DIR};
+  if (auto ceph_lib = getenv("CEPH_LIB"); ceph_lib) {
+    mod_dir = ceph_lib;
+  }
+  vector<DencoderPlugin> dencoder_plugins;
+  for (auto& entry : fs::directory_iterator(mod_dir)) {
+    static const string_view DENC_MOD_PREFIX = "denc-mod-";
+    if (entry.path().stem().string().compare(0, DENC_MOD_PREFIX.size(),
+                                            DENC_MOD_PREFIX) != 0) {
+      continue;
+    }
+    DencoderPlugin plugin(entry);
+    if (!plugin.good()) {
+      continue;
+    }
+    int n = plugin.register_dencoders();
+    if (n <= 0) {
+      std::cerr << "fail to load dencoders from " << entry << std::endl;
+      continue;
+    }
+    dencoder_plugins.push_back(std::move(plugin));
+  }
+  return dencoder_plugins;
+}
 
+int main(int argc, const char **argv)
+{
+  auto plugins = load_plugins();
   auto& dencoders = DencoderRegistry::instance().get();
 
   vector<const char*> args;
index 889a9e99e1cdcc20f68a13e396bc5fc91cdfe515..86c08c51211c7e40f2e8f1a56d5121c1fb5cf9db 100644 (file)
@@ -25,7 +25,7 @@ using namespace std;
 
 #include "denc_registry.h"
 
-void register_common_dencoders()
+DENC_API void register_dencoders()
 {
 #include "common_types.h"
 }
index 74c7be97db7e674521c684bbd923e5e9b1394e27..a5bc2b261df0d4b0ce68db5c6e44568d159204ed 100644 (file)
@@ -253,8 +253,4 @@ void make_and_register_dencoder(const char* name, Args&&...args)
 #define TYPE_NOCOPY(t) make_and_register_dencoder<DencoderImplNoFeatureNoCopy<t>>(#t, false, false);
 #define MESSAGE(t) make_and_register_dencoder<MessageDencoderImpl<t>>(#t);
 
-void register_common_dencoders();
-void register_mds_dencoders();
-void register_osd_dencoders();
-void register_rbd_dencoders();
-void register_rgw_dencoders();
+#define DENC_API extern "C" [[gnu::visibility("default")]]
index 5bec4bb146cfc500d2723d97bdb4f521ec4db759..d28306cbf6b9efb91907a841a2192239062ba00f 100644 (file)
@@ -25,7 +25,7 @@ using namespace std;
 
 #include "denc_registry.h"
 
-void register_mds_dencoders()
+DENC_API void register_dencoders()
 {
 #include "mds_types.h"
 }
index c0b82d4f36b73149e8b069c3699220d29cd64c0a..d21e904b9cc5bcdee894bc90e8ee7c2f489729e4 100644 (file)
@@ -28,7 +28,7 @@ using namespace std;
 // cannot initialize dencoders when initializing static variables, as some of
 // the types are allocated using mempool, and the mempools are initialized as
 // static variables.
-void register_osd_dencoders()
+DENC_API void register_dencoders()
 {
 #include "osd_types.h"
 }
index 6327d1904a19a476bc00f0c0f0cda02ff26fc7f8..a9ffe74aea5c914716350d18e24fa86c466aea43 100644 (file)
@@ -25,7 +25,7 @@ using namespace std;
 
 #include "denc_registry.h"
 
-void register_rbd_dencoders()
+DENC_API void register_dencoders()
 {
 #include "rbd_types.h"
 }
index 82dde00d24ee60f9f6a5b30cb32eb97d085dc5fa..de557cda54de7b9d22015f04950fe068d54cbccb 100644 (file)
@@ -25,7 +25,7 @@ using namespace std;
 
 #include "denc_registry.h"
 
-void register_rgw_dencoders()
+DENC_API void register_dencoders()
 {
 #include "rgw_types.h"
 }