]>
Commit | Line | Data |
---|---|---|
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 | ||
7c673cae FG |
18 | #include "PluginRegistry.h" |
19 | #include "ceph_ver.h" | |
11fdf7f2 | 20 | #include "common/ceph_context.h" |
7c673cae | 21 | #include "common/errno.h" |
7c673cae | 22 | #include "common/debug.h" |
f67539c2 | 23 | #include "include/dlfcn_compat.h" |
31f18b77 | 24 | |
7c673cae | 25 | #define PLUGIN_PREFIX "libceph_" |
f67539c2 | 26 | #define PLUGIN_SUFFIX SHARED_LIB_SUFFIX |
7c673cae FG |
27 | #define PLUGIN_INIT_FUNCTION "__ceph_plugin_init" |
28 | #define PLUGIN_VERSION_FUNCTION "__ceph_plugin_version" | |
29 | ||
30 | #define dout_subsys ceph_subsys_context | |
31 | ||
f67539c2 TL |
32 | using std::map; |
33 | using std::string; | |
34 | ||
35 | namespace ceph { | |
36 | ||
7c673cae FG |
37 | PluginRegistry::PluginRegistry(CephContext *cct) : |
38 | cct(cct), | |
7c673cae FG |
39 | loading(false), |
40 | disable_dlclose(false) | |
41 | { | |
42 | } | |
43 | ||
44 | PluginRegistry::~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 | ||
62 | int PluginRegistry::remove(const std::string& type, const std::string& name) | |
63 | { | |
11fdf7f2 | 64 | ceph_assert(ceph_mutex_is_locked(lock)); |
7c673cae FG |
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 | ||
85 | int PluginRegistry::add(const std::string& type, | |
86 | const std::string& name, | |
87 | Plugin* plugin) | |
88 | { | |
11fdf7f2 | 89 | ceph_assert(ceph_mutex_is_locked(lock)); |
7c673cae FG |
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 | ||
100 | Plugin *PluginRegistry::get_with_load(const std::string& type, | |
101 | const std::string& name) | |
102 | { | |
11fdf7f2 | 103 | std::lock_guard l(lock); |
7c673cae FG |
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 | ||
113 | Plugin *PluginRegistry::get(const std::string& type, | |
114 | const std::string& name) | |
115 | { | |
11fdf7f2 | 116 | ceph_assert(ceph_mutex_is_locked(lock)); |
7c673cae FG |
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 | ||
135 | int PluginRegistry::load(const std::string &type, | |
136 | const std::string &name) | |
137 | { | |
11fdf7f2 | 138 | ceph_assert(ceph_mutex_is_locked(lock)); |
7c673cae FG |
139 | ldout(cct, 1) << __func__ << " " << type << " " << name << dendl; |
140 | ||
11fdf7f2 | 141 | std::string fname = cct->_conf.get_val<std::string>("plugin_dir") + "/" + type + "/" + PLUGIN_PREFIX |
7c673cae FG |
142 | + name + PLUGIN_SUFFIX; |
143 | void *library = dlopen(fname.c_str(), RTLD_NOW); | |
144 | if (!library) { | |
145 | string err1(dlerror()); | |
146 | // fall back to plugin_dir | |
f67539c2 | 147 | fname = cct->_conf.get_val<std::string>("plugin_dir") + "/" + PLUGIN_PREFIX + |
7c673cae | 148 | name + PLUGIN_SUFFIX; |
f67539c2 | 149 | library = dlopen(fname.c_str(), RTLD_NOW); |
7c673cae FG |
150 | if (!library) { |
151 | lderr(cct) << __func__ | |
152 | << " failed dlopen(): \"" << err1.c_str() | |
153 | << "\" or \"" << dlerror() << "\"" | |
154 | << dendl; | |
155 | return -EIO; | |
156 | } | |
157 | } | |
158 | ||
159 | const char * (*code_version)() = | |
160 | (const char *(*)())dlsym(library, PLUGIN_VERSION_FUNCTION); | |
161 | if (code_version == NULL) { | |
162 | lderr(cct) << __func__ << " code_version == NULL" << dlerror() << dendl; | |
163 | return -EXDEV; | |
164 | } | |
165 | if (code_version() != string(CEPH_GIT_NICE_VER)) { | |
166 | lderr(cct) << __func__ << " plugin " << fname << " version " | |
167 | << code_version() << " != expected " | |
168 | << CEPH_GIT_NICE_VER << dendl; | |
169 | dlclose(library); | |
170 | return -EXDEV; | |
171 | } | |
172 | ||
173 | int (*code_init)(CephContext *, | |
174 | const std::string& type, | |
175 | const std::string& name) = | |
176 | (int (*)(CephContext *, | |
177 | const std::string& type, | |
178 | const std::string& name))dlsym(library, PLUGIN_INIT_FUNCTION); | |
179 | if (code_init) { | |
180 | int r = code_init(cct, type, name); | |
181 | if (r != 0) { | |
182 | lderr(cct) << __func__ << " " << fname << " " | |
183 | << PLUGIN_INIT_FUNCTION << "(" << cct | |
184 | << "," << type << "," << name << "): " << cpp_strerror(r) | |
185 | << dendl; | |
186 | dlclose(library); | |
187 | return r; | |
188 | } | |
189 | } else { | |
190 | lderr(cct) << __func__ << " " << fname << " dlsym(" << PLUGIN_INIT_FUNCTION | |
191 | << "): " << dlerror() << dendl; | |
192 | dlclose(library); | |
193 | return -ENOENT; | |
194 | } | |
195 | ||
196 | Plugin *plugin = get(type, name); | |
197 | if (plugin == 0) { | |
198 | lderr(cct) << __func__ << " " << fname << " " | |
199 | << PLUGIN_INIT_FUNCTION << "()" | |
200 | << "did not register plugin type " << type << " name " << name | |
201 | << dendl; | |
202 | dlclose(library); | |
203 | return -EBADF; | |
204 | } | |
205 | ||
206 | plugin->library = library; | |
207 | ||
208 | ldout(cct, 1) << __func__ << ": " << type << " " << name | |
209 | << " loaded and registered" << dendl; | |
210 | return 0; | |
211 | } | |
f67539c2 | 212 | } |
7c673cae FG |
213 | |
214 | /* | |
215 | int ErasureCodePluginRegistry::preload(const std::string &plugins, | |
216 | const std::string &directory, | |
217 | ostream &ss) | |
218 | { | |
11fdf7f2 | 219 | std::lock_guard l(lock); |
7c673cae FG |
220 | list<string> plugins_list; |
221 | get_str_list(plugins, plugins_list); | |
222 | for (list<string>::iterator i = plugins_list.begin(); | |
223 | i != plugins_list.end(); | |
224 | ++i) { | |
225 | ErasureCodePlugin *plugin; | |
226 | int r = load(*i, directory, &plugin, ss); | |
227 | if (r) | |
228 | return r; | |
229 | } | |
230 | return 0; | |
231 | } | |
232 | */ |