Allow using ExternalIdsUpdate and AccountsUpdate without reindex

At Google we need to use these classes in a context where reindex is not
possible. Hence reindexing for the classes must be optional.

Change-Id: Id1017853982c6ca4e1cfa024f73d20dffad82bd6
Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountsUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountsUpdate.java
index 069380f..64c1189 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountsUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountsUpdate.java
@@ -17,6 +17,7 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -80,6 +81,37 @@
   }
 
   /**
+   * Factory to create an AccountsUpdate instance for updating accounts by the Gerrit server.
+   *
+   * <p>Using this class will not perform reindexing for the updated accounts and they will also not
+   * be evicted from the account cache.
+   *
+   * <p>The Gerrit server identity will be used as author and committer for all commits that update
+   * the accounts.
+   */
+  @Singleton
+  public static class ServerNoReindex {
+    private final GitRepositoryManager repoManager;
+    private final AllUsersName allUsersName;
+    private final Provider<PersonIdent> serverIdent;
+
+    @Inject
+    public ServerNoReindex(
+        GitRepositoryManager repoManager,
+        AllUsersName allUsersName,
+        @GerritPersonIdent Provider<PersonIdent> serverIdent) {
+      this.repoManager = repoManager;
+      this.allUsersName = allUsersName;
+      this.serverIdent = serverIdent;
+    }
+
+    public AccountsUpdate create() {
+      PersonIdent i = serverIdent.get();
+      return new AccountsUpdate(repoManager, null, allUsersName, i, i);
+    }
+  }
+
+  /**
    * Factory to create an AccountsUpdate instance for updating accounts by the current user.
    *
    * <p>The identity of the current user will be used as author for all commits that update the
@@ -119,19 +151,19 @@
   }
 
   private final GitRepositoryManager repoManager;
-  private final AccountCache accountCache;
+  @Nullable private final AccountCache accountCache;
   private final AllUsersName allUsersName;
   private final PersonIdent committerIdent;
   private final PersonIdent authorIdent;
 
   private AccountsUpdate(
       GitRepositoryManager repoManager,
-      AccountCache accountCache,
+      @Nullable AccountCache accountCache,
       AllUsersName allUsersName,
       PersonIdent committerIdent,
       PersonIdent authorIdent) {
     this.repoManager = checkNotNull(repoManager, "repoManager");
-    this.accountCache = checkNotNull(accountCache, "accountCache");
+    this.accountCache = accountCache;
     this.allUsersName = checkNotNull(allUsersName, "allUsersName");
     this.committerIdent = checkNotNull(committerIdent, "committerIdent");
     this.authorIdent = checkNotNull(authorIdent, "authorIdent");
@@ -146,7 +178,7 @@
   public void insert(ReviewDb db, Account account) throws OrmException, IOException {
     db.accounts().insert(ImmutableSet.of(account));
     createUserBranch(account);
-    accountCache.evict(account.getId());
+    evictAccount(account.getId());
   }
 
   /**
@@ -157,13 +189,13 @@
   public void upsert(ReviewDb db, Account account) throws OrmException, IOException {
     db.accounts().upsert(ImmutableSet.of(account));
     createUserBranchIfNeeded(account);
-    accountCache.evict(account.getId());
+    evictAccount(account.getId());
   }
 
   /** Updates the account. */
   public void update(ReviewDb db, Account account) throws OrmException, IOException {
     db.accounts().update(ImmutableSet.of(account));
-    accountCache.evict(account.getId());
+    evictAccount(account.getId());
   }
 
   /**
@@ -185,7 +217,7 @@
                   consumer.accept(a);
                   return a;
                 });
-    accountCache.evict(accountId);
+    evictAccount(accountId);
     return account;
   }
 
@@ -193,14 +225,14 @@
   public void delete(ReviewDb db, Account account) throws OrmException, IOException {
     db.accounts().delete(ImmutableSet.of(account));
     deleteUserBranch(account.getId());
-    accountCache.evict(account.getId());
+    evictAccount(account.getId());
   }
 
   /** Deletes the account. */
   public void deleteByKey(ReviewDb db, Account.Id accountId) throws OrmException, IOException {
     db.accounts().deleteKeys(ImmutableSet.of(accountId));
     deleteUserBranch(accountId);
-    accountCache.evict(accountId);
+    evictAccount(accountId);
   }
 
   private void createUserBranch(Account account) throws IOException {
@@ -294,4 +326,10 @@
       throw new IOException(String.format("Failed to delete ref %s: %s", refName, result.name()));
     }
   }
+
+  private void evictAccount(Account.Id accountId) throws IOException {
+    if (accountCache != null) {
+      accountCache.evict(accountId);
+    }
+  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java
index 9beae0e..2985504 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java
@@ -136,6 +136,47 @@
   }
 
   /**
+   * Factory to create an ExternalIdsUpdate instance for updating external IDs by the Gerrit server.
+   *
+   * <p>Using this class no reindex will be performed for the affected accounts and they will also
+   * not be evicted from the account cache.
+   *
+   * <p>The Gerrit server identity will be used as author and committer for all commits that update
+   * the external IDs.
+   */
+  @Singleton
+  public static class ServerNoReindex {
+    private final GitRepositoryManager repoManager;
+    private final AllUsersName allUsersName;
+    private final MetricMaker metricMaker;
+    private final ExternalIds externalIds;
+    private final ExternalIdCache externalIdCache;
+    private final Provider<PersonIdent> serverIdent;
+
+    @Inject
+    public ServerNoReindex(
+        GitRepositoryManager repoManager,
+        AllUsersName allUsersName,
+        MetricMaker metricMaker,
+        ExternalIds externalIds,
+        ExternalIdCache externalIdCache,
+        @GerritPersonIdent Provider<PersonIdent> serverIdent) {
+      this.repoManager = repoManager;
+      this.allUsersName = allUsersName;
+      this.metricMaker = metricMaker;
+      this.externalIds = externalIds;
+      this.externalIdCache = externalIdCache;
+      this.serverIdent = serverIdent;
+    }
+
+    public ExternalIdsUpdate create() {
+      PersonIdent i = serverIdent.get();
+      return new ExternalIdsUpdate(
+          repoManager, null, allUsersName, metricMaker, externalIds, externalIdCache, i, i);
+    }
+  }
+
+  /**
    * Factory to create an ExternalIdsUpdate instance for updating external IDs by the current user.
    *
    * <p>The identity of the current user will be used as author for all commits that update the
@@ -204,7 +245,7 @@
   private static final Retryer<RefsMetaExternalIdsUpdate> RETRYER = retryerBuilder().build();
 
   private final GitRepositoryManager repoManager;
-  private final AccountCache accountCache;
+  @Nullable private final AccountCache accountCache;
   private final AllUsersName allUsersName;
   private final ExternalIds externalIds;
   private final ExternalIdCache externalIdCache;
@@ -216,7 +257,7 @@
 
   private ExternalIdsUpdate(
       GitRepositoryManager repoManager,
-      AccountCache accountCache,
+      @Nullable AccountCache accountCache,
       AllUsersName allUsersName,
       MetricMaker metricMaker,
       ExternalIds externalIds,
@@ -239,7 +280,7 @@
   @VisibleForTesting
   public ExternalIdsUpdate(
       GitRepositoryManager repoManager,
-      AccountCache accountCache,
+      @Nullable AccountCache accountCache,
       AllUsersName allUsersName,
       MetricMaker metricMaker,
       ExternalIds externalIds,
@@ -375,7 +416,7 @@
               }
             });
     externalIdCache.onRemoveByKeys(u.oldRev(), u.newRev(), accountId, extIdKeys);
-    accountCache.evict(accountId);
+    evictAccount(accountId);
   }
 
   /**
@@ -434,7 +475,7 @@
               }
             });
     externalIdCache.onReplaceByKeys(u.oldRev(), u.newRev(), accountId, toDelete, toAdd);
-    accountCache.evict(accountId);
+    evictAccount(accountId);
   }
 
   /**
@@ -726,7 +767,17 @@
     return ins.insert(OBJ_TREE, new byte[] {});
   }
 
+  private void evictAccount(Account.Id accountId) throws IOException {
+    if (accountCache != null) {
+      accountCache.evict(accountId);
+    }
+  }
+
   private void evictAccounts(Collection<ExternalId> extIds) throws IOException {
+    if (accountCache == null) {
+      return;
+    }
+
     for (Account.Id id : extIds.stream().map(ExternalId::accountId).collect(toSet())) {
       accountCache.evict(id);
     }