Forum OpenACS Development: using persistent variables in a package namespace

I'd like to define some variables in a package namespace to persist so long as the code is re-used.

I see the example in this thread that tests persistence of variable values: https://openacs.org/forums/message-view?message_id=174405

Yet, the variable is referenced in an absolute way ie $::foo::var_name and I understand that coding should use relative references such as foo::var_name and avoid absolute references.

Essentially, this is for defining a cache of constants and arrays within the environment. If the values persist between connections, then there's less of a load on the server to recalculate. If they have to be redefined every 10 or 1000 connections, no big deal. I'm just looking to be effective with memory usage.

What is the recommended way to do this?

grepping packages, nothing stands out as an example; given that acs-core uses practices that are not recommended for non-core packages.

cheers,
Benjamin

Collapse
Posted by Gustaf Neumann on
Dear Ben,

The rules of the variable cleanup are as following:
- all global variables (in the namespace "::") are cleaned up after every requests
- all other namespaced variables survive a request and are kept in the actual state in the per-thread interpreter of connection/scheduled thread until it shuts down.
- some packages perform management of the variables in "their" namespace (e.g. in the ::template:: namespace)

You are free what do do in your own namespace. If a connection thread set e.g. a variable ::x::v to 10 then another query executing in the same connection thread will see this variable and value when the query execution starts. However, be aware that when a thread sets a namespaced variable in its interpreter, the interpreters in other threads are unaffected. So, a new query might or might not be able to use this variable, since there is no built guarantee that the new query is executed in the same thread and there is no built-in synchronization for namespaced variables. Another consequence is that the namespaced variables are kept in every connection/scheduled thread, so there is some duplication.

A simple example for using namespaced variables is for caching of values from the DB, that will never change, like e.g. the package_id of acs-core. For this type of usage, namespaced variables are better than ns_cache (or nsvs), since the access does to the variable does not require a mutex lock.

If it is required to keep the variable value in sync with other threads (also, when e.g. a new connection thread starts) one approach is to do it same same way as for *-procs.tcl files. Add a file packages/mypkg/tcl/vars-procs.tcl to the source tree, set the variables there. This variables-file will be loaded at startup and can be reloaded at run-time via the reload operation in the package manager.

If an eventually consistent approach for communicating namespaced variables is fine, you could use ::xo::broadcast send {set ::x::v 123} or any other tcl command to update other interpreters (part of xotcl-core).

As for referring to variables: i would rather recommend to use absolute variable names (starting with "::"), since this is the only way to guarantee that you access this variable. For OpenACS (and other tcl packages) this is usually not an issue, since it uses a rather flat namespace, so the likelihood for a collision of a sub-namespace with a top-level namespace is little.

hope this helps
-g

Collapse
Posted by Benjamin Brink on
Thank you, Gustaf. You have answered my question as well as other questions I have about differences between various storage techniques and strategies that I was planning to investigate later this year. Truly, very helpful.