]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/PluginRegistry.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / PluginRegistry.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph distributed storage system
5 *
6 * Copyright (C) 2013,2014 Cloudwatt <libre.licensing@cloudwatt.com>
7 * Copyright (C) 2014 Red Hat <contact@redhat.com>
8 *
9 * Author: Loic Dachary <loic@dachary.org>
10 *
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.
15 *
16 */
17
18#include <errno.h>
19#include <dlfcn.h>
20
21#include "PluginRegistry.h"
22#include "ceph_ver.h"
23#include "common/ceph_context.h"
24#include "common/errno.h"
25#include "include/str_list.h"
26
27#include "common/debug.h"
28
29#define PLUGIN_PREFIX "libceph_"
30#define PLUGIN_SUFFIX ".so"
31#define PLUGIN_INIT_FUNCTION "__ceph_plugin_init"
32#define PLUGIN_VERSION_FUNCTION "__ceph_plugin_version"
33
34#define dout_subsys ceph_subsys_context
35
36PluginRegistry::PluginRegistry(CephContext *cct) :
37 cct(cct),
38 lock("PluginRegistry::lock"),
39 loading(false),
40 disable_dlclose(false)
41{
42}
43
44PluginRegistry::~PluginRegistry()
45{
46 if (disable_dlclose)
47 return;
48
49 for (std::map<std::string,std::map<std::string, Plugin*> >::iterator i =
50 plugins.begin();
51 i != plugins.end();
52 ++i) {
53 for (std::map<std::string,Plugin*>::iterator j = i->second.begin();
54 j != i->second.end(); ++j) {
55 void *library = j->second->library;
56 delete j->second;
57 dlclose(library);
58 }
59 }
60}
61
62int PluginRegistry::remove(const std::string& type, const std::string& name)
63{
64 assert(lock.is_locked());
65
66 std::map<std::string,std::map<std::string,Plugin*> >::iterator i =
67 plugins.find(type);
68 if (i == plugins.end())
69 return -ENOENT;
70 std::map<std::string,Plugin*>::iterator j = i->second.find(name);
71 if (j == i->second.end())
72 return -ENOENT;
73
74 ldout(cct, 1) << __func__ << " " << type << " " << name << dendl;
75 void *library = j->second->library;
76 delete j->second;
77 dlclose(library);
78 i->second.erase(j);
79 if (i->second.empty())
80 plugins.erase(i);
81
82 return 0;
83}
84
85int PluginRegistry::add(const std::string& type,
86 const std::string& name,
87 Plugin* plugin)
88{
89 assert(lock.is_locked());
90 if (plugins.count(type) &&
91 plugins[type].count(name)) {
92 return -EEXIST;
93 }
94 ldout(cct, 1) << __func__ << " " << type << " " << name
95 << " " << plugin << dendl;
96 plugins[type][name] = plugin;
97 return 0;
98}
99
100Plugin *PluginRegistry::get_with_load(const std::string& type,
101 const std::string& name)
102{
103 Mutex::Locker l(lock);
104 Plugin* ret = get(type, name);
105 if (!ret) {
106 int err = load(type, name);
107 if (err == 0)
108 ret = get(type, name);
109 }
110 return ret;
111}
112
113Plugin *PluginRegistry::get(const std::string& type,
114 const std::string& name)
115{
116 assert(lock.is_locked());
117 Plugin *ret = 0;
118
119 std::map<std::string,Plugin*>::iterator j;
120 std::map<std::string,map<std::string,Plugin*> >::iterator i =
121 plugins.find(type);
122 if (i == plugins.end())
123 goto out;
124 j = i->second.find(name);
125 if (j == i->second.end())
126 goto out;
127 ret = j->second;
128
129 out:
130 ldout(cct, 1) << __func__ << " " << type << " " << name
131 << " = " << ret << dendl;
132 return ret;
133}
134
135int PluginRegistry::load(const std::string &type,
136 const std::string &name)
137{
138 assert(lock.is_locked());
139 ldout(cct, 1) << __func__ << " " << type << " " << name << dendl;
140
141 // std::string fname = cct->_conf->plugin_dir + "/" + type + "/" PLUGIN_PREFIX
142 // + name + PLUGIN_SUFFIX;
143 std::string fname = cct->_conf->get_val<std::string>("plugin_dir") + "/" + type + "/" + PLUGIN_PREFIX
144 + name + PLUGIN_SUFFIX;
145 void *library = dlopen(fname.c_str(), RTLD_NOW);
146 if (!library) {
147 string err1(dlerror());
148 // fall back to plugin_dir
149 std::string fname2 = cct->_conf->get_val<std::string>("plugin_dir") + "/" + PLUGIN_PREFIX +
150 name + PLUGIN_SUFFIX;
151 library = dlopen(fname2.c_str(), RTLD_NOW);
152 if (!library) {
153 lderr(cct) << __func__
154 << " failed dlopen(): \"" << err1.c_str()
155 << "\" or \"" << dlerror() << "\""
156 << dendl;
157 return -EIO;
158 }
159 }
160
161 const char * (*code_version)() =
162 (const char *(*)())dlsym(library, PLUGIN_VERSION_FUNCTION);
163 if (code_version == NULL) {
164 lderr(cct) << __func__ << " code_version == NULL" << dlerror() << dendl;
165 return -EXDEV;
166 }
167 if (code_version() != string(CEPH_GIT_NICE_VER)) {
168 lderr(cct) << __func__ << " plugin " << fname << " version "
169 << code_version() << " != expected "
170 << CEPH_GIT_NICE_VER << dendl;
171 dlclose(library);
172 return -EXDEV;
173 }
174
175 int (*code_init)(CephContext *,
176 const std::string& type,
177 const std::string& name) =
178 (int (*)(CephContext *,
179 const std::string& type,
180 const std::string& name))dlsym(library, PLUGIN_INIT_FUNCTION);
181 if (code_init) {
182 int r = code_init(cct, type, name);
183 if (r != 0) {
184 lderr(cct) << __func__ << " " << fname << " "
185 << PLUGIN_INIT_FUNCTION << "(" << cct
186 << "," << type << "," << name << "): " << cpp_strerror(r)
187 << dendl;
188 dlclose(library);
189 return r;
190 }
191 } else {
192 lderr(cct) << __func__ << " " << fname << " dlsym(" << PLUGIN_INIT_FUNCTION
193 << "): " << dlerror() << dendl;
194 dlclose(library);
195 return -ENOENT;
196 }
197
198 Plugin *plugin = get(type, name);
199 if (plugin == 0) {
200 lderr(cct) << __func__ << " " << fname << " "
201 << PLUGIN_INIT_FUNCTION << "()"
202 << "did not register plugin type " << type << " name " << name
203 << dendl;
204 dlclose(library);
205 return -EBADF;
206 }
207
208 plugin->library = library;
209
210 ldout(cct, 1) << __func__ << ": " << type << " " << name
211 << " loaded and registered" << dendl;
212 return 0;
213}
214
215/*
216int ErasureCodePluginRegistry::preload(const std::string &plugins,
217 const std::string &directory,
218 ostream &ss)
219{
220 Mutex::Locker l(lock);
221 list<string> plugins_list;
222 get_str_list(plugins, plugins_list);
223 for (list<string>::iterator i = plugins_list.begin();
224 i != plugins_list.end();
225 ++i) {
226 ErasureCodePlugin *plugin;
227 int r = load(*i, directory, &plugin, ss);
228 if (r)
229 return r;
230 }
231 return 0;
232}
233*/