Allow to restrict the caches to auto-tune

Introduce the cache-name parameter to the auto-adjust-caches
command for reducing the scope of adjusting and converting caches
reducing the footprint on Gerrit and focusing the changes to
individual cache files.

Change-Id: I504e82808cefa73db09581c814eb4f9656d0d05e
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCaches.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCaches.java
index 4298a81..a5849a8 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCaches.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCaches.java
@@ -27,7 +27,10 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 import java.util.stream.Collectors;
 import org.apache.commons.io.FilenameUtils;
@@ -47,6 +50,7 @@
   private final AdministerCachePermission adminCachePermission;
 
   private boolean dryRun;
+  private Set<String> cacheNames = new HashSet<>();
 
   @Inject
   AutoAdjustCaches(
@@ -69,6 +73,10 @@
     this.dryRun = dryRun;
   }
 
+  public void addCacheNames(List<String> cacheNames) {
+    this.cacheNames.addAll(cacheNames);
+  }
+
   protected Config run(@Nullable ProgressMonitor optionalProgressMonitor)
       throws AuthException, PermissionBackendException, IOException {
     ProgressMonitor progressMonitor =
@@ -228,6 +236,7 @@
             pair ->
                 pair.getValue() instanceof ChronicleMapCacheImpl
                     && ((ChronicleMapCacheImpl) pair.getValue()).diskStats().size() > 0)
+        .filter(pair -> cacheNames.isEmpty() ? true : cacheNames.contains(pair.getKey()))
         .collect(
             Collectors.toMap(
                 ImmutablePair::getKey, p -> (ChronicleMapCacheImpl<Object, Object>) p.getValue()));
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesCommand.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesCommand.java
index 7aa240e..e57e130 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesCommand.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesCommand.java
@@ -19,8 +19,10 @@
 import com.google.gerrit.sshd.SshCommand;
 import com.google.inject.Inject;
 import java.io.IOException;
+import java.util.Arrays;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.kohsuke.args4j.Argument;
 import org.kohsuke.args4j.Option;
 
 public class AutoAdjustCachesCommand extends SshCommand {
@@ -38,6 +40,16 @@
     autoAdjustCachesEngine.setDryRun(dryRun);
   }
 
+  @Argument(
+      index = 0,
+      required = false,
+      multiValued = true,
+      metaVar = "CACHE_NAME",
+      usage = "name of cache to be adjusted")
+  public void setCacheName(String cacheName) {
+    autoAdjustCachesEngine.addCacheNames(Arrays.asList(cacheName));
+  }
+
   @Inject
   AutoAdjustCachesCommand(AutoAdjustCaches autoAdjustCachesEngine) {
     this.autoAdjustCachesEngine = autoAdjustCachesEngine;
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesServlet.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesServlet.java
index b217b0e..59d29ae 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesServlet.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesServlet.java
@@ -24,6 +24,7 @@
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Optional;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -56,6 +57,11 @@
             .or(() -> Optional.ofNullable(req.getParameter("d")))
             .isPresent());
 
+    String[] cacheNames = req.getParameterValues("CACHE_NAME");
+    if (cacheNames != null) {
+      autoAdjustCachesEngine.addCacheNames(Arrays.asList(cacheNames));
+    }
+
     try {
       Config outputChronicleMapConfig = autoAdjustCachesEngine.run(null);
 
diff --git a/src/main/resources/Documentation/tuning.md b/src/main/resources/Documentation/tuning.md
index feb98fc..c3979b2 100644
--- a/src/main/resources/Documentation/tuning.md
+++ b/src/main/resources/Documentation/tuning.md
@@ -148,7 +148,7 @@
 * You can now run an the tuning command:
 
 ```bash
-ssh -p 29418 admin@<gerrit-server> cache-chroniclemap auto-adjust-caches [--dry-run]
+ssh -p 29418 admin@<gerrit-server> cache-chroniclemap auto-adjust-caches [--dry-run] [cache-name]
 ```
 
 * You can also use the REST-API:
@@ -159,6 +159,10 @@
 
 * `--dry-run` or `-d` (SSH), `?dry-run` or `?d` (REST-API) optional parameter
 
+* `cache-name` (SSH), `?CACHE_NAME=cache-name` (REST-API) optional restriction of the caches
+  to analyze and auto-tune. The parameter can be repeated multiple times for analyzing
+  multiple caches. By default, analyze and adjust all persistent caches.
+
 Calculate the average key and value size, but do not migrate current cache
 data into new files
 
diff --git a/src/test/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesIT.java b/src/test/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesIT.java
index 8fad5ed..209b43e 100644
--- a/src/test/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesIT.java
+++ b/src/test/java/com/googlesource/gerrit/modules/cache/chroniclemap/AutoAdjustCachesIT.java
@@ -135,6 +135,19 @@
   }
 
   @Test
+  public void shouldCreateNewCacheFileForSingleDiffCache() throws Exception {
+    createChange();
+
+    adminSshSession.exec(SSH_CMD + " " + DIFF);
+
+    adminSshSession.assertSuccess();
+    Set<String> tunedCaches =
+        tunedFileNamesSet(n -> n.matches(".*" + AutoAdjustCaches.TUNED_INFIX + ".*"));
+
+    assertThat(tunedCaches.size()).isEqualTo(1);
+  }
+
+  @Test
   @GerritConfig(name = "cache.test_cache.avgKeySize", value = "207")
   @GerritConfig(name = "cache.test_cache.avgValueSize", value = "207")
   public void shouldNotRecreateTestCacheFileWhenAlreadyTuned() throws Exception {