IntroductionThe semaphore template allows locking of critical code between Presentation Engine instances. ConceptsThe implementation works on the model of 'lock' and 'release'. An area of code that may only execute on
one presentation engine instance at a time must be preceded by a request to lock the specified semaphore.
Once the critical section has completed the lock must be released. For example, suppose we wish to read the content on an individuals contact record - update a field and write
that record back safely without conflict from another page being executed on another Presentation Engine instance.
// Wait for the semaphore to be available
var key;
for (var i=0;key==null && i<100;i++)
key = rb.semaphore.lock('contactSemaphore',60,'update the login count');
if (key!=null) {
// Managed to lock the semaphore. Do the work.
var record = rb.contact.IndividualInfo(-1,'fredb');
record.customData.loginCount++;
rb.contact.modify(record);
// Finally - remember to release the semaphore!
rb.semaphore.release('contactSemaphore', key);
}
You can see in this example that the first parameter to both the lock
and release methods is
a string. This is the name of the semaphore, and can be any arbitrary string. The name must be assigned by the
application in such a way that all instances of the Presentation Engine can agree on the name. For example - if you simply want a global lock, as in the example, a simple name such as 'contactSemaphore' is fine.
If you want more control, so for example you want to be able to protect individual records then an
algorithmically generated name may be more appropriate. In the able example you can effectively lock an
individual by using a semaphore name of 'contact/'+uName, ie the name includes the thing that makes it
unique to that contact. The 'lock' method takes
three parameters. The first is the name. The second is a timeout. There is always the possibility for a presentation
engine instance to fail, most often due to scripting errors. In this case there would be no way to
recover a locked semaphore without manual intervention. Most things being locked will take a finite amount of time. The example of updating the contact record above is highly
unlikely to take more than a minute. The call the lock
sets the timeout to 60 seconds (second parameter). If the semaphore is still locked after this time then the system
will automatically release it. Some operations could take considerably longer. It is quite possible for example for big batch job to take say 30 minutes, during
which time you want to lock access to the system. Setting a timeout of say 60 minutes or more caters for this. Other UsesThe most common usage of semaphores is outlined above. There is a second use however which is derived
from the automatic timeout of a semaphore. Suppose in our application we want to cache a particularly heavy operation in a file object, but want to refresh the
cache if it image it stores is more than 5 minutes old. You can do this with the following code:
// Wait for the semaphore to be available
var key;
key = rb.semaphore.lock('updateCache',5*60,'check for cache refresh');
if (key!=null) {
// Because of automatic timeout it is *at least*
// 5 minutes since the last attempt to lock the semaphore.
// Update the cache
...
}
// NOTE the semaphore is never released by the code. There
// are no calls to rb.semaphore.release
This code relies on the fact that the semaphore is never released by the Presentation Page, but will authoatically
be released after 5 minutes by the system. DebuggingWhile not specifically for debug purposes, the semaphore template provides a means to iterate
over all the currently locked semaphores within an application. All the information is returned to
the caller including the ownershipID assigned to the owning Presentation Engine. This
interface provides enough information to allow another PE to release a locked semaphore should this
be absolutely necessary - usually only dirung debug. |