From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 12:58:51
|
Hi! Stephen added the module "nsconfigw" into the modules section, based on my example from RFE. He did quite a lot of work there lately to clean it up, debug and write some test cases. Good Work, Stephen! I changed the way how parameters are handled to avoid excessive allocations and conversions where possible (this can still be improved). I compared the ns_config (NS built-in read-only config) speed with the new module: lexxsrv:nscp 2> time {ns_config -bool ns/parameters logdebug} 1000 3.368 microseconds per iteration lexxsrv:nscp 4> time {ns_getconfig -bool ns/parameters logdebug} 1000 2.331 microseconds per iteration Well, 1 microsec is not much but in this case this is 30% (faster). Strings is similar, yet not so large difference (as expected): lexxsrv:nscp 16> time {ns_config ns/parameters tcllibrary} 1000 3.163 microseconds per iteration lexxsrv:nscp 18> time {ns_getconfig ns/parameters tcllibrary} 1000 2.966 microseconds per iteration The config store now has typed-params so we avoid conversions similarily to Tcl objects. Per-definition, the contention on readers is minimal per-design: just one reader and one writer may contend for the same mutex. Multiple readers will never contend, except on the very first request for a param that is not privately cached. This all comes with a price of more memory usage. Not really much, but still. OTOH, you get true read/write config which is reasonably (very!) fast so you can even put calls to it in tight loops. I think this is very good now. It needs adding WideInt type and some way of making the conig persistent. Perhaps some other param qualifiers (readonly, readwrite...) Cheers Zoran |
From: Stephen D. <sd...@gm...> - 2007-10-23 15:08:34
|
Fails to run. $ make gdbtest TCLTESTARGS="-debug 3" Tests began at Tue Oct 23 04:01:45 PM BST 2007 ns_config.test ::tcltest::Eval called Running ns_config-2.1 { expr {[ns_getconfig -bool ns/testconfig trueval] ? 1 : 0} } ::tcltest::Eval called Running ns_config-2.2 { ns_getconfig -bool ns/testconfig missing } make: *** [test] Segmentation fault [Switching to Thread 1077488528 (LWP 4409)] 0x400063d1 in CopyParam (dest=0x9fbb030, src=0x0) at configrw.c:958 958 dest->type = src->type; (gdb) backtrace #0 0x400063d1 in CopyParam (dest=0x9fbb030, src=0x0) at configrw.c:958 #1 0x4000625e in SetParam (secPtr=0x9fba960, name=0x9fbabb0 "missing", param=0x0) at configrw.c:858 #2 0x40005fbd in CfgGet (section=0x9fb0cf0 "ns/testconfig", key=0x9fbabb0 "missing", outPtr=0x4038e6c0) at configrw.c:708 #3 0x40004f9f in Cfg_GetBool (section=0x9fb0cf0 "ns/testconfig", key=0x9fbabb0 "missing", def=0x0, value=0x4038e7e4) at configrw.c:224 #4 0x400058d6 in CfgGetObjCmd (data=0x0, interp=0x9eeeaf0, objc=4, objv=0x4038e98c) at configrw.c:540 |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 15:50:28
|
On 23.10.2007, at 17:08, Stephen Deasey wrote: > Fails to run. > Amazing. For me it passes all tests... This is perhaps I'm on Mac and you're on Linux? ;-) Anyways... this must be some trivia... |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 16:04:24
|
On 23.10.2007, at 17:50, Vasiljevic Zoran wrote: > > Anyways... this must be some trivia... Indeed. Tests began at Tue Oct 23 18:03:40 CEST 2007 ns_config.test [23/Oct/2007:18:03:40][3655.1800600][-command-] Warning: configrw: ns/ testconfig:intval value=42, rounded up to 43 [23/Oct/2007:18:03:40][3655.1800600][-command-] Warning: configrw: ns/ testconfig:intval value=42, rounded down to 41 [23/Oct/2007:18:03:40][3655.1800600][-command-] Warning: configrw: ns/ testconfig:intval value=42, rounded up to 43 [23/Oct/2007:18:03:40][3655.1800600][-command-] Warning: configrw: ns/ testconfig:missing value=42, rounded down to 41 ns_getconfig.test [23/Oct/2007:18:03:40][3655.1803800][-ns_job_0-] Notice: Starting thread: -ns_job_1- Tests ended at Tue Oct 23 18:03:40 CEST 2007 all.tcl: Total 29 Passed 25 Skipped 4 Failed 0 Sourced 2 Test Files. Number of tests skipped for each constraint: 4 knownBug Please checkout, recompile and try again. |
From: Stephen D. <sd...@gm...> - 2007-10-23 16:53:50
|
On 10/23/07, Vasiljevic Zoran <zv...@ar...> wrote: > > On 23.10.2007, at 17:50, Vasiljevic Zoran wrote: > > > > > Anyways... this must be some trivia... > > Indeed. > > Tests ended at Tue Oct 23 18:03:40 CEST 2007 > all.tcl: Total 29 Passed 25 Skipped 4 Failed 0 Groovy. Fixed. |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 17:03:46
|
On 23.10.2007, at 18:53, Stephen Deasey wrote: > Groovy. Fixed. What would be intersting are some speed figures. The one I gave were from my MPB with 2GHZ Intel. I guess that weshould be not slower than ns_config. As looking in the nsd/config.c whole lotta things got into there... some arcane backslash parsing code etc pp... brrr... Ultimately the nsconfigrw should be plug-replacement for most of the things in config.c, or? 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... |
From: Stephen D. <sd...@gm...> - 2007-10-23 17:25:12
|
Two interesting failing test cases: test cfg-5.4 {defaults propagate to global store} -body { ns_getconfig section cfg-5.4 foo ns_getconfig section } -match glob -result {*cfg-5.4*} ---- Result was: cfg-4.1 cfg-3.2 cfg-4.2 cfg-3.1 ---- Result should have been (glob matching): *cfg-5.4* ==== cfg-5.4 FAILED test cfg-4.1 {global type check bool} -body { ns_setconfig section cfg-4.1 true expr {[ns_getconfig -bool section cfg-4.1] ? 1 : 0} } -result 1 ---- Test generated error; Return code was: 1 ---- Return code should have been one of: 0 2 ---- errorInfo: configuration parameter is not a boolean |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 18:53:31
|
On 23.10.2007, at 19:25, Stephen Deasey wrote: > Two interesting failing test cases: > > > > test cfg-5.4 {defaults propagate to global store} -body { > ns_getconfig section cfg-5.4 foo > ns_getconfig section > } -match glob -result {*cfg-5.4*} > > ---- Result was: > cfg-4.1 cfg-3.2 cfg-4.2 cfg-3.1 > ---- Result should have been (glob matching): > *cfg-5.4* > ==== cfg-5.4 FAILED > > This can happen if "cfg-5.4" was never declared. The "ns_getconfig section cfg-5.4 foo" will NOT trigger error if the section/key is missing. It will just return empty string (as ns_config does). Correspondingly, the "ns_getconfig section" will return just those keys that have been ns_setconfig'ed so far. > > > test cfg-4.1 {global type check bool} -body { > ns_setconfig section cfg-4.1 true > expr {[ns_getconfig -bool section cfg-4.1] ? 1 : 0} > } -result 1 > > ---- Test generated error; Return code was: 1 > ---- Return code should have been one of: 0 2 > ---- errorInfo: configuration parameter is not a boolean This is of course more tricky, as we do not store strings in Param, just 1/0. I think I must investigate string in Param on yes/y/no/n/true/t/false etc etc when converting string to boolean. Eagle-Eye-Stephen... |
From: Stephen D. <sd...@gm...> - 2007-10-23 19:24:06
|
On 10/23/07, Vasiljevic Zoran <zv...@ar...> wrote: > > On 23.10.2007, at 19:25, Stephen Deasey wrote: > > > Two interesting failing test cases: > > > > test cfg-5.4 {defaults propagate to global store} -body { > > ns_getconfig section cfg-5.4 foo > > ns_getconfig section > > } -match glob -result {*cfg-5.4*} > > > > ---- Result was: > > cfg-4.1 cfg-3.2 cfg-4.2 cfg-3.1 > > ---- Result should have been (glob matching): > > *cfg-5.4* > > ==== cfg-5.4 FAILED > > > > This can happen if "cfg-5.4" was never declared. > The "ns_getconfig section cfg-5.4 foo" will NOT > trigger error if the section/key is missing. It > will just return empty string (as ns_config does). > Correspondingly, the "ns_getconfig section" will > return just those keys that have been ns_setconfig'ed > so far. But one of the things we want to support is introspection, right? foreach section [ns_getconfig] { foreach {k v} [ns_getconfig $section] { ... } } The only way to make it work atm is to pre-declare all config values: # mylib.tcl ns_setconfig section enabled true ... proc foo {} { if {[ns_getconfig section enabled]} { ... } } ... Pre-declaring is a new restriction. Is this the plan? I could also imagine having a hybrid system, where you *could* pre-declare, but you could also have ad-hoc calls. Both have their benefits: - Config which is only referenced once, and rarely if ever needs to be changed, is ideally handled with inline calls. Everything is in one place. - Config which cannot be guessed, e.g. a host name, or which is accessed from multiple pieces of code, would benefit from a declaration. This would allow the default to be written once and make options for configuring code more obvious. A system of pre-declaring might have benefits for C-code especially. Or..? |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 19:24:45
|
On 23.10.2007, at 19:25, Stephen Deasey wrote: > > test cfg-4.1 {global type check bool} -body { > ns_setconfig section cfg-4.1 true > expr {[ns_getconfig -bool section cfg-4.1] ? 1 : 0} > } -result 1 Try again... |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 19:46:08
|
On 23.10.2007, at 21:24, Stephen Deasey wrote: > > But one of the things we want to support is introspection, right? Right. > > > foreach section [ns_getconfig] { > foreach {k v} [ns_getconfig $section] { > ... > } > } > > > The only way to make it work atm is to pre-declare all config values: > > > # mylib.tcl > > ns_setconfig section enabled true > ... > > proc foo {} { > if {[ns_getconfig section enabled]} { > ... > } > } > ... > > > Pre-declaring is a new restriction. Is this the plan? Well, I went ahead in making it ns_config compatible although this may NOT really always be clear. If you do not set default values, then module A might have different defaults then module B, which is right and wrong, depending on the position... If you however set them in module A, might that have side-effects in module B ? Perhaps the clearest is to have both, as you say below... > > I could also imagine having a hybrid system, where you *could* > pre-declare, but you could also have ad-hoc calls. Both have their > benefits: > > - Config which is only referenced once, and rarely if ever needs to be > changed, is ideally handled with inline calls. Everything is in one > place. > > - Config which cannot be guessed, e.g. a host name, or which is > accessed from multiple pieces of code, would benefit from a > declaration. This would allow the default to be written once and make > options for configuring code more obvious. > > > A system of pre-declaring might have benefits for C-code especially. > > > Or..? > So we'd change (back) the config to set default values when first required ? |
From: Stephen D. <sd...@gm...> - 2007-10-23 20:28:56
|
On 10/23/07, Vasiljevic Zoran <zv...@ar...> wrote: > > On 23.10.2007, at 19:25, Stephen Deasey wrote: > > > > > test cfg-4.1 {global type check bool} -body { > > ns_setconfig section cfg-4.1 true > > expr {[ns_getconfig -bool section cfg-4.1] ? 1 : 0} > > } -result 1 > > Try again... $ make gcc -g -Wall -Wno-implicit-int -fPIC -pipe -I/home/sd/local/ns-HEADg/include -I"/home/sd/local/tcl8.4.15g/include" -DHAVE_CONFIG_H -c -o configrw.o configrw.c configrw.c:219: error: conflicting types for 'Cfg_GetBool' nsconfigrw.h:58: error: previous declaration of 'Cfg_GetBool' was here configrw.c:265: error: conflicting types for 'Cfg_GetInt' nsconfigrw.h:61: error: previous declaration of 'Cfg_GetInt' was here configrw.c: In function 'Cfg_GetInt': configrw.c:266: warning: passing argument 3 of 'Cfg_GetRange' discards qualifiers from pointer target type configrw.c: At top level: configrw.c:291: error: conflicting types for 'Cfg_GetRange' nsconfigrw.h:65: error: previous declaration of 'Cfg_GetRange' was here make: *** [configrw.o] Error 1 Also: > static int > GetBoolFromParam(Param *param, int *result) > { > if (param->type != IntType) { > int bool; > if ( STREQ (param->value, "1" ) > || STRIEQ(param->value, "y" ) > || STRIEQ(param->value, "yes" ) > || STRIEQ(param->value, "on" ) > || STRIEQ(param->value, "t" ) > || STRIEQ(param->value, "true")) { > param->intval = 1; int Tcl_GetBoolean(Tcl_Interp *, CONST char *string, int *boolPtr) http://www.tcl.tk/man/tcl8.4/TclLib/GetInt.htm (You can pass it a NULL interp) |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 20:34:29
|
On 23.10.2007, at 22:28, Stephen Deasey wrote: > > $ make Damn. I did not check-in the nsconfigrw.h... |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 20:35:17
|
On 23.10.2007, at 22:28, Stephen Deasey wrote: > > int Tcl_GetBoolean(Tcl_Interp *, CONST char *string, int *boolPtr) > > http://www.tcl.tk/man/tcl8.4/TclLib/GetInt.htm Good tip! |
From: Stephen D. <sd...@gm...> - 2007-10-23 21:06:05
|
On 10/23/07, Vasiljevic Zoran <zv...@ar...> wrote: > > On 23.10.2007, at 21:24, Stephen Deasey wrote: > > > > But one of the things we want to support is introspection, right? > > Right. > > > > > > > foreach section [ns_getconfig] { > > foreach {k v} [ns_getconfig $section] { > > ... > > } > > } > > > > > > The only way to make it work atm is to pre-declare all config values: > > > > > > # mylib.tcl > > > > ns_setconfig section enabled true > > ... > > > > proc foo {} { > > if {[ns_getconfig section enabled]} { > > ... > > } > > } > > ... > > > > > > Pre-declaring is a new restriction. Is this the plan? > > Well, I went ahead in making it ns_config compatible > although this may NOT really always be clear. > > If you do not set default values, then module A might > have different defaults then module B, which is right > and wrong, depending on the position... > If you however set them in module A, might that have > side-effects in module B ? If you have: ns_getconfig section theint 42 and somewhere else you have: ns_getconfig section theint 13 and you set it up so that on the first access, if the value does not exist in the global config you seed it with the default (as you must if you want introspection to work), then the value seeded depends on which code runs first. I don't think this is necessarily an error. By design it's a read/write config, so if the value started at 42, maybe someone reset it to 13? It's the same effect. However, I think this would be an error: ns_getconfig -bool section key yes ... ns_getconfig -int section key 1 The two pieces of code share a config key but they have conflicting ideas about the type. One of them is wrong. The alternative is to always store the string value and do conversion on every access. I don't think this is the way to go: it's slow and it's just not logically correct. |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-23 21:52:21
|
On 23.10.2007, at 23:06, Stephen Deasey wrote: > If you have: > > ns_getconfig section theint 42 > > and somewhere else you have: > > ns_getconfig section theint 13 > > and you set it up so that on the first access, if the value does not > exist in the global config you seed it with the default (as you must > if you want introspection to work), then the value seeded depends on > which code runs first. > > I don't think this is necessarily an error. By design it's a > read/write config, so if the value started at 42, maybe someone reset > it to 13? It's the same effect. Not exactly as the second on will ignore the default, because the first one have set it allright. But I agree that this may not be considered as error. The deault is only used to seed the config if nothing found. As it is now. it doesn't. It simply parrots the default back to user w/o setting it in the store. This is how ns_config works. Not necesarily the correct way, though. > > However, I think this would be an error: > > ns_getconfig -bool section key yes > ... > ns_getconfig -int section key 1 > > The two pieces of code share a config key but they have conflicting > ideas about the type. One of them is wrong. But we can't recover from that. > > The alternative is to always store the string value and do conversion > on every access. I don't think this is the way to go: it's slow and > it's just not logically correct. Storing the string is not going to be very sexy because of permanent string/type conversions. I can live with "first default sets the value" in the config. This is how it was yesterday and I changed it today to be on-pair with ns_config. Not necessarily a good idea. I will revert the code again. Now that we "solved" that one.... do you have any idea about persistence? |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-24 15:49:41
|
On 23.10.2007, at 23:52, Vasiljevic Zoran wrote: > Now that we "solved" that one.... So, it is done. I will shortly check-in the changes. But before I do, a question: how "seriously" should I take those tests: test cfg-4.3 {type check: bool != int} -body { ns_getconfig -bool section cfg-4.3 yes ns_getconfig -int section cfg-4.3 42 } -returnCodes error -result {configuration parameter is not an integer} test cfg-4.4 {global type check: bool != int} -body { ns_job wait cfgtest [ns_job queue cfgtest { ns_getconfig -bool section cfg-4.4 yes }] ns_getconfig -int section cfg-4.4 42 } -returnCodes error -result {configuration parameter is not an integer} If this should be true, then something like this should also fail: ns_getconfig -bool foo bar 1 ns_getconfig -int foo bar Or not? I mean, we are not Java. Tcl is still C-like: set true 42 if {$true} {puts yesitis} Tcl will not jump in your face telling you that "true is not a boolean", or? Cheers Zoran |
From: Stephen D. <sd...@gm...> - 2007-10-24 16:36:03
|
On 10/24/07, Vasiljevic Zoran <zv...@ar...> wrote: > > On 23.10.2007, at 23:52, Vasiljevic Zoran wrote: > > > Now that we "solved" that one.... > > So, it is done. I will shortly check-in the changes. > But before I do, a question: how "seriously" should > I take those tests: > > test cfg-4.3 {type check: bool != int} -body { > ns_getconfig -bool section cfg-4.3 yes > ns_getconfig -int section cfg-4.3 42 > } -returnCodes error -result {configuration parameter is not an integer} > > test cfg-4.4 {global type check: bool != int} -body { > ns_job wait cfgtest [ns_job queue cfgtest { > ns_getconfig -bool section cfg-4.4 yes > }] > ns_getconfig -int section cfg-4.4 42 > } -returnCodes error -result {configuration parameter is not an integer} > > > If this should be true, then something like this should also fail: > > ns_getconfig -bool foo bar 1 > ns_getconfig -int foo bar > > Or not? Should add that test. > I mean, we are not Java. Tcl is still C-like: > > set true 42 > if {$true} {puts yesitis} > > Tcl will not jump in your face telling you that > "true is not a boolean", or? This works: if {[ns_getconfig -int section key 42]} { ... } ns_getconfig both uses and declares. It declares so that an admin can set the correct value. Some code may only need to check whether a buffer size is greater than zero (is it true?), but that doesn't make it a boolean config option. A buffer size of 'no' doesn't make any sense. |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-24 17:01:01
|
On 24.10.2007, at 18:36, Stephen Deasey wrote: > A buffer size of 'no' doesn't make any > sense. But ns_getconfig section buffer no (module A) ns_getconfig section buffer 1000 (module B) is the application problem, not ours. This is simply clash of config params. I do not think we need to take care of that. Otherwise we MUST predefine all upfront and not set implicitly when somebody provides default value. |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-24 17:09:43
|
On 24.10.2007, at 18:36, Stephen Deasey wrote: > ns_getconfig both uses and declares. It declares so that an admin can > set the correct value. Some code may only need to check whether a > buffer size is greater than zero (is it true?), but that doesn't make > it a boolean config option. A buffer size of 'no' doesn't make any > sense. So ns_getconfig -bool section param 1 ns_getconfig -int section param configuration parameter is not an integer would make you happy? |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-24 17:26:11
|
On 24.10.2007, at 19:09, Vasiljevic Zoran wrote: > So > > ns_getconfig -bool section param 1 > ns_getconfig -int section param > configuration parameter is not an integer > > would make you happy? > Lets stop and think about consequences of this... Underneath, some integer will be used to hold the value of the boolean param. After all,we have C underneath. Now somebody will go get integer rep of it and will receive error because the type is boolean. Good for the moment. But consider this: ns_getconfig section param "1" ns_getconfig -bool section param How should we react here? The "1" is not a boolean value. It is an string. Should I convert it to boolean? If the answer is YES, then the top example should not result in error. If the answer is NO, then we're going VERY far from common (Tcl) logic... |
From: Stephen D. <sd...@gm...> - 2007-10-24 18:35:17
|
On 10/24/07, Vasiljevic Zoran <zv...@ar...> wrote: > > On 24.10.2007, at 19:09, Vasiljevic Zoran wrote: > > > So > > > > ns_getconfig -bool section param 1 > > ns_getconfig -int section param > > configuration parameter is not an integer > > > > would make you happy? > > > > Lets stop and think about consequences of this... > > Underneath, some integer will be used to hold > the value of the boolean param. After all,we > have C underneath. Now somebody will go get > integer rep of it and will receive error > because the type is boolean. Good for the moment. > But consider this: > > ns_getconfig section param "1" > ns_getconfig -bool section param > > How should we react here? The "1" is not a boolean > value. It is an string. It should be 'unknown'. i.e. this: typedef enum { UnknownType, StrType, IntType } ParamType; Should be more like this: typedef enum { UnknownType, BoolType, IntType } ParamType; The conversion rules would be that you can go from Unknown to Bool or Int, but not the other way around, and you can't go from Bool to Int or vice versa. So code like this: ns_getconfig section key 42 would set a value of unknown type if not present. Code like this: ns_getconfig -int section key 42 would cause it's type to become Int. It's then OK to follow that sequence with: ns_getconfig section key 42 again. The underlying C code would actually return a Tcl Integer type, but that doesn't matter. If you don't specify either -int or -bool then you're either setting an unknown type or are happy to receive any type. Type conversion and checking can still occur, but that's standard Tcl: if {[ns_getconfig section key]} { return [expr $key + 2] } If we were still at step 1 above, they key with type Unknown would be returned as a string and Tcl would convert to an int. It *is* kinda weird to build (but easy to use), but that's because we're using a command designed for the read-only existing config. Explicitly, ns_getconfig with a default param is just shorthand for this sort of code: if {[catch { set value [ns_getconfig -int section key] } err]} { ns_setconfig -int section key 42 set value 42 } The first time the code is called, when there is no record of the key or value in the global config, there is an implicit call to set. We want to record that 'key' is an int because that is useful: [-main-] Dev: config section: ns/server/server1 [-main-] Dev: config: (null):maxthreads value=(null) min=0 max=100 default=10 (int) And really we always want this information. So maybe ns_setconfig should be more like: ns_setstringconfig section key value ns_setboolconfig section key value ns_setintconfig ?-min n? ?-max n? ?--? section key value And if you do that, then as ns_getconfig is implicitly a set on the first call with a default, then maybe ns_getconfig should be more like: ns_getstringconfig section key ?default? ns_getboolconfig section key ?default? ns_getintconfig ?-min n? ?-max n? ?--? section key ?default? ns_getconfig ?section? ?key? $ ns_getconfig ns/foo ns/bar $ ns_getconfig ns/foo a b $ ns_getconfig ns/foo a type int value 42 min 0 max 99 Or, considering this common idiom: ns_section "ns/foo" ns_param bar greeble ;# Oh, Hi! ns_setstringvalue ?-description d? section key ?default? $ ns_getconfig ns/foo bar type string value greeble description "Oh, Hi!" > > A buffer size of 'no' doesn't make any > > sense. > > But > > ns_getconfig section buffer no (module A) > ns_getconfig section buffer 1000 (module B) > > is the application problem, not ours. > > This is simply clash of config params. I do not > think we need to take care of that. The above would not throw an error, they're of Unknown type. It would throw an error if one specified -bool and the other -int. But that is an error (of the application). A single key in a section can't have two types at once. You can treat it as two different types once you get it into Tcl, but that's just standard Tcl. |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-24 18:53:00
|
On 24.10.2007, at 20:35, Stephen Deasey wrote: > On 10/24/07, Vasiljevic Zoran <zv...@ar...> wrote: >> >> On 24.10.2007, at 19:09, Vasiljevic Zoran wrote: >> >>> So >>> >>> ns_getconfig -bool section param 1 >>> ns_getconfig -int section param >>> configuration parameter is not an integer >>> >>> would make you happy? >>> >> >> Lets stop and think about consequences of this... >> >> Underneath, some integer will be used to hold >> the value of the boolean param. After all,we >> have C underneath. Now somebody will go get >> integer rep of it and will receive error >> because the type is boolean. Good for the moment. >> But consider this: >> >> ns_getconfig section param "1" >> ns_getconfig -bool section param >> >> How should we react here? The "1" is not a boolean >> value. It is an string. > > > It should be 'unknown'. i.e. this: > > typedef enum { > UnknownType, > StrType, > IntType > } ParamType; > > Should be more like this: > > typedef enum { > UnknownType, > BoolType, > IntType > } ParamType; > > > The conversion rules would be that you can go from Unknown to Bool or > Int, but not the other way around, and you can't go from Bool to Int > or vice versa. > > So code like this: > > ns_getconfig section key 42 > > would set a value of unknown type if not present. Code like this: > > ns_getconfig -int section key 42 > > would cause it's type to become Int. It's then OK to follow that > sequence with: > > ns_getconfig section key 42 > > again. The underlying C code would actually return a Tcl Integer type, > but that doesn't matter. > > If you don't specify either -int or -bool then you're either setting > an unknown type or are happy to receive any type. Type conversion and > checking can still occur, but that's standard Tcl: > > if {[ns_getconfig section key]} { return [expr $key + 2] } > > If we were still at step 1 above, they key with type Unknown would be > returned as a string and Tcl would convert to an int. > > > It *is* kinda weird to build (but easy to use), but that's because > we're using a command designed for the read-only existing config. > Explicitly, ns_getconfig with a default param is just shorthand for > this sort of code: > > if {[catch { > set value [ns_getconfig -int section key] > } err]} { > ns_setconfig -int section key 42 > set value 42 > } > > The first time the code is called, when there is no record of the key > or value in the global config, there is an implicit call to set. > > We want to record that 'key' is an int because that is useful: > > [-main-] Dev: config section: ns/server/server1 > [-main-] Dev: config: (null):maxthreads value=(null) min=0 max=100 > default=10 (int) > > > And really we always want this information. So maybe ns_setconfig > should be more like: > > ns_setstringconfig section key value > ns_setboolconfig section key value > ns_setintconfig ?-min n? ?-max n? ?--? section key value > > And if you do that, then as ns_getconfig is implicitly a set on the > first call with a default, then maybe ns_getconfig should be more > like: > > ns_getstringconfig section key ?default? > ns_getboolconfig section key ?default? > ns_getintconfig ?-min n? ?-max n? ?--? section key ?default? > > ns_getconfig ?section? ?key? > > $ ns_getconfig > ns/foo ns/bar > > $ ns_getconfig ns/foo > a b > > $ ns_getconfig ns/foo a > type int value 42 min 0 max 99 > > > Or, considering this common idiom: > > ns_section "ns/foo" > ns_param bar greeble ;# Oh, Hi! > > > ns_setstringvalue ?-description d? section key ?default? > > > $ ns_getconfig ns/foo bar > type string value greeble description "Oh, Hi!" > > OK. I buy everything. So, supported conversion rules: Unknown -> any Int -> Unknown Bool-> Unknown and unsupported: Int -> Boolean Boolean -> Int (more types like floating, wide can be introduced later, if needed). Commands ns_getconfig/ns_setconfig ?-type? I would leave as is. Without the specific type, if the argument is already set, the conversion is done as any->unknown (AND the parameter shimmers). If the parameter is not there and default is given it is recored as Unonown type. In all other cases, type-checking is introduced. Do we now have consensus here? I would not like to change the code every 5 minutes, so lets stick to (any) spec and go from there. I believe we have something good now that we can build upon. |
From: Stephen D. <sd...@gm...> - 2007-10-24 19:31:54
|
On 10/24/07, Vasiljevic Zoran <zv...@ar...> wrote: > > OK. I buy everything. > > So, supported conversion rules: > > Unknown -> any > Int -> Unknown > Bool-> Unknown Unknown -> Int || Bool Valid for the value stored in the config itself. On the way out: Int || Bool -> no assert when asked for Unknown. i.e. no conversion is going on, but the checking (assertion) rules are relaxed. (Just clarifying what's getting converted, where). > and unsupported: > > Int -> Boolean > Boolean -> Int > > (more types like floating, wide can be introduced later, if needed). Yes. |
From: Vasiljevic Z. <zv...@ar...> - 2007-10-24 20:38:25
|
On 24.10.2007, at 21:31, Stephen Deasey wrote: > Yes. It is (now in CVS). We now only have knownBugs left, but we will never bee case-insensitive I guess. Now: where you want to go today? Couple of issues still left: persistence wideint type parameter introspection (you name it) Cheers Zoran |