This chapter describes locks on documents and directories, and includes the following sections:
This chapter is about document and directory locks that you set explicitly, not about transaction locks which MarkLogic sets implicitly. To understand transactions, see Understanding Transactions in MarkLogic Server.
Each document and directory can have a lock. A lock is stored as a locks document in a MarkLogic Server database. The locks document is separate from the document or directory to which it is associated. Locks have the following characteristics:
Locks are write locks; they restrict updates from all users who do not have the locks. When a user has an exclusive lock, no other users can get a lock and no other users can update or delete the document. Attempts to update or delete documents that have locks raise an error. Other users can still read documents that have locks, however.
Locks are persistent in the database. They are not tied to a transaction. You can set locks to last a specified time period or to last indefinitely. Because they are persistent, you can use locks to ensure that a document is not modified during a multi-transaction operation.
Because locks are persistent XML documents, they are therefore searchable XML documents, and you can write queries to give information about locks in the database. For an example, see Example: Finding the URI of Documents With Locks.
You can set locks as exclusive
, which means only the user who set the lock can update the associated database object (document, directory, or collection). You can also set locks as shared
, which means other users can obtain a shared lock on the database object; once a user has a shared
lock on an object, the user can update it.
When you are locking a directory, you can specify the depth in a directory hierarchy you want to lock. Specifying "0"
means only the specified URI is locked, and specifying "infinity"
means the URI (for example, the directory) and all of its children are locked.
WebDAV clients use locks to lock documents and directories before updating them. Locking ensures that no other clients will change the document while it is being saved. It is up to the implementation of a WebDAV client as to how it sets locks. Some clients set the locks to expire after a time period and some set them to last until they explicitly unlock the document.
Any application can use locks as part of its update strategy. For example, you can have a policy that a developer sets a lock for 30 seconds before performing an update to a document or directory. Locks are very flexible, so you can set up a policy that makes sense for your environment, or you can choose not to use them at all.
If you set a lock on every document and directory in the database, that can have the effect of not allowing any data to change in the database (except by the user who owns the lock). Combining a application development practice of locking and using security permissions effectively can provide a robust multi-user development environment.
There are basically two kinds of APIs for locks: APIs to show locks and APIs to set/remove locks. For detailed syntax for these APIs, see the online XQuery Built-In and Module Function Reference.
The xdmp:document-locks function with no arguments returns a sequence of locks, one for each document lock. The xdmp:document-locks function with a sequence of URIs as an argument returns the locks for the specified document(s). The xdmp:directory-locks function returns locks for all of the documents in the specified directory, and the xdmp:collection-locks function returns all of the locks for documents in the specified collection.
You can set and remove locks on directories and documents with the following functions:
The basic procedure to set a lock on a document or a directory is to submit a query using the xdmp:lock-acquire
function, specifying the URI, the scope of lock requested (exclusive
or shared
), the hierarchy affected by the lock (just the URI or the URI and all of its children), the owner of the lock, the duration of the lock
The owner
of the lock is not the same as the sec:user-id
of the lock. The owner
can be specified as an option to xdmp:lock-acquire. If owner is not explicitly specified, then the owner defaults to the name of the user who issued the lock command. For an example, see Example: Finding the User to Whom a Lock Belongs.
If you call the XQuery built-in xdmp:node-uri function on a locks document, it returns the URI of the document that is locked. The following query returns a document listing the URIs of all documents in the database that have locks.
<root> { for $locks in xdmp:document-locks() return <document-URI>{xdmp:node-uri($locks)}</document-URI> } </root>
For example, if the only document in the database with a lock has a URI /document/myDocument.xml
, then the above query would return the following.
<root> <document-URI>/documents/myDocument.xml</document-URI> </root>
The following example uses the xdmp:lock-acquire function to set a two minute (120 second) lock on a document with the specified URI:
xdmp:lock-acquire("/documents/myDocument.xml", "exclusive", "0", "Raymond is editing this document", xs:unsignedLong(120))
You can view the resulting lock document with the xdmp:document-locks function as follows:
xdmp:document-locks("/documents/myDocument.xml") => <lock:lock xmlns:lock="http://marklogic.com/xdmp/lock"> <lock:lock-type>write</lock:lock-type> <lock:lock-scope>exclusive</lock:lock-scope> <lock:active-locks> <lock:active-lock> <lock:depth>0</lock:depth> <lock:owner>Raymond is editing this document</lock:owner> <lock:timeout>120</lock:timeout> <lock:lock-token> http://marklogic.com/xdmp/locks/4d0244560cc3726c </lock:lock-token> <lock:timestamp>1121722103</lock:timestamp> <sec:user-id xmlns:sec="http://marklogic.com/xdmp/security"> 8216129598321388485 </sec:user-id> </lock:active-lock> </lock:active-locks> </lock:lock>
The following example uses the xdmp:lock-release function to explicitly release a lock on a document:
xdmp:lock-release("/documents/myDocument.xml")
If you acquire a lock with no timeout period, be sure to release the lock when you are done with it. If you do not release the lock, no other users can update any documents or directories locked by the xdmp:lock-acquire action.
Because locks are documents, you can write a query that finds the user to whom a lock belongs. For example, the following query searches through the sec:user-id
elements of the lock documents and returns a set of URI names and user IDs of the user who owns each lock:
for $x in xdmp:document-locks()//sec:user-id return <lock> <URI>{xdmp:node-uri($x)}</URI> <user-id>{data($x)}</user-id> </lock>
A sample result is as follows (this result assumes there is only a single lock in the database):
<lock> <URI>/documents/myDocument.xml</URI> <user-id>15025067637711025979</user-id> </lock>