@classmethod
  def _TryAcquire(cls, client, resource_type, resource_id, callback,
                  resource_data=None, detect_abandonment=False, owner_id=None,
                  attempts=0, test_hook=None):
    def _OnUpdate(lock, status):
      """If lock was acquired and abandonment needs to be detected,
      then starts renewal timer.
      """
      if status != Lock.FAILED_TO_ACQUIRE_LOCK and detect_abandonment:
        lock._Renew(client)

      callback(lock, status)

    def _OnException(type, value, tb):
      """Starts over unless too many acquire attempts have been made."""
      logging.warning('race condition caused update of "%s:%s" lock to fail (will retry): %s' %
                      (resource_type, resource_id, value))

      # Retry the acquire unless too many attempts have already been made.
      if attempts >= Lock.MAX_UPDATE_ATTEMPTS:
        logging.error('too many failures attempting to update lock; aborting', exc_info=(type, value, tb))
        callback(None, Lock.FAILED_TO_ACQUIRE_LOCK)
      else:
        # TODO(Andy): We really should consider adding in a randomly-perturbed, exponential backoff
        # here to avoid senseless fights between concurrent servers.
        Lock._TryAcquire(client, resource_type, resource_id, callback,
                         resource_data=resource_data, detect_abandonment=detect_abandonment,
                         attempts=attempts + 1, test_hook=test_hook)

    def _DoUpdate(update_func):
      """Calls the test hook just before a row is updated in the database.
      Tests can simulate updates made by another agent at this critical
      juncture.
      """
      if test_hook is not None:
        test_hook(update_func)
      else:
        update_func()

    def _OnQuery(lock):
      """Creates a new lock, takes control of an abandoned lock, or reports
      failure to acquire the lock. The choice depends upon the current
      state of the lock in the database. Other agents may be trying to
      acquire the lock at the same time, so takes care to handle those race
      conditions.
      """
      if lock is None:
        # Create new lock.
        lock = Lock(lock_id, owner_id)
        if resource_data is not None:
          lock.resource_data = resource_data
        if detect_abandonment:
          lock.expiration = time.time() + Lock.ABANDONMENT_SECS

        with util.Barrier(partial(_OnUpdate, lock, Lock.ACQUIRED_LOCK), on_exception=_OnException) as b:
          _DoUpdate(partial(lock.Update, client, expected={'lock_id': False}, callback=b.Callback()))
      elif lock._IsOwnedBy(owner_id):
        assert not detect_abandonment, (resource_type, resource_data)
        # Acquirer knew owner id, so sync _unique_id up with it.
        lock._SyncUniqueIdToOwnerId()
        _OnUpdate(lock, Lock.ACQUIRED_LOCK)
      elif lock.IsAbandoned():
        logging.warning('lock was abandoned; trying to take control of it: %s' % lock)

        # Try to take control of lock.
        with util.Barrier(partial(_OnUpdate, lock, Lock.ACQUIRED_ABANDONED_LOCK), on_exception=_OnException) as b:
          _DoUpdate(partial(lock._TryTakeControl, client, detect_abandonment, b.Callback()))
      else:
        logging.warning('acquire of lock failed; already held by another agent: %s' % lock)

        # Report the failure to acquire in order to track contention on the lock and to notify the current
        # lock owner that another agent tried to acquire the lock.
        with util.Barrier(partial(_OnUpdate, None, Lock.FAILED_TO_ACQUIRE_LOCK), on_exception=_OnException) as b:
          _DoUpdate(partial(lock._TryReportAcquireFailure, client, b.Callback()))

    # Get current state of the lock from the database.
    lock_id = Lock.ConstructLockId(resource_type, resource_id)
    Lock.Query(client, lock_id, None, _OnQuery, must_exist=False)
**SUMMARY**
dataset/ETHPy150Open viewfinderco/viewfinder/backend/db/lock.py/Lock._TryAcquire--crossover with--dataset/ETHPy150Open sightmachine/SimpleCV/SimpleCV/LineScan.py/LineScan.convolve