The repository lock mechanism ensures that only one Jackrabbit instance can open the same repository at one time. By default, when a repository is started, Jackrabbit tries to create a file named .lock in the repository home directory and protects it using using a native file lock. If the repository is already in use, this will fail, usually with one of the following exceptions / entries in the log file:
Existing lock file at ../.lock detected. Repository was not shut down properly. javax.jcr.RepositoryException: The repository home ... appears to be in use since the file named .lock is locked by another process. or The repository home ... appears to be in use since the file named .lock is already locked by the current process. or OverlappingFileLockException
In the first case, the repository is already open in another process. Please stop the other process first.
In the second and third case, the repository is already open in the same process but within another class loader (for example, in another web application). In this case you need to ensure that the repository is closed when the web-application is stopped.
Why Is the Repository Locked
Jackrabbit works like a file system or database: to improve performance, Jackrabbit caches frequently used data, and keeps transient changes in memory until they are saved explicitly. Therefore, to avoid inconsistencies and corruption, it must be ensured that the same repository is only accessed by one process at a time.
How to Access the Repository from Multiple Processes
An alternative is to use Clustering.
When to Manually Delete the Lock File
Deleting the lock file manually is normally not necessary, even if the repository was not closed before.
The only case where it may be required to manually delete the repository lock file is when using an NFS share (for some NFS implementations), and the NFS server died and was re-started. Some NFS servers will not release the file lock in this case.
Using the Cooperative File Lock Mechanism
Since Jackrabbit 1.6 an alternative repository locking mechanism is available.
Some NFS implementations do not release native locks after a hard reboot. In this case the workaround is to manually delete all .lock files. Older NFS implementation throw the exception "No locks available", which means the NFS does not support native file locks.
To solve this problem, Jackrabbit also supports cooperative file locking. This mechanism is not based on native file locks, but instead uses background threads that periodically update a sentinel file (lock.properties). The algorithm of cooperative file locking is described below. To use cooperative file locking, add this to your repository.xml before the </Repository> tag:
<RepositoryLockMechanism class="org.apache.jackrabbit.core.util.CooperativeFileLock" />
Cooperative File Locking Algorithm
The cooperative file locking works as follows:
- If the lock.properties file does not exist, it is created (using the atomic operation File.createNewFile). Then, the process waits a little bit and checks the file again. If the file was changed during this time, the operation is aborted. This protects against a race condition when one process deletes the lock file just after another one create it, and a third process creates the file again. It does not occur if there are only two writers.
- If the file can be created, a random id is inserted. Afterwards, a watchdog thread is started that checks regularly (every second once by default) if the file was deleted or modified by another (challenger) thread or process. Whenever that occurs, the file is overwritten with the old data. The watchdog thread runs with high priority so that a change to the file does not get through undetected even if the system is very busy. However, the watchdog thread does use very little resources (CPU time), because it waits most of the time. Also, the watchdog only reads from the hard disk and does not write to it.
- If the file exists and was recently modified, the process waits for some time (up to two seconds). If it was still changed, an exception is thrown. This is done to eliminate race conditions with many concurrent writers. Afterwards, the file is overwritten with a new version (challenge). After that, the thread waits for 2 seconds. If there is a watchdog thread protecting the file, he will overwrite the change and this process will fail to lock the repository. However, if there is no watchdog thread, the file will still be as written by this thread. In this case, the file is deleted and atomically created again. The watchdog thread is started in this case and the file is locked.