]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/PluginRegistry.cc
import quincy beta 17.1.0
[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
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
32using std::map;
33using std::string;
34
35namespace ceph {
36
7c673cae
FG
37PluginRegistry::PluginRegistry(CephContext *cct) :
38 cct(cct),
7c673cae
FG
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{
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
85int 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
100Plugin *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
113Plugin *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
135int 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/*
215int 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*/