def RetryWrapper(self, subject, callback, retrywrap_timeout=1, token=None,
                   retrywrap_max_timeout=10, **kw):
    """Retry a Transaction until it succeeds.

    Args:
      subject: The subject which the transaction applies to.
      callback: A callback which will receive the transaction
         object. The callback will be called repeatedly until success.
      retrywrap_timeout: How long to wait before retrying the transaction.
      token: An ACL token.
      retrywrap_max_timeout: The maximum time to wait for a retry until we
         raise.
      **kw: Args passed to the callback.

    Returns:
      The result from the callback.

    Raises:
      TransactionError: If the maximum retry count has been reached.
    """

    def Retry():
      """Retry transaction."""
      transaction = self.Transaction(subject, token=token)
      try:
        result = callback(transaction, **kw)
      finally:
        # Make sure the transaction is committed.
        transaction.Commit()

      return result

    timeout = 0
    while timeout < retrywrap_max_timeout:
      try:
        result = Retry()
        if timeout > 1:
          logging.debug("Transaction took %s tries.", timeout)
        return result
      except TransactionError:
        stats.STATS.IncrementCounter("datastore_retries")
        time.sleep(retrywrap_timeout)
        timeout += retrywrap_timeout

    raise TransactionError("Retry number exceeded.")
dataset/ETHPy150Open google/grr/grr/lib/data_store.py/DataStore.RetryWrapper/original