1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph distributed storage system
6 * Copyright (C) 2013,2014 Cloudwatt <libre.licensing@cloudwatt.com>
7 * Copyright (C) 2014 Red Hat <contact@redhat.com>
9 * Author: Loic Dachary <loic@dachary.org>
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
22 #include "ErasureCodePlugin.h"
23 #include "common/errno.h"
24 #include "include/str_list.h"
28 #define PLUGIN_PREFIX "libec_"
30 #define PLUGIN_SUFFIX ".dylib"
32 #define PLUGIN_SUFFIX ".so"
34 #define PLUGIN_INIT_FUNCTION "__erasure_code_init"
35 #define PLUGIN_VERSION_FUNCTION "__erasure_code_version"
37 ErasureCodePluginRegistry ErasureCodePluginRegistry::singleton;
39 ErasureCodePluginRegistry::ErasureCodePluginRegistry() :
40 lock("ErasureCodePluginRegistry::lock"),
42 disable_dlclose(false)
46 ErasureCodePluginRegistry::~ErasureCodePluginRegistry()
51 for (std::map<std::string,ErasureCodePlugin*>::iterator i = plugins.begin();
54 void *library = i->second->library;
60 int ErasureCodePluginRegistry::remove(const std::string &name)
62 assert(lock.is_locked());
63 if (plugins.find(name) == plugins.end())
65 std::map<std::string,ErasureCodePlugin*>::iterator plugin = plugins.find(name);
66 void *library = plugin->second->library;
67 delete plugin->second;
69 plugins.erase(plugin);
73 int ErasureCodePluginRegistry::add(const std::string &name,
74 ErasureCodePlugin* plugin)
76 assert(lock.is_locked());
77 if (plugins.find(name) != plugins.end())
79 plugins[name] = plugin;
83 ErasureCodePlugin *ErasureCodePluginRegistry::get(const std::string &name)
85 assert(lock.is_locked());
86 if (plugins.find(name) != plugins.end())
92 int ErasureCodePluginRegistry::factory(const std::string &plugin_name,
93 const std::string &directory,
94 ErasureCodeProfile &profile,
95 ErasureCodeInterfaceRef *erasure_code,
98 ErasureCodePlugin *plugin;
100 Mutex::Locker l(lock);
101 plugin = get(plugin_name);
104 int r = load(plugin_name, directory, &plugin, ss);
111 int r = plugin->factory(directory, profile, erasure_code, ss);
114 if (profile != (*erasure_code)->get_profile()) {
115 *ss << __func__ << " profile " << profile << " != get_profile() "
116 << (*erasure_code)->get_profile() << std::endl;
122 static const char *an_older_version() {
123 return "an older version";
126 int ErasureCodePluginRegistry::load(const std::string &plugin_name,
127 const std::string &directory,
128 ErasureCodePlugin **plugin,
131 assert(lock.is_locked());
132 std::string fname = directory + "/" PLUGIN_PREFIX
133 + plugin_name + PLUGIN_SUFFIX;
134 void *library = dlopen(fname.c_str(), RTLD_NOW);
136 *ss << "load dlopen(" << fname << "): " << dlerror();
140 const char * (*erasure_code_version)() =
141 (const char *(*)())dlsym(library, PLUGIN_VERSION_FUNCTION);
142 if (erasure_code_version == NULL)
143 erasure_code_version = an_older_version;
144 if (erasure_code_version() != string(CEPH_GIT_NICE_VER)) {
145 *ss << "expected plugin " << fname << " version " << CEPH_GIT_NICE_VER
146 << " but it claims to be " << erasure_code_version() << " instead";
151 int (*erasure_code_init)(const char *, const char *) =
152 (int (*)(const char *, const char *))dlsym(library, PLUGIN_INIT_FUNCTION);
153 if (erasure_code_init) {
154 std::string name = plugin_name;
155 int r = erasure_code_init(name.c_str(), directory.c_str());
157 *ss << "erasure_code_init(" << plugin_name
159 << "): " << cpp_strerror(r);
164 *ss << "load dlsym(" << fname
165 << ", " << PLUGIN_INIT_FUNCTION
166 << "): " << dlerror();
171 *plugin = get(plugin_name);
173 *ss << "load " << PLUGIN_INIT_FUNCTION << "()"
174 << "did not register " << plugin_name;
179 (*plugin)->library = library;
181 *ss << __func__ << ": " << plugin_name << " ";
186 int ErasureCodePluginRegistry::preload(const std::string &plugins,
187 const std::string &directory,
190 Mutex::Locker l(lock);
191 list<string> plugins_list;
192 get_str_list(plugins, plugins_list);
193 for (list<string>::iterator i = plugins_list.begin();
194 i != plugins_list.end();
196 ErasureCodePlugin *plugin;
197 int r = load(*i, directory, &plugin, ss);