first previous next last contents

Locking Mechanisms

When preparing to update data it is essential that a function checks whether other displays are currently accessing this data, and if so whether these displays are allowing the data to be modified.

This is implemented with use of the REG_GET_LOCK and REG_SET_LOCK notifications. These notifications both both include a lock field within their structures. This is initially set to the mode of access desired (currently REG_LOCK_WRITE is the only one we support). The contig_notify call is then used to send this notification to all appropriate data callbacks. If a callback wishes to block the request to write it should clear this lock flag.

The calling code then checks the returned status of the lock flag. If the REG_LOCK_WRITE bit is still set then it knows locking is allowed. In this case notification of the acceptance of this lock is sent around using the REG_SET_LOCK request. An example of the communication follows. To send the lock request we do:

    reg_get_lock lg;

    lg.job = REG_GET_LOCK;
    lg.lock = REG_LOCK_WRITE;

    contig_notify(io, contig, (reg_data *)&lg);

The default action of ignoring the REG_GET_LOCK request will allow the write operation to take place. The contig editor does not support updates of the contig that it is editing other than those made by itself, so it needs to block such locks. The callback procedure of the contig editor contains:

    case REG_GET_LOCK:
        /*
         * We need exclusive access, so clear any write lock
         */
        if (jdata->glock.lock & REG_LOCK_WRITE)
            jdata->glock.lock &= ~REG_LOCK_WRITE;

        break;

The calling code should now check the status of the lock and send a REG_SET_LOCK request if the lock was not blocked:

    if (lg.lock & REG_LOCK_WRITE) {
        reg_set_lock ls;

        ls.job = REG_SET_LOCK;
        ls.lock = REG_LOCK_WRITE;

        contig_notify(io, contig, (reg_data *)&ls);

        [ ... ]
    }

To simplify this procedure, the contig_lock_write function performs the above lock request and acknowledge protocol.

int contig_lock_write(GapIO *io, int contig);

Returns:  0 for success (write granted)
         -1 for failure (write blocked)

In some cases, where large amounts of data are modified in unpredictable fashion, it is easier to simply shut down all displays viewing the database before proceding. This is especially true of functions such as assembly where all contigs maybe modified. In this case we use the locking mechanism once more, except with a REG_QUIT call instead of REG_GET_LOCK. The same procedure of checking and clearing (if necessary) the lock flag is used. Once again, an example from the contig editor callback illustrates the procedure.

    case REG_QUIT:
        /*
         * We are being asked to quit. We can only allow this is we
         * haven't made changes.
         */
        if (_editsMade(db)) {
            jdata->glock.lock &= ~REG_LOCK_WRITE;
        } else {
            DBI_callback(db, DBCALL_QUIT, 0, 0, NULL);
        }

        break;

The code above checks whether the editor has made any edits. If not the editor is shutdown, otherwise the REG_LOCK_WRITE flag is cleared.

The tcl_quit_displays function can be used to perform the REG_QUIT locking procedure. Currently this is an interface to Tcl and no C interface, other than using the contig_notify with REG_QUIT, exists. See section Tcl Interfaces.


first previous next last contents
This page is maintained by staden-package. Last generated on 1 March 2001.
URL: http://www.mrc-lmb.cam.ac.uk/pubseq/manual/scripting_190.html