~ubuntu-branches/ubuntu/precise/ceph/precise-proposed

« back to all changes in this revision

Viewing changes to src/osd/ClassHandler.cc

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2011-08-28 15:56:16 UTC
  • mfrom: (1.1.4 upstream) (0.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20110828155616-h19o67xdn2sjrh10
Tags: 0.34-1
* New upstream release (closes: #638714).
* Make librbd-dev depends on librados-dev as it uses headers from the latter
  (closes: #636845).
* Add new binary packages, gceph, gceph-dbg and obsync . The libcrush ones
  removed.
* Change to quilt source format and tune packaging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "include/types.h"
 
3
#include "msg/Message.h"
 
4
#include "osd/OSD.h"
 
5
#include "ClassHandler.h"
 
6
 
 
7
#include <dlfcn.h>
 
8
 
 
9
#include <map>
 
10
 
 
11
#include "common/config.h"
 
12
 
 
13
#define DOUT_SUBSYS osd
 
14
#undef dout_prefix
 
15
#define dout_prefix *_dout
 
16
 
 
17
int ClassHandler::open_class(const string& cname, ClassData **pcls)
 
18
{
 
19
  Mutex::Locker lock(mutex);
 
20
  ClassData *cls = _get_class(cname);
 
21
  if (cls->status != ClassData::CLASS_OPEN) {
 
22
    int r = _load_class(cls);
 
23
    if (r)
 
24
      return r;
 
25
  }
 
26
  *pcls = cls;
 
27
  return 0;
 
28
}
 
29
 
 
30
ClassHandler::ClassData *ClassHandler::_get_class(const string& cname)
 
31
{
 
32
  ClassData *cls;
 
33
  map<string, ClassData>::iterator iter = classes.find(cname);
 
34
 
 
35
  if (iter != classes.end()) {
 
36
    cls = &iter->second;
 
37
  } else {
 
38
    cls = &classes[cname];
 
39
    dout(10) << "_get_class adding new class name " << cname << " " << cls << dendl;
 
40
    cls->name = cname;
 
41
    cls->handler = this;
 
42
  }
 
43
  return cls;
 
44
}
 
45
 
 
46
int ClassHandler::_load_class(ClassData *cls)
 
47
{
 
48
  // already open
 
49
  if (cls->status == ClassData::CLASS_OPEN)
 
50
    return 0;
 
51
 
 
52
  if (cls->status == ClassData::CLASS_UNKNOWN ||
 
53
      cls->status == ClassData::CLASS_MISSING) {
 
54
    char fname[PATH_MAX];
 
55
    snprintf(fname, sizeof(fname), "%s/libcls_%s.so",
 
56
             g_conf->osd_class_dir.c_str(),
 
57
             cls->name.c_str());
 
58
    dout(10) << "_load_class " << cls->name << " from " << fname << dendl;
 
59
 
 
60
    cls->handle = dlopen(fname, RTLD_NOW);
 
61
    if (!cls->handle) {
 
62
      dout(0) << "_load_class could not open class " << fname
 
63
              << " (dlopen failed): " << dlerror() << dendl;
 
64
      cls->status = ClassData::CLASS_MISSING;
 
65
      return -EIO;
 
66
    }
 
67
 
 
68
    cls_deps_t *(*cls_deps)();
 
69
    cls_deps = (cls_deps_t *(*)())dlsym(cls->handle, "class_deps");
 
70
    if (cls_deps) {
 
71
      cls_deps_t *deps = cls_deps();
 
72
      while (deps) {
 
73
        if (!deps->name)
 
74
          break;
 
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);
 
79
        deps++;
 
80
      }
 
81
    }
 
82
  }
 
83
 
 
84
  // resolve dependencies
 
85
  set<ClassData*>::iterator p = cls->missing_dependencies.begin();
 
86
  while (p != cls->missing_dependencies.end()) {
 
87
    ClassData *dc = *p;
 
88
    int r = _load_class(dc);
 
89
    if (r < 0) {
 
90
      cls->status = ClassData::CLASS_MISSING_DEPS;
 
91
      return r;
 
92
    }
 
93
    
 
94
    dout(10) << "_load_class " << cls->name << " satisfied dependency " << dc->name << dendl;
 
95
    cls->missing_dependencies.erase(p++);
 
96
  }
 
97
  
 
98
  // initialize
 
99
  void (*cls_init)() = (void (*)())dlsym(cls->handle, "__cls_init");
 
100
  if (cls_init) {
 
101
    cls->status = ClassData::CLASS_INITIALIZING;
 
102
    cls_init();
 
103
  }
 
104
  
 
105
  dout(10) << "_load_class " << cls->name << " success" << dendl;
 
106
  cls->status = ClassData::CLASS_OPEN;
 
107
  return 0;
 
108
}
 
109
 
 
110
 
 
111
 
 
112
ClassHandler::ClassData *ClassHandler::register_class(const char *cname)
 
113
{
 
114
  assert(mutex.is_locked());
 
115
 
 
116
  ClassData *cls = _get_class(cname);
 
117
  dout(10) << "register_class " << cname << " status " << cls->status << dendl;
 
118
 
 
119
  if (cls->status != ClassData::CLASS_INITIALIZING) {
 
120
    dout(0) << "class " << cname << " isn't loaded; is the class registering under the wrong name?" << dendl;
 
121
    return NULL;
 
122
  }
 
123
  return cls;
 
124
}
 
125
 
 
126
void ClassHandler::unregister_class(ClassHandler::ClassData *cls)
 
127
{
 
128
  /* FIXME: do we really need this one? */
 
129
}
 
130
 
 
131
ClassHandler::ClassMethod *ClassHandler::ClassData::register_method(const char *mname,
 
132
                                                                    int flags,
 
133
                                                                    cls_method_call_t func)
 
134
{
 
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];
 
138
  method.func = func;
 
139
  method.name = mname;
 
140
  method.flags = flags;
 
141
  method.cls = this;
 
142
  return &method;
 
143
}
 
144
 
 
145
ClassHandler::ClassMethod *ClassHandler::ClassData::register_cxx_method(const char *mname,
 
146
                                                                        int flags,
 
147
                                                                        cls_method_cxx_call_t func)
 
148
{
 
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;
 
153
  method.name = mname;
 
154
  method.flags = flags;
 
155
  method.cls = this;
 
156
  return &method;
 
157
}
 
158
 
 
159
ClassHandler::ClassMethod *ClassHandler::ClassData::_get_method(const char *mname)
 
160
{
 
161
  map<string, ClassHandler::ClassMethod>::iterator iter = methods_map.find(mname);
 
162
  if (iter == methods_map.end())
 
163
    return NULL;
 
164
  return &(iter->second);
 
165
}
 
166
 
 
167
int ClassHandler::ClassData::get_method_flags(const char *mname)
 
168
{
 
169
  Mutex::Locker l(handler->mutex);
 
170
  ClassMethod *method = _get_method(mname);
 
171
  if (!method)
 
172
    return 0;
 
173
  return method->flags;
 
174
}
 
175
 
 
176
void ClassHandler::ClassData::unregister_method(ClassHandler::ClassMethod *method)
 
177
{
 
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())
 
181
     return;
 
182
   methods_map.erase(iter);
 
183
}
 
184
 
 
185
void ClassHandler::ClassMethod::unregister()
 
186
{
 
187
  cls->unregister_method(this);
 
188
}
 
189
 
 
190
int ClassHandler::ClassMethod::exec(cls_method_context_t ctx, bufferlist& indata, bufferlist& outdata)
 
191
{
 
192
  int ret;
 
193
  if (cxx_func) {
 
194
    // C++ call version
 
195
    ret = cxx_func(ctx, &indata, &outdata);
 
196
  } else {
 
197
    // C version
 
198
    char *out = NULL;
 
199
    int olen = 0;
 
200
    ret = func(ctx, indata.c_str(), indata.length(), &out, &olen);
 
201
    if (out) {
 
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);
 
205
    }
 
206
  }
 
207
  return ret;
 
208
}
 
209