From 1eb64400f740844f607a906001163e74a9297d54 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Mon, 1 Jun 2009 13:24:47 -0700 Subject: [PATCH] class: able to update classes in runtime --- src/common/ClassHandler.cc | 72 +++++++++++++++++++++++++++----------- src/common/ClassHandler.h | 9 +++-- src/config.cc | 1 + src/config.h | 2 ++ 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/common/ClassHandler.cc b/src/common/ClassHandler.cc index c7ddc3ac441d0..e3596cb1908b5 100644 --- a/src/common/ClassHandler.cc +++ b/src/common/ClassHandler.cc @@ -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::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::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); diff --git a/src/common/ClassHandler.h b/src/common/ClassHandler.h index b883ba8bae873..38d892612c533 100644 --- a/src/common/ClassHandler.h +++ b/src/common/ClassHandler.h @@ -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 classes; diff --git a/src/config.cc b/src/config.cc index dfbdcc4e44710..9a51cbd000cb8 100644 --- a/src/config.cc +++ b/src/config.cc @@ -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 diff --git a/src/config.h b/src/config.h index cbe425f24d3fc..b6dfb5398f0e1 100644 --- a/src/config.h +++ b/src/config.h @@ -292,6 +292,8 @@ struct md_config_t { bool osd_auto_weight; + bool osd_class_timeout; + // filestore bool filestore; double filestore_max_sync_interval; -- 2.39.5