]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
class: able to update classes in runtime
authorYehuda Sadeh <yehuda@hq.newdream.net>
Mon, 1 Jun 2009 20:24:47 +0000 (13:24 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Mon, 1 Jun 2009 20:24:47 +0000 (13:24 -0700)
src/common/ClassHandler.cc
src/common/ClassHandler.h
src/config.cc
src/config.h

index c7ddc3ac441d0c2007da807f2670fff5a575e950..e3596cb1908b5763f9487cbef3d41f0331b728bb 100644 (file)
@@ -24,6 +24,7 @@ void ClassHandler::_load_class(ClassData &cls)
 
   char *fname=strdup("/tmp/class-XXXXXX");
   int fd = mkstemp(fname);
+  cls_deps_t *(*cls_deps)();
 
   for (list<bufferptr>::const_iterator it = cls.impl.binary.buffers().begin();
        it != cls.impl.binary.buffers().end(); it++)
@@ -32,7 +33,12 @@ void ClassHandler::_load_class(ClassData &cls)
   close(fd);
 
   cls.handle = dlopen(fname, RTLD_NOW);
-  cls_deps_t *(*cls_deps)() = ( cls_deps_t *(*)())dlsym(cls.handle, "class_deps");
+
+  if (!cls.handle) {
+    dout(0) << "could not open class (dlopen failed)" << dendl;
+    goto done;
+  }
+  cls_deps = (cls_deps_t *(*)())dlsym(cls.handle, "class_deps");
   if (cls_deps) {
     cls_deps_t *deps = cls_deps();
     while (deps) {
@@ -43,6 +49,7 @@ void ClassHandler::_load_class(ClassData &cls)
     }
   }
   cls.load();
+done:
   unlink(fname);
   free(fname);
 
@@ -84,6 +91,7 @@ ClassHandler::ClassData& ClassHandler::get_obj(const nstring& cname)
 
 ClassHandler::ClassData *ClassHandler::get_class(const nstring& cname, ClassVersion& version)
 {
+  ClassHandler::ClassData *ret = NULL;
   ClassData *class_data = &get_obj(cname);
   if (class_data == &null_cls_data)
     return NULL;
@@ -91,28 +99,30 @@ ClassHandler::ClassData *ClassHandler::get_class(const nstring& cname, ClassVers
   Mutex::Locker lock(*class_data->mutex);
 
   switch (class_data->status) {
+  case ClassData::CLASS_INVALID:
   case ClassData::CLASS_LOADED:
+    if (class_data->cache_timed_out()) {
+      dout(0) << "class timed out going to send request for " << cname.c_str() << " v" << version << dendl;
+      ret = class_data;
+      goto send;
+    }
     return class_data;
-    
   case ClassData::CLASS_REQUESTED:
     return NULL;
     break;
 
   case ClassData::CLASS_UNKNOWN:
-    class_data->status = ClassData::CLASS_REQUESTED;
+    class_data->set_status(ClassData::CLASS_REQUESTED);
     break;
 
-  case ClassData::CLASS_INVALID:
-    return class_data;
-
   default:
     assert(0);
   }
 
   class_data->version = version;
-
+send:
   osd->send_class_request(cname.c_str(), version);
-  return NULL;
+  return ret;
 }
 
 void ClassHandler::handle_class(MClass *m)
@@ -133,18 +143,14 @@ void ClassHandler::handle_class(MClass *m)
     data.mutex->Lock();
     
     if (*add_iter) {
-      
-      if (data.status == ClassData::CLASS_REQUESTED) {
+        data.set_status(ClassData::CLASS_REQUESTED);
        dout(10) << "added class '" << info_iter->name << "'" << dendl;
        data.impl = *impl_iter;
        ++impl_iter;
        _load_class(data);
-      } else {
-        dout(0) << "class status=" << data.status << dendl;
-      }
     } else {
        dout(10) << "response of an invalid class '" << info_iter->name << "'" << dendl;
-        data.status = ClassData::CLASS_INVALID;
+        data.set_status(ClassData::CLASS_INVALID);
         osd->got_class(info_iter->name);
     }
     data.mutex->Unlock();
@@ -200,7 +206,7 @@ void ClassHandler::ClassData::load()
   }
 
   if (!has_missing_deps()) {
-    status = CLASS_LOADED;
+    set_status(CLASS_LOADED);
     dout(0) << "setting class " << name << " status to CLASS_LOADED" << dendl;
     init();
     osd->got_class(name);
@@ -216,6 +222,7 @@ void ClassHandler::ClassData::load()
 void ClassHandler::ClassData::init()
 {
   void (*cls_init)() = (void (*)())dlsym(handle, "class_init");
+
   if (cls_init)
     cls_init();
 }
@@ -248,7 +255,7 @@ bool ClassHandler::ClassData::_add_dependency(cls_deps_t *dep)
 
   if (cls_dep.status == CLASS_INVALID) {
     dout(0) << "ouch! depending on invalid class" << dendl;
-    status = CLASS_INVALID; /* we have an invalid dependency, we're invalid */
+    set_status(CLASS_INVALID); /* we have an invalid dependency, we're invalid */
   }
 
   return true;
@@ -264,7 +271,7 @@ void ClassHandler::ClassData::satisfy_dependency(ClassData *cls)
     missing_dependencies.erase(iter);
     if (missing_dependencies.size() == 0) {
       dout(0) << "all dependencies are satisfied! initializing, notifying osd" << dendl;
-      status = CLASS_LOADED;
+      set_status(CLASS_LOADED);
   dout(0) << "this=" << (void *)this << " status=" << status << dendl;
       init();
       osd->got_class(name);
@@ -281,8 +288,7 @@ void ClassHandler::ClassData::_add_dependent(ClassData& dependent)
 
 ClassHandler::ClassMethod *ClassHandler::ClassData::register_method(const char *mname, cls_method_call_t func)
 {
-  Mutex::Locker lock(*mutex);
-
+ /* no need for locking, called under the class_init mutex */
   ClassMethod& method = methods_map[mname];
   method.func = func;
   method.name = mname;
@@ -304,7 +310,7 @@ ClassHandler::ClassMethod *ClassHandler::ClassData::get_method(const char *mname
 
 void ClassHandler::ClassData::unregister_method(ClassHandler::ClassMethod *method)
 {
-   Mutex::Locker lock(*mutex);
+ /* no need for locking, called under the class_init mutex */
    map<nstring, ClassMethod>::iterator iter;
 
    iter = methods_map.find(method->name);
@@ -314,6 +320,32 @@ void ClassHandler::ClassData::unregister_method(ClassHandler::ClassMethod *metho
    methods_map.erase(iter);
 }
 
+void ClassHandler::ClassData::set_status(ClassHandler::ClassData::Status _status)
+{
+  status = _status;
+
+  switch (status) {
+    case CLASS_INVALID:
+    case CLASS_LOADED:
+      set_timeout();
+      break;
+    default:
+      break;
+  }
+}
+
+void ClassHandler::ClassData::set_timeout()
+{
+  timeout = g_clock.now();
+  timeout += g_conf.osd_class_timeout;
+}
+
+bool ClassHandler::ClassData::cache_timed_out()
+{
+  dout(0) << "timeout=" << timeout << " g_clock.now()=" << g_clock.now() << dendl;
+  return (timeout && g_clock.now() >= timeout);
+}
+
 void ClassHandler::ClassMethod::unregister()
 {
   cls->unregister_method(this);
index b883ba8bae873f3f57056a233e8601bc517c74d3..38d892612c5338dfd25c5292f8a83590fde45b5a 100644 (file)
@@ -38,13 +38,14 @@ public:
 
     void satisfy_dependency(ClassData *cls);
 
-    enum { 
+    enum Status 
       CLASS_UNKNOWN, 
       CLASS_INVALID, 
       CLASS_LOADED, 
       CLASS_REQUESTED, 
     } status;
     ClassVersion version;
+    time_t timeout;
     ClassImpl impl;
     nstring name;
     OSD *osd;
@@ -59,7 +60,7 @@ public:
 
     bool has_missing_deps() { return (missing_dependencies.size() > 0); }
 
-    ClassData() : mutex(NULL), status(CLASS_UNKNOWN), version(), handle(NULL), registered(false)  {}
+    ClassData() : mutex(NULL), status(CLASS_UNKNOWN), version(), timeout(0), handle(NULL), registered(false)  {}
     ~ClassData() { if (mutex) delete mutex; }
 
     ClassMethod *register_method(const char *mname,
@@ -69,6 +70,10 @@ public:
 
     void load();
     void init();
+
+    void set_status(Status _status);
+    void set_timeout();
+    bool cache_timed_out();
   };
   Mutex mutex;
   map<nstring, ClassData> classes;
index dfbdcc4e4471002b4a31f3f7a340e97780351fc1..9a51cbd000cb889c21dc081acbfda33c86f06860 100644 (file)
@@ -468,6 +468,7 @@ static struct config_option config_optionsp[] = {
        OPTION(osd_recovery_delay_start, 0, OPT_FLOAT, 15),
        OPTION(osd_recovery_max_active, 0, OPT_INT, 5),
        OPTION(osd_auto_weight, 0, OPT_BOOL, false),
+       OPTION(osd_class_timeout, 0, OPT_FLOAT, 10.0),
        OPTION(filestore, 0, OPT_BOOL, false),
        OPTION(filestore_max_sync_interval, 0, OPT_DOUBLE, .2),    // seconds
        OPTION(filestore_min_sync_interval, 0, OPT_DOUBLE, .001),  // seconds
index cbe425f24d3fc7a75b9b1781539a899b52df5c82..b6dfb5398f0e1a62b72282b6e80fda5fef101a8b 100644 (file)
@@ -292,6 +292,8 @@ struct md_config_t {
 
   bool osd_auto_weight;
 
+  bool osd_class_timeout;
+
   // filestore
   bool filestore;
   double   filestore_max_sync_interval;