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
[email protected]
https://lists.sourceforge.net/lists/listinfo/naviserver-devel