2
#include "include/types.h"
3
#include "msg/Message.h"
5
#include "ClassHandler.h"
11
#include "common/config.h"
13
#define DOUT_SUBSYS osd
15
#define dout_prefix *_dout
17
int ClassHandler::open_class(const string& cname, ClassData **pcls)
19
Mutex::Locker lock(mutex);
20
ClassData *cls = _get_class(cname);
21
if (cls->status != ClassData::CLASS_OPEN) {
22
int r = _load_class(cls);
30
ClassHandler::ClassData *ClassHandler::_get_class(const string& cname)
33
map<string, ClassData>::iterator iter = classes.find(cname);
35
if (iter != classes.end()) {
38
cls = &classes[cname];
39
dout(10) << "_get_class adding new class name " << cname << " " << cls << dendl;
46
int ClassHandler::_load_class(ClassData *cls)
49
if (cls->status == ClassData::CLASS_OPEN)
52
if (cls->status == ClassData::CLASS_UNKNOWN ||
53
cls->status == ClassData::CLASS_MISSING) {
55
snprintf(fname, sizeof(fname), "%s/libcls_%s.so",
56
g_conf->osd_class_dir.c_str(),
58
dout(10) << "_load_class " << cls->name << " from " << fname << dendl;
60
cls->handle = dlopen(fname, RTLD_NOW);
62
dout(0) << "_load_class could not open class " << fname
63
<< " (dlopen failed): " << dlerror() << dendl;
64
cls->status = ClassData::CLASS_MISSING;
68
cls_deps_t *(*cls_deps)();
69
cls_deps = (cls_deps_t *(*)())dlsym(cls->handle, "class_deps");
71
cls_deps_t *deps = cls_deps();
75
ClassData *cls_dep = _get_class(deps->name);
76
cls->dependencies.insert(cls_dep);
77
if (cls_dep->status != ClassData::CLASS_OPEN)
78
cls->missing_dependencies.insert(cls_dep);
84
// resolve dependencies
85
set<ClassData*>::iterator p = cls->missing_dependencies.begin();
86
while (p != cls->missing_dependencies.end()) {
88
int r = _load_class(dc);
90
cls->status = ClassData::CLASS_MISSING_DEPS;
94
dout(10) << "_load_class " << cls->name << " satisfied dependency " << dc->name << dendl;
95
cls->missing_dependencies.erase(p++);
99
void (*cls_init)() = (void (*)())dlsym(cls->handle, "__cls_init");
101
cls->status = ClassData::CLASS_INITIALIZING;
105
dout(10) << "_load_class " << cls->name << " success" << dendl;
106
cls->status = ClassData::CLASS_OPEN;
112
ClassHandler::ClassData *ClassHandler::register_class(const char *cname)
114
assert(mutex.is_locked());
116
ClassData *cls = _get_class(cname);
117
dout(10) << "register_class " << cname << " status " << cls->status << dendl;
119
if (cls->status != ClassData::CLASS_INITIALIZING) {
120
dout(0) << "class " << cname << " isn't loaded; is the class registering under the wrong name?" << dendl;
126
void ClassHandler::unregister_class(ClassHandler::ClassData *cls)
128
/* FIXME: do we really need this one? */
131
ClassHandler::ClassMethod *ClassHandler::ClassData::register_method(const char *mname,
133
cls_method_call_t func)
135
/* no need for locking, called under the class_init mutex */
136
dout(10) << "register_method " << name << "." << mname << " flags " << flags << " " << (void*)func << dendl;
137
ClassMethod& method = methods_map[mname];
140
method.flags = flags;
145
ClassHandler::ClassMethod *ClassHandler::ClassData::register_cxx_method(const char *mname,
147
cls_method_cxx_call_t func)
149
/* no need for locking, called under the class_init mutex */
150
dout(10) << "register_cxx_method " << name << "." << mname << " flags " << flags << " " << (void*)func << dendl;
151
ClassMethod& method = methods_map[mname];
152
method.cxx_func = func;
154
method.flags = flags;
159
ClassHandler::ClassMethod *ClassHandler::ClassData::_get_method(const char *mname)
161
map<string, ClassHandler::ClassMethod>::iterator iter = methods_map.find(mname);
162
if (iter == methods_map.end())
164
return &(iter->second);
167
int ClassHandler::ClassData::get_method_flags(const char *mname)
169
Mutex::Locker l(handler->mutex);
170
ClassMethod *method = _get_method(mname);
173
return method->flags;
176
void ClassHandler::ClassData::unregister_method(ClassHandler::ClassMethod *method)
178
/* no need for locking, called under the class_init mutex */
179
map<string, ClassMethod>::iterator iter = methods_map.find(method->name);
180
if (iter == methods_map.end())
182
methods_map.erase(iter);
185
void ClassHandler::ClassMethod::unregister()
187
cls->unregister_method(this);
190
int ClassHandler::ClassMethod::exec(cls_method_context_t ctx, bufferlist& indata, bufferlist& outdata)
195
ret = cxx_func(ctx, &indata, &outdata);
200
ret = func(ctx, indata.c_str(), indata.length(), &out, &olen);
202
// assume *out was allocated via cls_alloc (which calls malloc!)
203
buffer::ptr bp = buffer::claim_malloc(olen, out);
204
outdata.push_back(bp);