Cooperative locking is a mechanism that is intended to prevent concurrent updates to an object by two or more Content Engine API-based applications. The mechanism is cooperative because applications volunteer to lock objects, check for locks, and honor an object's locked state by not modifying the object until it is unlocked. Note that any application with the appropriate permissions can perform any action on an object regardless of whether it is locked or not. In addition, an object's lock is not checked or honored by non-cooperating applications. Cooperative locking does not prevent an application from updating or deleting a locked object. Cooperative locking provides a voluntary mechanism to lock objects, test for locks, and decide which action to take based on the object's lock state.
You can lock objects of the following interfaces (and subinterfaces): CustomObject, Document, and Folder. These interfaces provide methods for locking, unlocking, extending a lock, and checking the lock status of an object. In addition, the superinterface, Containable, provides readable properties with lock information, such as the owner and duration of a lock.
Locking or unlocking an object creates a pending action instance of Lock or Unlock. When these actions are committed to the server, a LockEvent or UnlockEvent is triggered. These events can be audited.
To modify a document, folder, or custom object, an application that participates in cooperative locking performs the following steps:
Before you modify a document, folder, or custom object, an application that participates in cooperative locking would first check the lock state of an object, and, if locked, perhaps get information about the lock.
For code samples, see Working with Lockable Objects.
You apply a lock to an object by calling the object's lock method. The timeout parameter of the lock method is the number of seconds that the object is to be locked. The expiration time equals the time value of the object's DateLastModified property plus the number of seconds specified in the lock method's timeout parameter. Subsequent update activity on an object by the lock owner causes the DateLastModified time to change, which has the side effect of refreshing the lock and extending the lock's timeout period. The lock owner can also explicitly call the updateLock method to extend the lock's timeout period. Although calling this method is the recommended way to extend a lock, a similar effect might be achieved by calling the unlock method followed by the lock method, another application might intervene between the calls and steal the lock.
After you call the lock or updateLock method on an object, you must save it to commit the lock operation on the server. You must have at least the AccessRight.WRITE permission to successfully run the save.
While a CustomObject, Document, or Folder is locked, other cooperating applications must treat the object as if they have read access to it until the lock is removed or expires.
After an object is locked, the lock owner can modify the content, properties, and permissions of the locked object as is normally done. The extent of the modifications that can be performed depends on the scope of the lock owner's permissions.
The owner of an object's lock can remove the lock in one of the following ways:
If you attempt to unlock an object that's not locked, an EngineRuntimeException is thrown with an exception code of E_OBJECT_NOT_LOCKED.
An application that participates in cooperative locking must determine the lock status of a CustomObject, Document, or Folder object before it attempts to modify the object. While the isLocked method is provided to test the lock status, note that this method returns an approximation of the locked state at the time of the call. After this method runs and returns the value, the object's lock state might be immediately changed by another application's call to the lock method or the lock might expire. Therefore, the recommended way of testing the status is to call the lock method and then handle any exception that is thrown if the method fails.
If an object is locked, an application can get information about the lock from the Containable interface, which has the following lock-related, read-only properties. These properties are populated as a result of a successful call to the lock method, and are stored in the property cache of the object.