CGI Services Architecture
Recent Pages

Environment Variables
Template Processing
RDF Responses
RDF Messaging
URL Rewriting
File Uploads
Sample Authenticated Se ...
HTTP Cookies
Client Authentication
GET and POST Variables

Links on Twitter
CSA Home
Table of Contents



User ID

Campaigns petition banner

Handling Concurrency

The standard CSA? library provides functions that are needed to handle concurrent access to the data by multiple programs, with the objective of preserving file integrity during update operations. Concurrency is handled through the use of lock-files, or semaphores. These can be created/destroyed with the relevant CSA library functions csaLock and csaUnlock. Handling locks is a tricky subject, due to the possibility of race-conditions that may lead to either data corruption or dead-locks. The former can occur whenever we have a test operation, followed by an action based on the result of the test. This test-action sequence is non-atomical, hence the potential for races. Starting from CSA version 1.1.0, locking relies on the Open Lock Daemon (OLD), a program especially conceived for this purpose and that can safely be used also when the files to be locked leave on NFS-mounts. One problem with previous releases of CSA was about stale-locks, i.e. semaphores left in place by processes that died prematurely. After switching to OLD for locking, this is now no longer an issue. The down-side is that the previous mechanism based on the lockfile(1) utility was time-honoured, while the new one is less mature and may well have bugs.

Preventing dead-locks is another issue that the library functions try to cope with, although for this to be effective a CSA application program must be designed sensibly in the first place.

As a rule-of-thumb, semaphores MUST be set whenever any of the following conditions are met:

  1. A program needs to write/delete data. If the operation is based on a previous read operation, the lock MUST be set before the read (reading+writing is non-atomical): in the CSA parliance this condition is called Non-Atomical Write (NAW).
  2. A program needs to read data from multiple files, for instance as a result of a join operation between two table-files (i.e. a view). If there is a chance that one or more of the involved files can be modified while we are reading them, then all the files SHOULD be locked before we start reading from any of them. I call this condition a Non-Atomical Read (NAR). In common database terminology, we need to make sure that nobody can break the referential integrity between the data that we are about to read from multiple, phisically-indipendent but logically-related, sources.

Whatever the locking policy, it is left entirely up to the CSA application program. The CSA library merely provides the locking primitives, but whether to lock individual files, whole directories, or other application-dependent collections of resources is an application-level affair from the CSA point of view.

Explicitly releasing lock-files is usually not necessary, as they are removed automatically when a program calls csaExit or one of its variants ( csaExit.ok, csaExit.fault, etc.). Removing one or more locks with an explicit call to csaUnlock may be necessary only if a program needs to iterate multiple times before exiting, and in general when it is expected to go on for a while before calling csaExit. In such cases we SHOULD release the locks when we no longer need them, or others may time-out while waiting to try and set their own locks on the same resources.


A program that wants to read from, or write to a certain file, and that wants to make sure that nobody else changes that file in the meantime, can set a lock on that file as follows:

 csaLock /path/to/file || csaExit.fault 0007 /path/to/file 
 csaExit.ok 0028 
The csaLock function will then tell OLD to lock a resource named /path/to/file.lock, returning non-zero if the operation fails. If the lock already exists, csaLock will keep trying for a pre-defined number of seconds, after which it will give-up and fail with a error.

In the example, if the lock fails, an error exit is taken, with a suitable error message. If locking succeedes, csaLock returns zero and the program continues (in this case it will simply exit with a positive completion message). It is normally not necessary to release a lock when it is no longer needed, as that will occur anyway when the program terminates with any of the CSA functions of the csaExit.* family.

There is a lot more to be said to use lock-files properly. I'll eventually expand this section a bit, to try and make it more useful.

Trackbacks (0) | New trackback | Print

This Web Site is Copyright © 2007,2008,2009,2010 Carlo Strozzi, Some Rights Reserved
site map | recent changes | disclaimer