Simultaneous Database Access and Locking
The CentraSite implementation stores all RegistryObjects in a common repository, which is a database. If multiple JAXR-based clients (or, to be more precise, multiple JAXR-based connections) are active simultaneously, it is possible that they might read and update the data in the common database concurrently.
Multiple clients that update a RegistryObject must be synchronized in order to prevent lost updates. Usually, this is handled by the underlying database's locking mechanism. However, since it is likely that many JAXR-based clients would be browsing or searching the repository and only a few JAXR-based clients would be modifying data, the CentraSite implementation has been optimized to allow maximum concurrent access. In particular, if one or more JAXR-based clients are reading a RegistryObject, another JAXR-based client may update it concurrently.
For example, if a user has opened CentraSite Control to look for a particular object and then keeps his or her UI open for a protracted period – maybe even for several days – this should not prevent other users from updating that object.
Locks for read access are therefore relatively permissive, but of course it must be ensured that two JAXR-based clients cannot modify the same object at the same time. This is achieved as follows:
When a JAXR-based client starts to modify a RegistryObject, JAXR acquires an exclusive lock for this object from the database management system. This prevents any other client from updating the same object at the same time. When the JAXR-based client saves the modified object, the lock is released as a side-effect of calling LifeCyclemanager.saveObjects(). Alternatively, if the JAXR-based client decides to discard the changes, it should release the lock by calling CentraSiteConnection.rollback().
With this locking behavior, there are two principal scenarios when two JAXR-based clients attempt to modify the same object at the same time. Bear in mind that in order to modify an object, the JAXR-based client always has to read it first, then modify the Java instance, then call saveObjects() in order to write the modified object back to the database.
Scenario A
JAXR-based Client A | JAXR-based Client B |
1. Read a RegistryObject. | |
| 2. Read the same RegistryObject. |
3. Start to modify the object. This automatically locks the object. | |
| 4. Start to modify the object. The attempt to lock the object fails and a LockNotAvailableException is thrown. |
As long as client A holds the exclusive lock for the object, client B is unable to modify it.
Scenario B
JAXR-based Client A | JAXR-based Client B |
1. Read a RegistryObject. | |
| 2. Read the same RegistryObject. |
3. Start to modify the object. This automatically locks the object. | |
4. Save the object. This releases the lock. | |
| 5. Start to modify the object. The attempt to lock the object fails and an ObjectOutdatedException is thrown. |
In scenario B, client A has finished making its changes and has released the lock, so the lock is now available for acquisition by another client, for example client B. However, client B's local copy of the object does not reflect the current database status of the object, which has been modified in the meantime by client A. If client B were allowed to save object, client A's modifications would be overwritten.
To avoid this, each RegistryObject has a last-modification date. When a lock is acquired, the API checks whether the last-modification date of the object in the database is the same as the last-modification date of the client's local copy of the object. If the dates are not the same, an ObjectOutdatedException is thrown. This ensures that updates are not lost and that all modifications are based on the latest state of the object.
Immediately before the ObjectOutdatedException is thrown, the API cleans up its internal structures. When the client catches the exception, it should release all references to the RegistryObject and then re-read it. This should return the latest copy of the object from the database; the client can now continue to make the necessary modifications to this clean copy.