Programming with AOLserver

by Michael Yoon and Jon Salz
part of the ACS Engineering Manual

The global command

When using AOLserver, remember that there are effectively two types of global namespace, not one:
  1. Server-global: As you'd expect, there is only one server-global namespace per server, and variables set within it can be accessed by any Tcl code running subsequently, in any of the server's threads. To set/get server-global variables, use AOLserver 3's nsv API (which supersedes ns_share from the pre-3.0 API).

  2. Script-global: Each Tcl script (ADP, Tcl page, registered proc, filter, etc.) executing within an AOLserver thread has its own global namespace. Any variable set in the top level of a script is, by definition, script-global, meaning that it is accessible only by subsequent code in the same script and only for the duration of the current script execution.
The Tcl built-in command global accesses script-global, not server-global, variables from within a procedure. This distinction is important to understand in order to use global correctly when programming AOLserver.

Also, AOLserver purges all script-global variables in a thread (i.e., Tcl interpreter) between HTTP requests. If it didn't, that would affect (and complicate) our use of script-global variables dramatically, which would then be better described as thread-global variables. Given AOLserver's behaviour, however, "script-global" is a more appropriate term.

Threads and Scheduled Procedures

ns_schedule_proc and ad_schedule_proc each take a -thread flag to cause a scheduled procedure to run asychronously, in its own thread. It almost always seems like a good idea to specify this switch, but there's a problem.

It turns out that whenever a task scheduled with ns_schedule_proc -thread or ad_schedule_proc -thread t is run, AOLserver creates a brand new thread and a brand new interpreter, and reinitializes the procedure table (essentially, loads all procedures that were created during server initialization into the new interpreter). This happens every time the task is executed - and it is a very expensive process that should not be taken lightly!

The moral: if you have a lightweight scheduled procedure which runs frequently, don't use the -thread switch.

Using return

The return command in TCL returns control to the caller procedure. This definition allows nested procedures to work properly. However, this definition also means that nested procedures cannot use return to end an entire thread. This situation is most common in exception conditions that can be triggered from inside a procedure e.g., a permission denied exception. At this point, the procedure that detects invalid permission wants to write an error message to the user, and completely abort execution of the caller thread. return doesn't work, because the procedure may be nested several levels deep. We therefore use ad_script_abort to abort the remainder of the thread. Note that using return instead of ad_script_abort may raise some security issues: an attacker could call a page that performed some DML statement, pass in some arguments, and get a permission denied error -- but the DML statement would still be executed because the thread was not stopped. Note that return -code return can be used in circumstances where the procedure will only be called from two levels deep.