code: def advisory_lock(dax, key, lock_mode=LockMode.wait, xact=False):
    
    if lock_mode == LockMode.wait:
      obtain_lock(dax, key, lock_mode, xact)
    else:
      got_lock = obtain_lock(dax, key, lock_mode, xact)
      if not got_lock:
        if lock_mode == LockMode.error:
          raise Exception("Unable to obtain advisory lock {}".format(key))
        else:
          # lock_mode is skip
          yield False
          return
  
    # At this point we have the lock
    try:
      yield True
    finally:
      if not xact:
        release_lock(dax, key, lock_mode)
docs: A context manager for obtaining a lock, executing code, and then releasing
    the lock.
  
    A boolean value is passed to the block indicating whether or not the lock was
    obtained.
  
    :dax: a DataAccess instance
    :key: either a big int or a 2-tuple of integers
    :lock_mode: a member of the LockMode enum. Determines how this function
                operates:
                  - wait: the wrapped code will not be executed until the lock
                          is obtained.
                  - skip: an attempt will be made to get the lock, and if
                          unsuccessful, False is passed to the code block
                  - error: an attempt will be made to get the lock, and if
                           unsuccessful, an exception will be raised.
    :xact: a boolean, if True, the lock will be obtained according to lock_mode,
           but will not be released after the code is executed, since it will be
           automatically released at the end of the transaction.