On 10/23/07, Vasiljevic Zoran <[EMAIL PROTECTED]> wrote: > > What we haven't figured out is: how the changed > params are saved (made persistent) when a change > occurs? This is by no means trivial to do. > Perhaps the easiest would be to have some kind of > dbm-like storage (qdbm is nice and LGPL) plus > some utility to display the values inthere... > Just a thought...
It looks like there's a natural callback in CfgSet. i.e. this: static void CfgSet(CONST char *section, CONST char *key, CONST Param *param) { Section *globalSection, *threadSection; Ns_MutexLock(&lock); globalSection = GetSection(&globalTable, section); SetParam(globalSection, key, param); threadSection = globalSection->nextPtr; while (threadSection != NULL) { Ns_MutexLock(&threadSection->lock); SetParam(threadSection, key, param); Ns_MutexUnlock(&threadSection->lock); threadSection = threadSection->nextPtr; } Ns_MutexUnlock(&lock); } Could look (roughly) like this: typedef void (Cfg_SetParamProc)(CONST char *section, CONST char *key, CFG_TYPE type, void *valuePtr, void *arg); typedef Callback { struct Callback *nextPtr; Cfg_SetParamProc *proc; void *arg; } Callback; static void DefaultSetProc(CONST char *section, CONST char *key, CFG_TYPE type, void *valuePtr, void *arg) { Section *threadSection = arg; Ns_MutexLock(&threadSection->lock); SetParam(threadSection, key, type, valuePtr); Ns_MutexUnlock(&threadSection->lock); } static void CfgSet(CONST char *section, CONST char *key, CONST Param *param) { Section *globalSection; Callback *cbPtr; Ns_MutexLock(&lock); globalSection = GetSection(&globalTable, section); SetParam(globalSection, key, param); cbPtr = globalSection->nextPtr; while (cbPtr != NULL) { (*cbPtr->proc)(section, key, cbPtr->arg); cbPtr = cbPtr->nextPtr; } Ns_MutexUnlock(&lock); } Once introspection works, then you can do: ns_atshutdown { # Save whole config foreach section [ns_getconfig] { ... } } With exposed callbacks, you could save every update. Perhaps like this: do_foo [ns_getconfig -onupdate do_update -- section key 42] proc do_update {section key value} { do_foo -thingy $value ns_log notice new thingy: $value } Perhaps it could also be exposed on the C-side. Currently, you'd have to do something like this: int configEnabled = 0; /* default disabled */ AtRuntime() { int enabled; if (Cfg_GetBool("ns/foo", "enabled", &configEnabled, &enabled) == NS_OK && enabled) { ... } } But perhaps it could become something like this: struct { int enabled; /* default disabled */ ... } config; Ns_ModuleInit(char *server, char *module) { int def = 0; if (Cfg_GetBool("ns/foo", "enabled", &def, &config.enabled, OnUpdate, &config) != NS_OK) { return NS_ERROR; } } AtRuntime() { if (configEnabled) { ... } } OnUpdate(char *section, char *key, CFG_TYPE type, *valuePtr, void *arg) { int *enabledPtr = &((typeof(config) *) arg).enabled; *enabledPtr = *valuePtr; } (Obviously the details need work... :-) The basic idea of a callback seem to fit fairly naturaly to how the code currently works. And I like the idea more than a hard dependency on some DBM library. I also like the idea that it serves two functions: it's a hook which can be used to dump config, but it can also be used to handle updates to systems with different locking schemes than atomic key/value pairs. ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ naviserver-devel mailing list naviserver-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/naviserver-devel