If the RES-Reach service is stopped, permanent public variables are stored in a reachvar.dat file located in the directory specified by the netbase.ini file. When the service is re-started, they are loaded back into global memory.
4.6.2.1 Creation and Assignment: PUT
If the public variable has not been created yet, then the PUT function is used to create it. Existing public variables must be locked before the PUT function is called (see Section 4.6.2.3 below). To create a public variable and/or set its value, the syntax is:
<SET VARIABLE="varname" FUNCTION="PUT" VALUE="this value" EXPIRE="1200">This sets the value of the public variable named "varname" to the string "this value" and sets or changes its expiry to 1200 milliseconds from the time of the assignment.
If the public variable does not exist, the "PUT" creates it.
If the EXPIRE attribute is the empty string or it is missing altogether, it is assumed to be "0". An expiry of "0" indicates that the variable is permanent, i.e. it has an infinite lifespan. RES-Reach will try to ensure that it and its value survive a RES-Reach service shutdown.
Any other user or thread can change the value of a permanent public variable and can reduce its lifespan by changing its expiry as long as it is not locked.
If, after _RUN.WAIT milliseconds, the public variable cannot be given the new value (probably because it is locked by another thread or user), then _RUN.errno is given the value "HY000" and _RUN.errstring is "General error". The public variable value remains at whatever it was before the assignment attempt was made.
If _RUN.WAIT is "0", there is only one try at setting the variable value. If it fails for any reason (and it will fail if the variable is locked by another thread) the value of the variable will not be changed.
4.6.2.2 Retrieval: GET
To get the value of a public variable, the syntax is:
<SET VARIABLE="varname" FUNCTION="GET">This assigns the value of the public variable "varname" to the temporary, private variable "varname" overriding any previous value it may have had. If the public variable does not exist or does not have a value or some other problem occurs while trying to find it, the value of the temporary, private variable value is unchanged (if it had one). _RUN.errno is also set to "HY092" and _RUN.errstring is "Invalid attribute/option identifier".
The run-time variable "_RUN.WAIT" is used to determine how long this retrieval command should wait before declaring a failure. If it times out and the public variable has a value, _RUN.errno will be "HYT00" and _RUN.errstring will be "Timeout expired".
Example:
<SET VARIABLE="_RUN.WAIT" VALUE="5">If _RUN.WAIT is "0", there is only one try at fetching the variable value. If it fails for any reason, the value of the temporary variable will be unchanged and _RUN.errno will reflect the failure, as discussed above.
4.6.2.3 Locking: LOCK
Because public variables are accessible to all RES-Reach threads and users, they must be locked before assigning them a value. The syntax for this is:
<SET VARIABLE="varname" FUNCTION="LOCK">This places an exclusive lock on the variable, preventing other threads or users from locking it and from changing its value and expiry attribute (although they can still retrieve its value). It also retrieves the value of the public variable placing it into a temporary, private variable of the same name.
If the public variable did not exist before the lock attempt, it can still be locked.
If, after _RUN.WAIT milliseconds, the public variable cannot be locked (probably because it is locked by another thread or user), then _RUN.errno is given the value "HYT00" and _RUN.errstring is "Timeout expired". If _RUN.WAIT is 0, only one attempt will be made to lock the variable.
Any subsequent lock attempt on a variable locked by the same thread will be ignored, i.e. if you already have a lock on the variable, RES-Reach will ignore you if you try to lock it again.
Locks are released by the same thread using the UNLOCK function or when the thread terminates.
4.6.2.4 Unlocking: UNLOCK
To unlock a public variable, the syntax is:
<SET VARIABLE="varname" FUNCTION="UNLOCK">This will release the exclusive lock the thread had on the named public variable. The value of the private variable is updated to match the public variable value.
If the variable does not exist or was not locked by this thread, this command is ignored and error "HY092" ("Invalid attribute/option identifier") is reported. The value of the private variable is not updated in this case.
If, after _RUN.WAIT milliseconds, the lock cannot be released, then _RUN.errno will be set to the value "HY000" and _RUN.errstring will be "General error".
If _RUN.WAIT is 0, only one attempt is made to unlock the variable.
Examples:
Example 1: This example shows how a global counter could be implemented using public variables.
Test, by repeatedly clicking on the button, that a global counter works correctly. Note that because we cannot compare numerical values, the last value of the counter may not be the highest. <P><SET VARIABLE="_RUN.LIBS" VALUE="R32DLL.DLL"> <IF VARIABLE="{USER_ACTION}" OPERATOR="EQ" COMPARISON="ADD_PRODUCT"> <SET VARIABLE="_RUN.WAIT" VALUE="120000"> <SET VARIABLE="UserCount" FUNCTION="GET"> Status after GET: {ErrNo}, {Errstring}<BR> Value of "UserCount": {UserCount}<BR><SET VARIABLE="UserCount" FUNCTION="LOCK"> Status after LOCK: {ErrNo}, {Errstring}<BR><SET VARIABLE="LockStatus" VALUE="{ErrNo}"> Value of "UserCount" after LOCK: {UserCount}<BR><IF VARIABLE="{LockStatus}" OPERATOR="EQ" COMPARISON="00000"> <![ If the variable does not have a value yet, then set the local copy to 0. ]> <IF VARIABLE="{UserCount}" OPERATOR="EQ" COMPARISON="{Unknown}"> <SET VARIABLE="UserCount" VALUE="0"> </IF><SET VARIABLE="UserCount" FUNCTION="INCR" VALUE="{UserCount}"> Incremented value of "UserCount": {UserCount}<BR><SET VARIABLE="UserCount" FUNCTION="PUT" VALUE="{UserCount}" EXPIRE=""> Status after PUT: {ErrNo}, {Errstring}<BR><SET VARIABLE="UserCount" FUNCTION="UNLOCK"> Status after UNLOCK: {ErrNo}, {Errstring}<BR> </IF><SET VARIABLE="UserCount" FUNCTION="GET"> Status after GET: {ErrNo}, {Errstring}<BR> Value of "UserCount" after GET: {UserCount}<BR> </IF> <FORM NAME="ActionForm" ACTION="{GET_NBT}" METHOD="GET"> <INPUT TYPE="hidden" NAME="NBT" VALUE="{NBT}"> <INPUT TYPE=hidden NAME="USER_ACTION" VALUE="ADD_PRODUCT"> <CENTER> <INPUT TYPE="submit" VALUE="Test"> </CENTER> </FORM>