Auto-reload the indexTs file for auto-reindexing

The indexTs file under $GERRIT_SITE/data/high-availability/<index>
was not auto-reloaded making the auto-reindex functionality not
useful.

Use the JGit's FileSnapshot features to automatically detect changes
to the underlying indexTs file and use the new value for delta
reindexing.

Bug: Issue 15632
Change-Id: I3dcf7a6ade2286f684b289ed0994acdf86bd6362
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/IndexTs.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/IndexTs.java
index 8abdb59..f1783e7 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/IndexTs.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/IndexTs.java
@@ -38,6 +38,7 @@
 import java.time.format.DateTimeFormatter;
 import java.util.Optional;
 import java.util.concurrent.ScheduledExecutorService;
+import org.eclipse.jgit.internal.storage.file.FileSnapshot;
 
 @Singleton
 public class IndexTs
@@ -65,15 +66,17 @@
 
   class FlusherRunner implements Runnable {
     private final AbstractIndexRestApiServlet.IndexName index;
+    private final Path tsPath;
+    private FileSnapshot tsPathSnapshot;
 
     @Override
     public void run() {
+      reloadIndexTimeStampIfChanged();
       LocalDateTime latestTs = getIndexTimeStamp();
       Optional<LocalDateTime> currTs = getUpdateTs(index);
       if (!currTs.isPresent() || latestTs.isAfter(currTs.get())) {
-        Path indexTsFile = dataDir.resolve(index.name().toLowerCase());
         try {
-          Files.write(indexTsFile, latestTs.format(formatter).getBytes(StandardCharsets.UTF_8));
+          Files.write(tsPath, latestTs.format(formatter).getBytes(StandardCharsets.UTF_8));
         } catch (IOException e) {
           log.atSevere().withCause(e).log("Unable to update last timestamp for index %s", index);
         }
@@ -82,6 +85,8 @@
 
     FlusherRunner(AbstractIndexRestApiServlet.IndexName index) {
       this.index = index;
+      this.tsPath = getIndexTsPath(index);
+      this.tsPathSnapshot = FileSnapshot.save(tsPath.toFile());
     }
 
     private LocalDateTime getIndexTimeStamp() {
@@ -98,6 +103,31 @@
           throw new IllegalArgumentException("Unsupported index " + index);
       }
     }
+
+    private void reloadIndexTimeStampIfChanged() {
+      if (tsPathSnapshot.isModified(tsPath.toFile())) {
+        getUpdateTs(index).ifPresent(this::setIndexTimeStamp);
+      }
+    }
+
+    private void setIndexTimeStamp(LocalDateTime newTs) {
+      switch (index) {
+        case CHANGE:
+          changeTs = newTs;
+          break;
+        case GROUP:
+          groupTs = newTs;
+          break;
+        case ACCOUNT:
+          accountTs = newTs;
+          break;
+        case PROJECT:
+          projectTs = newTs;
+          break;
+      }
+
+      tsPathSnapshot = FileSnapshot.save(tsPath.toFile());
+    }
   }
 
   @Inject
@@ -157,7 +187,7 @@
 
   public Optional<LocalDateTime> getUpdateTs(AbstractIndexRestApiServlet.IndexName index) {
     try {
-      Path indexTsFile = dataDir.resolve(index.name().toLowerCase());
+      Path indexTsFile = getIndexTsPath(index);
       if (indexTsFile.toFile().exists()) {
         String tsString = Files.readAllLines(indexTsFile).get(0);
         return Optional.of(LocalDateTime.parse(tsString, formatter));
@@ -190,4 +220,8 @@
         throw new IllegalArgumentException("Unsupported index " + index);
     }
   }
+
+  private Path getIndexTsPath(AbstractIndexRestApiServlet.IndexName index) {
+    return dataDir.resolve(index.name().toLowerCase());
+  }
 }