6

I have a function that I wrote for generation of a sequential number. The function is as follows:

declare function generate-instrument-Id( $cnt as xs:int? )
as xs:int {
    let $count := if( $cnt and  $cnt > 0 ) then $cnt else 1
    let $url := '/private/instrumentId-Sequence.xml'
    (: this redirection is needed to write id in another 
       transaction context :)
    return xdmp:invoke-function( function() {
               let $id := fn:doc( $url )/instrument/@nextId
               let $_ := xdmp:node-replace( $id
                            , attribute nextId {  $id + $count } )
                return $id
            }
          )
};

The function works fine from a qconsole window using the following test code:

let res := util:generate-instrument-Id( 1 )
return fn:error( fn:QName("test", $res ) )

i.e. it executes in another transaction context and updates the document correctly. However, when I try to call the same function from a REST service, it returns the following error message:

XDMP-LOCKED: xdmp:node-replace(fn:doc("/private/instrumentId-Sequence.xml")/instrument/@nextId, attribute{fn:QName("","nextId")}{"1228"}) -- Document or Directory is locked

Please note that I cleaned up every other piece of code from the service interface to isolate the problem and still receive the same error message.

So here are my questions:

  • Under what conditions this error is issued?
  • I am sure there are no locks are held on this document (or directory it is put under) by any other process, so what might trigger such a false alarm?
  • Since it works from qconsole, I assume if I replicate what it does when executing programs I could solve this problem, as well. Any documentation on how qconsole executes programs?

Thanks a lot
K.

PS: I use MarkLogic 9 on a windows server

Kemal Erdogan
  • 1,060
  • 1
  • 9
  • 19
  • 1
    Is there any chance that the function gets invoked more than once? Also, you might want to pass in `different-transaction`. That is not the default for invoke and eval. – grtjn Sep 07 '17 at 17:53
  • @grtjn: I actually tested with some different isolation options; none of them seems to work. it also appears that different-transaction is the default option, as was proven by the correct execution of the function in the qconsole. And, no there is no other calls: to ensure that I removed every other call in the service code and left only the call to this function – Kemal Erdogan Sep 08 '17 at 07:18
  • By the way, have you considered using random id's instead? There are good reasons to prefer that over sequential id's. See here for details: https://github.com/grtjn/ml-unique#how-it-works – grtjn Sep 08 '17 at 12:36
  • yes, indeed I considered that, but this id is part of a publicly visible identifier thus cannot contain some random sequences, but thanks for the link and the suggestion – Kemal Erdogan Sep 08 '17 at 14:08

1 Answers1

2

After some pain, I discovered that the reason I received this error. It appears it was because there was indeed a lock placed on the directory "/" and that this lock is not a transaction lock.

As per documentation, it is a persistent lock that is acquired by the WebDAV server.I actually suspected that might be related to webDAV and I disabled the WebDAV services on the database, assuming that would release any locks those services would hold and I was able to write to doc using qconsole anyways.

It appears that the admin account has rights to ignore those persistent locks created by the webDAV server so that the function works from that context and that the disabling webDAV server would not release persistent locks it acquires.

So, all I had to do to solve the problem was to release the locks that were hanging around after I disabled the webDAV server.

Afterwards, I re-enabled the webdav server and the function continues to work OK, that would mean the wevDAV server acquires locks under only certain conditions which is not documented.

I thought, I should share this info to help others that might see the same problem

Kemal Erdogan
  • 1,060
  • 1
  • 9
  • 19