private void abortTransactionsAtNode()

in src/main/java/com/google/firebase/database/core/Repo.java [1138:1207]


  private void abortTransactionsAtNode(Tree<List<TransactionData>> node, int reason) {
    List<TransactionData> queue = node.getValue();
    List<Event> events = new ArrayList<>();

    if (queue != null) {
      List<Runnable> callbacks = new ArrayList<>();
      final DatabaseError abortError;
      if (reason == DatabaseError.OVERRIDDEN_BY_SET) {
        abortError = DatabaseError.fromStatus(TRANSACTION_OVERRIDE_BY_SET);
      } else {
        hardAssert(
            reason == DatabaseError.WRITE_CANCELED, "Unknown transaction abort reason: " + reason);
        abortError = DatabaseError.fromCode(DatabaseError.WRITE_CANCELED);
      }

      int lastSent = -1;
      for (int i = 0; i < queue.size(); ++i) {
        final TransactionData transaction = queue.get(i);
        if (transaction.status == TransactionStatus.SENT_NEEDS_ABORT) {
          // No-op. Already marked
        } else if (transaction.status == TransactionStatus.SENT) {
          assert lastSent == i - 1; // All SENT items should be at beginning of queue.
          lastSent = i;
          // Mark transaction for abort when it comes back.
          transaction.status = TransactionStatus.SENT_NEEDS_ABORT;
          transaction.abortReason = abortError;
        } else {
          assert transaction.status
          == TransactionStatus.RUN; // Unexpected transaction status in abort
          // We can abort this immediately.
          removeEventCallback(
              new ValueEventRegistration(
                  Repo.this,
                  transaction.outstandingListener,
                  QuerySpec.defaultQueryAtPath(transaction.path)));
          if (reason == DatabaseError.OVERRIDDEN_BY_SET) {
            events.addAll(
                serverSyncTree.ackUserWrite(
                    transaction.currentWriteId, /*revert=*/ true, /*persist=*/ false, serverClock));
          } else {
            hardAssert(
                reason == DatabaseError.WRITE_CANCELED,
                "Unknown transaction abort reason: " + reason);
            // If it was cancelled, it was already removed from the sync tree
          }
          callbacks.add(
              new Runnable() {
                @Override
                public void run() {
                  runTransactionOnComplete(transaction.handler, abortError, false, null);
                }
              });
        }
      }

      if (lastSent == -1) {
        // We're not waiting for any sent transactions. We can clear the queue
        node.setValue(null);
      } else {
        // Remove the transactions we aborted
        node.setValue(queue.subList(0, lastSent + 1));
      }

      // Now fire the callbacks.
      this.postEvents(events);
      for (Runnable r : callbacks) {
        postEvent(r);
      }
    }
  }