Index: openacs-4/packages/acs-core-docs/www/programming-with-aolserver.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/programming-with-aolserver.adp,v diff -u -r1.1.2.3 -r1.1.2.4 --- openacs-4/packages/acs-core-docs/www/programming-with-aolserver.adp 28 Sep 2015 07:54:22 -0000 1.1.2.3 +++ openacs-4/packages/acs-core-docs/www/programming-with-aolserver.adp 23 Jun 2016 08:32:46 -0000 1.1.2.4 @@ -18,12 +18,14 @@ two types of global namespace, not one:
-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).
+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).
Script-global: Each Tcl
script (ADP, Tcl page, registered proc, filter, etc.) executing
within an AOLserver thread has its own global namespace. Any
@@ -36,11 +38,12 @@
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.
+(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.-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,
+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.
Note also that thread is initialized +runs frequently, don't use the
-thread
switch.Note also that thread is initialized with a copy of what was installed during server startup, so if the procedure table have changed since startup (e.g. using the APM watch facility), that will not be @@ -73,9 +76,10 @@ 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 usead_script_abort
to -abort the remainder of the thread. Note that usingreturn
instead ofad_script_abort
may raise some security +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 usingreturn
instead ofad_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 @@ -88,13 +92,13 @@ Value From a Function
Many functions have a single return value. For instance,
util_email_valid_p
returns a number: 1
or 0. Other functions need to return a composite value. For
-instance, consider a function that looks up a user's name and email
-address, given an ID. One way to implement this is to return a
-three-element list and document that the first element contains the
-name, and the second contains the email address. The problem with
-this technique is that, because Tcl does not support constants,
-calling procedures that returns lists in this way necessitates the
-use of magic numbers, e.g.:
+instance, consider a function that looks up a user's name and +email address, given an ID. One way to implement this is to return +a three-element list and document that the first element contains +the name, and the second contains the email address. The problem +with this technique is that, because Tcl does not support +constants, calling procedures that returns lists in this way +necessitates the use of magic numbers, e.g.:set user_info [ad_get_user_info $user_id] set first_name [lindex $user_info 0] set email [lindex $user_info 1] @@ -128,17 +132,17 @@ return [array get user_info] } -Using Arrays and Pass-By-Reference
Sometimes pass-by-value incurs too much overhead, and you'd -rather pass-by-reference. Specifically, if you're writing a proc -that uses arrays internally to build up some value, there are many -entries in the array, and you're planning on iterating over the -proc many times. In this case, pass-by-value is expensive, and -you'd use pass-by-reference.
The transformation of the array into +
Using Arrays and Pass-By-Reference
Sometimes pass-by-value incurs too much overhead, and you'd +rather pass-by-reference. Specifically, if you're writing a +proc that uses arrays internally to build up some value, there are +many entries in the array, and you're planning on iterating +over the proc many times. In this case, pass-by-value is expensive, +and you'd use pass-by-reference.
The transformation of the array into a list and back to an array takes, in our test environment, -approximately 10 microseconds per entry of 100 character's length. -Thus you can process about 100 entries per milisecond. The time -depends almost completely on the number of entries, and almost not -at all on the size of the entries.
You implement pass-by-reference in Tcl by taking the name of an +approximately 10 microseconds per entry of 100 character's +length. Thus you can process about 100 entries per milisecond. The +time depends almost completely on the number of entries, and almost +not at all on the size of the entries.
You implement pass-by-reference in Tcl by taking the name of an array as an argument and
upvar
it.@@ -162,16 +166,16 @@ Pass-by-reference makes the code harder to read and debug, because changing a value in one place has side effects in other places. Especially if have a chain ofupvar
s through several layers of the call -stack, you'll have a hard time debugging.Multisets: Using
ns_set
s and -Pass-By-ReferenceAn array is a type of set, which means you can't have multiple -entries with the same key. Data structures that can have multiple -entries for the same key are known as a multiset or bag.
If your data can have multiple entries with the same key, you +stack, you'll have a hard time debugging.
Multisets: Using
ns_set
s and +Pass-By-ReferenceAn array is a type of set, which means you can't have +multiple entries with the same key. Data structures that can have +multiple entries for the same key are known as a multiset or bag.
If your data can have multiple entries with the same key, you should use the AOLserver built-in
ns_set
. You can also -do a case-insensitive lookup on anns_set
, something you can't easily do on an -array. This is especially useful for things like HTTP headers, -which happen to have these exact properties.You always use pass-by-reference with
ns_set
s, since they don't have any built-in -way of generating and reconstructing themselves from a string -representation. Instead, you pass the handle to the set.+do a case-insensitive lookup on anns_set
, something you can't easily do +on an array. This is especially useful for things like HTTP +headers, which happen to have these exact properties.You always use pass-by-reference with
ns_set
s, since they don't have any +built-in way of generating and reconstructing themselves from a +string representation. Instead, you pass the handle to the set.ad_proc ad_get_user_info { -set:required @@ -189,11 +193,11 @@ doc_body_append "[ns_set get $user_info namelink] ([ns_set get $user_info emaillink])" -We don't recommend
ns_set
as -a general mechanism for passing sets (as opposed to multisets) of -data. Not only do they inherently use pass-by-reference, which we -dis-like, they're also somewhat clumsy to use, since Tcl doesn't -have built-in syntactic support for them.Consider for example a loop over the entries in a
ns_set
as compared to an array:+We don't recommend
ns_set
as a general mechanism for passing +sets (as opposed to multisets) of data. Not only do they inherently +use pass-by-reference, which we dis-like, they're also somewhat +clumsy to use, since Tcl doesn't have built-in syntactic +support for them.Consider for example a loop over the entries in a
ns_set
as compared to an array:# ns_set variant set size [ns_set size $myset] @@ -226,8 +230,8 @@ However, when usingns_set get
to perform lookup by name, they perform a linear lookup, whereas arrays use a hash table, sons_set
s are slower than arrays when the -number of entries is large.($Id: programming-with-aolserver.xml,v 1.7 -2014/10/27 16:39:30 victorg Exp $)+number of entries is large.($Id: programming-with-aolserver.html,v +1.49.2.10 2016/06/21 07:44:36 gustafn Exp $)