<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def advisory_lock(dax, key, lock_mode=LockMode.wait, xact=False):
 """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. """

  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)