Merge branch 'stable-2.13'

* stable-2.13:
  RestForwarder: factor out common response handling logic
  Replace wait/notify with CyclicBarrier

Change-Id: I12d527f8d268fbf5dca1a56afda179adb5aaf33f
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java
index 3afe689..4574026 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java
@@ -45,33 +45,23 @@
   }
 
   @Override
-  public boolean indexChange(int changeId) {
-    try {
-      HttpResult result = httpSession.post(buildIndexEndpoint(changeId));
-      if (result.isSuccessful()) {
-        return true;
+  public boolean indexChange(final int changeId) {
+    return new Request("index change " + changeId) {
+      @Override
+      HttpResult send() throws IOException {
+        return httpSession.post(buildIndexEndpoint(changeId));
       }
-      log.error("Unable to index change {}. Cause: {}", changeId,
-          result.getMessage());
-    } catch (IOException e) {
-      log.error("Error trying to index change " + changeId, e);
-    }
-    return false;
+    }.execute();
   }
 
   @Override
-  public boolean deleteChangeFromIndex(int changeId) {
-    try {
-      HttpResult result = httpSession.delete(buildIndexEndpoint(changeId));
-      if (result.isSuccessful()) {
-        return true;
+  public boolean deleteChangeFromIndex(final int changeId) {
+    return new Request("delete change " + changeId + " from index") {
+      @Override
+      HttpResult send() throws IOException {
+        return httpSession.delete(buildIndexEndpoint(changeId));
       }
-      log.error("Unable to delete from index change {}. Cause: {}", changeId,
-          result.getMessage());
-    } catch (IOException e) {
-      log.error("Error trying to delete from index change " + changeId, e);
-    }
-    return false;
+    }.execute();
   }
 
   private String buildIndexEndpoint(int changeId) {
@@ -79,35 +69,52 @@
   }
 
   @Override
-  public boolean send(Event event) {
-    String serializedEvent = new GsonBuilder()
-        .registerTypeAdapter(Supplier.class, new SupplierSerializer()).create()
-        .toJson(event);
-    try {
-      HttpResult result = httpSession.post(
+  public boolean send(final Event event) {
+    return new Request("send event " + event.type) {
+      @Override
+      HttpResult send() throws IOException {
+        String serializedEvent = new GsonBuilder()
+            .registerTypeAdapter(Supplier.class, new SupplierSerializer()).create()
+            .toJson(event);
+      return httpSession.post(
           Joiner.on("/").join(pluginRelativePath, "event"), serializedEvent);
-      if (result.isSuccessful()) {
-        return true;
       }
-      log.error(
-          "Unable to send event '" + event.type + "' " + result.getMessage());
-    } catch (IOException e) {
-      log.error("Error trying to send event " + event.type, e);
-    }
-    return false;
+    }.execute();
   }
 
   @Override
-  public boolean evict(String cacheName, Object key) {
-    try {
-      String json = GsonParser.toJson(cacheName, key);
-      return httpSession
-          .post(Joiner.on("/").join(pluginRelativePath, "cache", cacheName),
-              json)
-          .isSuccessful();
-    } catch (IOException e) {
-      log.error("Error trying to evict for cache " + cacheName, e);
+  public boolean evict(final String cacheName, final Object key) {
+    return new Request("evict for cache " + cacheName) {
+      @Override
+      HttpResult send() throws IOException {
+        String json = GsonParser.toJson(cacheName, key);
+        return httpSession
+            .post(Joiner.on("/").join(pluginRelativePath, "cache", cacheName),
+                json);
+      }
+    }.execute();
+  }
+
+  private abstract class Request {
+    private String name;
+
+    Request(String name) {
+      this.name = name;
+    }
+
+    boolean execute() {
+      try {
+        HttpResult result = send();
+        if (result.isSuccessful()) {
+          return true;
+        }
+        log.error("Unable to {}: {}", name, result.getMessage());
+      } catch (IOException e) {
+        log.error("Error trying to {}", name, e);
+      }
       return false;
     }
+
+    abstract HttpResult send() throws IOException;
   }
 }
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java
index 6eef10c..caaf2d8 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java
@@ -22,6 +22,7 @@
 import static com.github.tomakehurst.wiremock.client.WireMock.verify;
 import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
 
+import com.google.common.base.Throwables;
 import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
 import com.google.gerrit.acceptance.NoHttpd;
@@ -37,6 +38,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.TimeUnit;
 
 @NoHttpd
@@ -59,12 +62,15 @@
   public void flushAndSendPost() throws Exception {
     final String flushRequest =
         "/plugins/high-availability/cache/" + Constants.PROJECT_LIST;
+    final CyclicBarrier checkPoint = new CyclicBarrier(2);
     wireMockRule.addMockServiceRequestListener(new RequestListener() {
       @Override
       public void requestReceived(Request request, Response response) {
         if (request.getAbsoluteUrl().contains(flushRequest)) {
-          synchronized (flushRequest) {
-            flushRequest.notify();
+          try {
+            checkPoint.await();
+          } catch (InterruptedException | BrokenBarrierException e) {
+            Throwables.propagateIfPossible(e);
           }
         }
       }
@@ -74,9 +80,7 @@
 
     adminSshSession
         .exec("gerrit flush-caches --cache " + Constants.PROJECT_LIST);
-    synchronized (flushRequest) {
-      flushRequest.wait(TimeUnit.SECONDS.toMillis(5));
-    }
+    checkPoint.await(5, TimeUnit.SECONDS);
     verify(postRequestedFor(urlEqualTo(flushRequest)));
   }
 }