Trigger GitReferenceUpdated event when account or change sequence is updated

This allows to replicate updates to the refs/sequences/* branches in
All-Users and All-Projects. Replicating these refs is not needed for
Gerrit slaves (since they do not create new accounts or changes) but
replicating these refs may be wanted if the replication target is a
Gerrit backup server.

Change-Id: Ib1d21a646d89b2e774dc9d50574eb990b8d79ece
Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
Edwin Kempin 2017-10-05 12:19:46 +02:00
parent 02e281d9d3
commit 54c04d380d
7 changed files with 55 additions and 7 deletions

View File

@ -252,7 +252,8 @@ public class AccountIT extends AbstractDaemonTest {
Account.Id accountId = create(2); // account creation + external ID creation
refUpdateCounter.assertRefUpdateFor(
RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)),
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS));
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS),
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS));
}
@Test
@ -264,6 +265,9 @@ public class AccountIT extends AbstractDaemonTest {
RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)),
2,
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS),
1,
RefUpdateCounter.projectRef(
allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS),
1));
}

View File

@ -17,6 +17,7 @@ package com.google.gerrit.pgm.init.api;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.RepoSequence;
import com.google.gwtorm.server.OrmException;
@ -40,6 +41,7 @@ public class SequencesOnInit {
RepoSequence accountSeq =
new RepoSequence(
repoManager,
GitReferenceUpdated.DISABLED,
new Project.NameKey(allUsersName.get()),
Sequences.NAME_ACCOUNTS,
accountSeed,

View File

@ -27,6 +27,7 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.RepoSequence;
@ -64,6 +65,7 @@ public class Sequences {
Provider<ReviewDb> db,
NotesMigration migration,
GitRepositoryManager repoManager,
GitReferenceUpdated gitRefUpdated,
AllProjectsName allProjects,
AllUsersName allUsers,
MetricMaker metrics) {
@ -74,6 +76,7 @@ public class Sequences {
accountSeq =
new RepoSequence(
repoManager,
gitRefUpdated,
allUsers,
NAME_ACCOUNTS,
() -> ReviewDb.FIRST_ACCOUNT_ID,
@ -84,7 +87,8 @@ public class Sequences {
RepoSequence.Seed changeSeed = () -> db.get().nextChangeId() + gap;
int changeBatchSize = cfg.getInt("noteDb", "changes", "sequenceBatchSize", 20);
changeSeq =
new RepoSequence(repoManager, allProjects, NAME_CHANGES, changeSeed, changeBatchSize);
new RepoSequence(
repoManager, gitRefUpdated, allProjects, NAME_CHANGES, changeSeed, changeBatchSize);
nextIdLatency =
metrics.newTimer(

View File

@ -36,6 +36,7 @@ import com.google.common.util.concurrent.Runnables;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gwtorm.server.OrmException;
import java.io.IOException;
@ -86,6 +87,7 @@ public class RepoSequence {
private static final Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build();
private final GitRepositoryManager repoManager;
private final GitReferenceUpdated gitRefUpdated;
private final Project.NameKey projectName;
private final String refName;
private final Seed seed;
@ -103,16 +105,26 @@ public class RepoSequence {
public RepoSequence(
GitRepositoryManager repoManager,
GitReferenceUpdated gitRefUpdated,
Project.NameKey projectName,
String name,
Seed seed,
int batchSize) {
this(repoManager, projectName, name, seed, batchSize, Runnables.doNothing(), RETRYER);
this(
repoManager,
gitRefUpdated,
projectName,
name,
seed,
batchSize,
Runnables.doNothing(),
RETRYER);
}
@VisibleForTesting
RepoSequence(
GitRepositoryManager repoManager,
GitReferenceUpdated gitRefUpdated,
Project.NameKey projectName,
String name,
Seed seed,
@ -120,6 +132,7 @@ public class RepoSequence {
Runnable afterReadRef,
Retryer<RefUpdate.Result> retryer) {
this.repoManager = checkNotNull(repoManager, "repoManager");
this.gitRefUpdated = checkNotNull(gitRefUpdated, "gitRefUpdated");
this.projectName = checkNotNull(projectName, "projectName");
checkArgument(
@ -213,11 +226,15 @@ public class RepoSequence {
}
private void checkResult(RefUpdate.Result result) throws OrmException {
if (result != RefUpdate.Result.NEW && result != RefUpdate.Result.FORCED) {
if (!refUpdated(result)) {
throw new OrmException("failed to update " + refName + ": " + result);
}
}
private boolean refUpdated(RefUpdate.Result result) {
return result == RefUpdate.Result.NEW || result == RefUpdate.Result.FORCED;
}
private class TryAcquire implements Callable<RefUpdate.Result> {
private final Repository repo;
private final RevWalk rw;
@ -275,7 +292,11 @@ public class RepoSequence {
}
ru.setNewObjectId(newId);
ru.setForceUpdate(true); // Required for non-commitish updates.
return ru.update(rw);
RefUpdate.Result result = ru.update(rw);
if (refUpdated(result)) {
gitRefUpdated.fire(projectName, ru, null);
}
return result;
}
public static ReceiveCommand storeNew(ObjectInserter ins, String name, int val)

View File

@ -51,6 +51,7 @@ import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.GerritServerConfigProvider;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LockFailureException;
import com.google.gerrit.server.git.WorkQueue;
@ -505,6 +506,7 @@ public class NoteDbMigrator implements AutoCloseable {
RepoSequence seq =
new RepoSequence(
repoManager,
GitReferenceUpdated.DISABLED,
allProjects,
Sequences.NAME_CHANGES,
// If sequenceGap is 0, this writes into the sequence ref the same ID that is returned

View File

@ -17,6 +17,7 @@ package com.google.gerrit.server.schema;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.RepoSequence;
import com.google.gwtorm.server.OrmException;
@ -42,7 +43,13 @@ public class Schema_155 extends SchemaVersion {
@SuppressWarnings("deprecation")
RepoSequence.Seed accountSeed = () -> db.nextAccountId();
RepoSequence accountSeq =
new RepoSequence(repoManager, allUsersName, Sequences.NAME_ACCOUNTS, accountSeed, 1);
new RepoSequence(
repoManager,
GitReferenceUpdated.DISABLED,
allUsersName,
Sequences.NAME_ACCOUNTS,
accountSeed,
1);
// consume one account ID to ensure that the account sequence is initialized in NoteDb
accountSeq.next();

View File

@ -25,6 +25,7 @@ import com.github.rholder.retry.StopStrategies;
import com.google.common.util.concurrent.Runnables;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
import com.google.gwtorm.server.OrmException;
import java.io.IOException;
@ -264,7 +265,14 @@ public class RepoSequenceTest {
Runnable afterReadRef,
Retryer<RefUpdate.Result> retryer) {
return new RepoSequence(
repoManager, project, name, () -> start, batchSize, afterReadRef, retryer);
repoManager,
GitReferenceUpdated.DISABLED,
project,
name,
() -> start,
batchSize,
afterReadRef,
retryer);
}
private ObjectId writeBlob(String sequenceName, String value) {