summaryrefslogtreecommitdiffstats
path: root/src/tools/ceph-dencoder/denc_plugin.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/tools/ceph-dencoder/denc_plugin.h
parentInitial commit. (diff)
downloadceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz
ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/ceph-dencoder/denc_plugin.h')
-rw-r--r--src/tools/ceph-dencoder/denc_plugin.h78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/tools/ceph-dencoder/denc_plugin.h b/src/tools/ceph-dencoder/denc_plugin.h
new file mode 100644
index 000000000..a203551ea
--- /dev/null
+++ b/src/tools/ceph-dencoder/denc_plugin.h
@@ -0,0 +1,78 @@
+#include <dlfcn.h>
+#include <filesystem>
+#include <vector>
+
+#include "denc_registry.h"
+
+namespace fs = std::filesystem;
+
+class DencoderPlugin {
+ using dencoders_t = std::vector<std::pair<std::string, Dencoder*>>;
+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(DencoderPlugin&& other)
+ : mod{other.mod},
+ dencoders{std::move(other.dencoders)}
+ {
+ other.mod = nullptr;
+ other.dencoders.clear();
+ }
+ ~DencoderPlugin() {
+#if !defined(__FreeBSD__)
+ if (mod) {
+ dlclose(mod);
+ }
+#endif
+ }
+ const dencoders_t& register_dencoders() {
+ static constexpr std::string_view REGISTER_DENCODERS_FUNCTION = "register_dencoders\0";
+
+ assert(mod);
+ using register_dencoders_t = void (*)(DencoderPlugin*);
+ const auto do_register =
+ reinterpret_cast<register_dencoders_t>(dlsym(mod, REGISTER_DENCODERS_FUNCTION.data()));
+ if (do_register == nullptr) {
+ std::cerr << "failed to dlsym(" << REGISTER_DENCODERS_FUNCTION << "): "
+ << dlerror() << std::endl;
+ return dencoders;
+ }
+ do_register(this);
+ return dencoders;
+ }
+
+ bool good() const {
+ return mod != nullptr;
+ }
+
+ void unregister_dencoders() {
+ while (!dencoders.empty()) {
+ delete dencoders.back().second;
+ dencoders.pop_back();
+ }
+ }
+ template<typename DencoderT, typename...Args>
+ void emplace(const char* name, Args&&...args) {
+ dencoders.emplace_back(name, new DencoderT(std::forward<Args>(args)...));
+ }
+
+private:
+ void *mod = nullptr;
+ dencoders_t dencoders;
+};
+
+#define TYPE(t) plugin->emplace<DencoderImplNoFeature<t>>(#t, false, false);
+#define TYPE_STRAYDATA(t) plugin->emplace<DencoderImplNoFeature<t>>(#t, true, false);
+#define TYPE_NONDETERMINISTIC(t) plugin->emplace<DencoderImplNoFeature<t>>(#t, false, true);
+#define TYPE_FEATUREFUL(t) plugin->emplace<DencoderImplFeatureful<t>>(#t, false, false);
+#define TYPE_FEATUREFUL_STRAYDATA(t) plugin->emplace<DencoderImplFeatureful<t>>(#t, true, false);
+#define TYPE_FEATUREFUL_NONDETERMINISTIC(t) plugin->emplace<DencoderImplFeatureful<t>>(#t, false, true);
+#define TYPE_FEATUREFUL_NOCOPY(t) plugin->emplace<DencoderImplFeaturefulNoCopy<t>>(#t, false, false);
+#define TYPE_NOCOPY(t) plugin->emplace<DencoderImplNoFeatureNoCopy<t>>(#t, false, false);
+#define MESSAGE(t) plugin->emplace<MessageDencoderImpl<t>>(#t);
+
+#define DENC_API extern "C" [[gnu::visibility("default")]]