Enable to run online noteDb migration using multiple threads

So far online migration only used a single thread for migration from
reviewDb to noteDb. Introduce a configuration parameter
notedb.onlineMigrationThreads to allow tuning the number of threads the
migration can use.

This helps to speedup online migration at the expense of imposing a
higher load on the Gerrit server running at the same time.

Change-Id: Icac0ec4907b82d1402330d01eb05e09fcca28682
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 03c4beb..cd15de7 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3716,6 +3716,13 @@
 +
 By default, 1.
 
+[[notedb.onlineMigrationThreads]] notedb.onlineMigrationThreads::
++
+The number of threads used to run the online migration from reviewDb to noteDb.
+This allows to speed up online migration from reviewDb to noteDb at the expense
+of imposing a higher load on the running server.
++
+By default, 1.
 
 [[oauth]]
 === Section oauth
diff --git a/java/com/google/gerrit/server/notedb/rebuild/OnlineNoteDbMigrator.java b/java/com/google/gerrit/server/notedb/rebuild/OnlineNoteDbMigrator.java
index b5a8236..46f5b22 100644
--- a/java/com/google/gerrit/server/notedb/rebuild/OnlineNoteDbMigrator.java
+++ b/java/com/google/gerrit/server/notedb/rebuild/OnlineNoteDbMigrator.java
@@ -14,6 +14,8 @@
 
 package com.google.gerrit.server.notedb.rebuild;
 
+import static com.google.gerrit.server.notedb.NotesMigration.SECTION_NOTE_DB;
+
 import com.google.common.base.Stopwatch;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.extensions.events.LifecycleListener;
@@ -35,6 +37,8 @@
 
   private static final String TRIAL = "OnlineNoteDbMigrator/trial";
 
+  private static final String ONLINE_MIGRATION_THREADS = "onlineMigrationThreads";
+
   public static class Module extends LifecycleModule {
     private final boolean trial;
 
@@ -54,6 +58,7 @@
   private final Provider<NoteDbMigrator.Builder> migratorBuilderProvider;
   private final boolean upgradeIndex;
   private final boolean trial;
+  private final int threads;
 
   @Inject
   OnlineNoteDbMigrator(
@@ -67,6 +72,7 @@
     this.migratorBuilderProvider = migratorBuilderProvider;
     this.upgradeIndex = VersionManager.getOnlineUpgrade(cfg);
     this.trial = trial || NoteDbMigrator.getTrialMode(cfg);
+    this.threads = cfg.getInt(SECTION_NOTE_DB, ONLINE_MIGRATION_THREADS, 1);
   }
 
   @Override
@@ -84,9 +90,14 @@
           "Online index schema upgrades will be deferred until NoteDb migration is complete");
     }
     Stopwatch sw = Stopwatch.createStarted();
-    // TODO(dborowitz): Tune threads, maybe expose a progress monitor somewhere.
+    // TODO(dborowitz): maybe expose a progress monitor somewhere.
     try (NoteDbMigrator migrator =
-        migratorBuilderProvider.get().setAutoMigrate(true).setTrialMode(trial).build()) {
+        migratorBuilderProvider
+            .get()
+            .setThreads(threads)
+            .setAutoMigrate(true)
+            .setTrialMode(trial)
+            .build()) {
       migrator.migrate();
     } catch (Exception e) {
       logger.atSevere().withCause(e).log("Error in online NoteDb migration");
diff --git a/javatests/com/google/gerrit/acceptance/pgm/StandaloneNoteDbMigrationIT.java b/javatests/com/google/gerrit/acceptance/pgm/StandaloneNoteDbMigrationIT.java
index 1bb23fb..fd00e54 100644
--- a/javatests/com/google/gerrit/acceptance/pgm/StandaloneNoteDbMigrationIT.java
+++ b/javatests/com/google/gerrit/acceptance/pgm/StandaloneNoteDbMigrationIT.java
@@ -222,6 +222,26 @@
   }
 
   @Test
+  public void onlineMigrationMultithreaded() throws Exception {
+    assertNoAutoMigrateConfig(gerritConfig);
+    assertNoAutoMigrateConfig(noteDbConfig);
+
+    testOnlineMigration(
+        u -> {
+          gerritConfig.setBoolean("noteDb", "changes", "autoMigrate", true);
+          gerritConfig.setInt("noteDb", null, "onlineMigrationThreads", 4);
+          gerritConfig.save();
+          return startServer(u.module());
+        });
+
+    // Auto-migration is turned off in notedb.config, which takes precedence, but is still on in
+    // gerrit.config. This means Puppet can continue overwriting gerrit.config without turning
+    // auto-migration back on.
+    assertAutoMigrateConfig(gerritConfig, true);
+    assertAutoMigrateConfig(noteDbConfig, false);
+  }
+
+  @Test
   public void onlineMigrationTrialModeViaFlag() throws Exception {
     assertNoAutoMigrateConfig(gerritConfig);
     assertNoTrialConfig(gerritConfig);