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>
%{_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*
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
cls_cephfs
ceph-fuse
ceph-dencoder
+ ceph-dencoder-modules
cephfs-journal-tool
cephfs-meta-injection
cephfs-data-scan
ceph-mon
get_command_descriptions
ceph-dencoder
+ ceph-dencoder-modules
ceph-objectstore-tool
ceph-kvstore-tool
ceph-monstore-tool
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})
*/
+#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"
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;
#include "denc_registry.h"
-void register_common_dencoders()
+DENC_API void register_dencoders()
{
#include "common_types.h"
}
#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")]]
#include "denc_registry.h"
-void register_mds_dencoders()
+DENC_API void register_dencoders()
{
#include "mds_types.h"
}
// 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"
}
#include "denc_registry.h"
-void register_rbd_dencoders()
+DENC_API void register_dencoders()
{
#include "rbd_types.h"
}
#include "denc_registry.h"
-void register_rgw_dencoders()
+DENC_API void register_dencoders()
{
#include "rgw_types.h"
}