Log acquiring and releasing sharedref locks
Before mutating refs entries in the sharedref database, a lock is
acquired to manage concurrency and guarantee exclusive access to that
ref. The lock is then released once the ref
has been created/updated/deleted from the sharedref database.
Add logging of lock acquisition/release to the sharedref_log, since
locks are also held in the sharedref database.
Feature: Issue 11254
Change-Id: Ie9f0d0d3422d5a6c8191703b472db4aaadfba974
diff --git a/BUILD b/BUILD
index d03d116..d6e7348 100644
--- a/BUILD
+++ b/BUILD
@@ -46,6 +46,7 @@
exports = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
":multi-site__plugin",
"@curator-client//jar",
+ "@curator-recipes//jar",
"@curator-framework//jar",
"@curator-test//jar",
"@mockito//jar",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/LockWrapper.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/LockWrapper.java
new file mode 100644
index 0000000..0e018d3
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/LockWrapper.java
@@ -0,0 +1,50 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite;
+
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+public class LockWrapper implements AutoCloseable {
+ public interface Factory {
+ LockWrapper create(
+ @Assisted("project") String project,
+ @Assisted("refName") String refName,
+ @Assisted("lock") AutoCloseable lock);
+ }
+
+ private final String project;
+ private final String refName;
+ private final AutoCloseable lock;
+ private final SharedRefLogger sharedRefLogger;
+
+ @Inject
+ public LockWrapper(
+ SharedRefLogger sharedRefLogger,
+ @Assisted("project") String project,
+ @Assisted("refName") String refName,
+ @Assisted("lock") AutoCloseable lock) {
+ this.lock = lock;
+ this.sharedRefLogger = sharedRefLogger;
+ this.project = project;
+ this.refName = refName;
+ }
+
+ @Override
+ public void close() throws Exception {
+ lock.close();
+ sharedRefLogger.logLockRelease(project, refName);
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
index 36ed2a7..5930576 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
@@ -103,6 +103,16 @@
sharedRefDBLog.info(gson.toJson(new SharedRefLogEntry.DeleteProject(project)));
}
+ @Override
+ public void logLockAcquisition(String project, String refName) {
+ sharedRefDBLog.info(gson.toJson(new SharedRefLogEntry.LockAcquire(project, refName)));
+ }
+
+ @Override
+ public void logLockRelease(String project, String refName) {
+ sharedRefDBLog.info(gson.toJson(new SharedRefLogEntry.LockRelease(project, refName)));
+ }
+
@VisibleForTesting
public void setLogger(Logger logger) {
this.sharedRefDBLog = logger;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
index f21f185..7d8ae22 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
@@ -50,7 +50,9 @@
@Override
public AutoCloseable lockRef(String project, String refName) throws SharedLockException {
- return sharedRefDb.lockRef(project, refName);
+ AutoCloseable locker = sharedRefDb.lockRef(project, refName);
+ sharedRefLogger.logLockAcquisition(project, refName);
+ return locker;
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogEntry.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogEntry.java
index 88d38bb..d9e762f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogEntry.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogEntry.java
@@ -22,7 +22,9 @@
public enum Type {
UPDATE_REF,
DELETE_REF,
- DELETE_PROJECT
+ DELETE_PROJECT,
+ LOCK_ACQUIRE,
+ LOCK_RELEASE
}
public String projectName;
@@ -73,4 +75,26 @@
this.oldId = oldId;
}
}
+
+ public static class LockAcquire extends SharedRefLogEntry {
+
+ public String refName;
+
+ LockAcquire(String projectName, String refName) {
+ this.type = Type.LOCK_ACQUIRE;
+ this.projectName = projectName;
+ this.refName = refName;
+ }
+ }
+
+ public static class LockRelease extends SharedRefLogEntry {
+
+ public String refName;
+
+ LockRelease(String projectName, String refName) {
+ this.type = Type.LOCK_RELEASE;
+ this.projectName = projectName;
+ this.refName = refName;
+ }
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogger.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogger.java
index 0311a53..51f9ff0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogger.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogger.java
@@ -22,4 +22,8 @@
void logRefUpdate(String project, Ref currRef, ObjectId newRefValue);
void logProjectDelete(String project);
+
+ void logLockAcquisition(String project, String refName);
+
+ void logLockRelease(String project, String refName);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
index 15c0a13..4e6bef5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
@@ -17,6 +17,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.multisite.LockWrapper;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
@@ -47,9 +48,10 @@
SharedRefDatabaseWrapper sharedRefDb,
ValidationMetrics validationMetrics,
SharedRefEnforcement refEnforcement,
+ LockWrapper.Factory lockWrapperFactory,
@Assisted String projectName,
@Assisted RefDatabase refDb) {
- super(sharedRefDb, validationMetrics, refEnforcement, projectName, refDb);
+ super(sharedRefDb, validationMetrics, refEnforcement, lockWrapperFactory, projectName, refDb);
}
public void executeBatchUpdateWithValidation(
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
index 5330bca..82d4ff0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
@@ -20,6 +20,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.multisite.LockWrapper;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.OutOfSyncException;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedDbSplitBrainException;
@@ -41,6 +42,7 @@
protected final ValidationMetrics validationMetrics;
protected final String projectName;
+ private final LockWrapper.Factory lockWrapperFactory;
protected final RefDatabase refDb;
protected final SharedRefEnforcement refEnforcement;
@@ -70,10 +72,12 @@
SharedRefDatabaseWrapper sharedRefDb,
ValidationMetrics validationMetrics,
SharedRefEnforcement refEnforcement,
+ LockWrapper.Factory lockWrapperFactory,
@Assisted String projectName,
@Assisted RefDatabase refDb) {
this.sharedRefDb = sharedRefDb;
this.validationMetrics = validationMetrics;
+ this.lockWrapperFactory = lockWrapperFactory;
this.refDb = refDb;
this.projectName = projectName;
this.refEnforcement = refEnforcement;
@@ -160,7 +164,9 @@
locks.addResourceIfNotExist(
String.format("%s-%s", projectName, refName),
- () -> sharedRefDb.lockRef(projectName, refName));
+ () ->
+ lockWrapperFactory.create(
+ projectName, refName, sharedRefDb.lockRef(projectName, refName)));
RefPair latestRefPair = getLatestLocalRef(refPair);
if (sharedRefDb.isUpToDate(projectName, latestRefPair.compareRef)) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
index 087c4ed..86943f4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
@@ -21,6 +21,7 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Scopes;
import com.googlesource.gerrit.plugins.multisite.Configuration;
+import com.googlesource.gerrit.plugins.multisite.LockWrapper;
import com.googlesource.gerrit.plugins.multisite.Log4jSharedRefLogger;
import com.googlesource.gerrit.plugins.multisite.SharedRefLogger;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.CustomSharedRefEnforcementByProject;
@@ -43,6 +44,7 @@
install(new ReplicationExtensionPointModule());
bind(SharedRefLogger.class).to(Log4jSharedRefLogger.class);
+ factory(LockWrapper.Factory.class);
factory(MultiSiteRepository.Factory.class);
factory(MultiSiteRefDatabase.Factory.class);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
index 29c0a0c..661a480 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
@@ -148,6 +148,7 @@
zkSharedRefDatabase,
new ValidationMetrics(new DisabledMetricMaker()),
sharedRefEnforcement,
+ new DummyLockWrapper(),
projectName,
diskRepo.getRefDatabase());
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DisabledSharedRefLogger.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DisabledSharedRefLogger.java
index 5fc66ad..37d5008 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DisabledSharedRefLogger.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DisabledSharedRefLogger.java
@@ -27,4 +27,10 @@
@Override
public void logProjectDelete(String project) {}
+
+ @Override
+ public void logLockAcquisition(String project, String refName) {}
+
+ @Override
+ public void logLockRelease(String project, String refName) {}
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DummyLockWrapper.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DummyLockWrapper.java
new file mode 100644
index 0000000..1ff0429
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DummyLockWrapper.java
@@ -0,0 +1,13 @@
+package com.googlesource.gerrit.plugins.multisite.validation;
+
+import com.googlesource.gerrit.plugins.multisite.LockWrapper;
+import org.junit.Ignore;
+
+@Ignore
+public class DummyLockWrapper implements LockWrapper.Factory {
+
+ @Override
+ public LockWrapper create(String project, String refName, AutoCloseable lock) {
+ return new LockWrapper(new DisabledSharedRefLogger(), project, refName, lock);
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java
index 8b305c7..f368d41 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java
@@ -120,6 +120,32 @@
assertThat(gotLogEntry.committer).isNull();
}
+ @Test
+ public void shouldLogLockAcquisition() {
+ String refName = "refs/foo/bar";
+ log4jSharedRefLogger.logLockAcquisition(project.get(), refName);
+
+ SharedRefLogEntry.LockAcquire gotLogEntry =
+ gson.fromJson(logWriter.toString(), SharedRefLogEntry.LockAcquire.class);
+
+ assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.LOCK_ACQUIRE);
+ assertThat(gotLogEntry.projectName).isEqualTo(project.get());
+ assertThat(gotLogEntry.refName).isEqualTo(refName);
+ }
+
+ @Test
+ public void shouldLogLockRelease() {
+ String refName = "refs/foo/bar";
+ log4jSharedRefLogger.logLockRelease(project.get(), refName);
+
+ SharedRefLogEntry.LockAcquire gotLogEntry =
+ gson.fromJson(logWriter.toString(), SharedRefLogEntry.LockAcquire.class);
+
+ assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.LOCK_RELEASE);
+ assertThat(gotLogEntry.projectName).isEqualTo(project.get());
+ assertThat(gotLogEntry.refName).isEqualTo(refName);
+ }
+
private Log4jSharedRefLogger newLog4jSharedRefLogger() throws IOException {
final Log4jSharedRefLogger log4jSharedRefLogger =
new Log4jSharedRefLogger(new SystemLog(new SitePaths(newPath()), baseConfig), repoManager);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
index fb7b58d..730e558 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
@@ -155,6 +155,7 @@
sharedRefDb,
validationMetrics,
new DefaultSharedRefEnforcement(),
+ new DummyLockWrapper(),
projectName,
refDb);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
index 74a45e1..a9d8e76 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
@@ -197,6 +197,7 @@
sharedRefDb,
validationMetrics,
new DefaultSharedRefEnforcement(),
+ new DummyLockWrapper(),
projectName,
refDb);
return RefUpdateValidator;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
index 4177b02..f0677b8 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
@@ -76,7 +76,12 @@
refUpdateValidator =
new RefUpdateValidator(
- sharedRefDb, validationMetrics, defaultRefEnforcement, A_TEST_PROJECT_NAME, localRefDb);
+ sharedRefDb,
+ validationMetrics,
+ defaultRefEnforcement,
+ new DummyLockWrapper(),
+ A_TEST_PROJECT_NAME,
+ localRefDb);
}
@Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
index 3f10908..317f130 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
@@ -23,6 +23,7 @@
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.BatchRefUpdateValidator;
import com.googlesource.gerrit.plugins.multisite.validation.DisabledSharedRefLogger;
+import com.googlesource.gerrit.plugins.multisite.validation.DummyLockWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.MultiSiteBatchRefUpdate;
import com.googlesource.gerrit.plugins.multisite.validation.ValidationMetrics;
import com.googlesource.gerrit.plugins.multisite.validation.ZkConnectionConfig;
@@ -183,6 +184,7 @@
zkSharedRefDatabase,
new ValidationMetrics(new DisabledMetricMaker()),
new DefaultSharedRefEnforcement(),
+ new DummyLockWrapper(),
projectName,
refDb);
}