Open given urn and locks it.

    Opens an object and locks it for 'lease_time' seconds. OpenWithLock can
    only be used in 'with ...' statement. The lock is released when code
    execution leaves 'with ...' block.

    The urn is always opened in "rw" mode. Symlinks are not followed in
    OpenWithLock() due to possible race conditions.

    Args:
      urn: The urn to open.
      aff4_type: If this optional parameter is set, we raise an
        InstantiationError if the object exists and is not an instance of this
        type. This check is important when a different object can be stored in
        this location.
      token: The Security Token to use for opening this item.
      age: The age policy used to build this object. Should be one of
        NEWEST_TIME, ALL_TIMES or a time range given as a tuple (start, end) in
        microseconds since Jan 1st, 1970.
      blocking: When True, wait and repeatedly try to grab the lock.
      blocking_lock_timeout: Maximum wait time when sync is True.
      blocking_sleep_interval: Sleep time between lock grabbing attempts. Used
        when blocking is True.
      lease_time: Maximum time the object stays locked. Lock will be considered
        released when this time expires.

    Raises:
      ValueError: The URN passed in is None.

    Returns:
      Context manager to be used in 'with ...' statement.

def OpenWithLock(self,
                   urn,
                   aff4_type=None,
                   token=None,
                   age=NEWEST_TIME,
                   blocking=True,
                   blocking_lock_timeout=10,
                   blocking_sleep_interval=1,
                   lease_time=100):
    """Open given urn and locks it.

    Opens an object and locks it for 'lease_time' seconds. OpenWithLock can
    only be used in 'with ...' statement. The lock is released when code
    execution leaves 'with ...' block.

    The urn is always opened in "rw" mode. Symlinks are not followed in
    OpenWithLock() due to possible race conditions.

    Args:
      urn: The urn to open.
      aff4_type: If this optional parameter is set, we raise an
        InstantiationError if the object exists and is not an instance of this
        type. This check is important when a different object can be stored in
        this location.
      token: The Security Token to use for opening this item.
      age: The age policy used to build this object. Should be one of
        NEWEST_TIME, ALL_TIMES or a time range given as a tuple (start, end) in
        microseconds since Jan 1st, 1970.
      blocking: When True, wait and repeatedly try to grab the lock.
      blocking_lock_timeout: Maximum wait time when sync is True.
      blocking_sleep_interval: Sleep time between lock grabbing attempts. Used
        when blocking is True.
      lease_time: Maximum time the object stays locked. Lock will be considered
        released when this time expires.

    Raises:
      ValueError: The URN passed in is None.

    Returns:
      Context manager to be used in 'with ...' statement.
    """

    if not data_store.AFF4Enabled():
      raise NotImplementedError("AFF4 data store has been disabled.")

    transaction = self._AcquireLock(
        urn,
        blocking=blocking,
        blocking_lock_timeout=blocking_lock_timeout,
        blocking_sleep_interval=blocking_sleep_interval,
        lease_time=lease_time)

    # Since we now own the data store subject, we can simply read the aff4
    # object in the usual way.
    return self.Open(
        urn,
        aff4_type=aff4_type,
        mode="rw",
        token=token,
        age=age,
        follow_symlinks=False,
        transaction=transaction)