Define a floor for NoteDb sequence generation
Make sure that new entities created with NoteDb sequences are never below the floor value defined in ReviewDb when performing a NoteDb migration. Prevents any possible conflicts with existing change sequences on ReviewDb once NoteDb is set as main active review store. Bug: Issue 8861 Change-Id: Ica4529771fae6487b01708fb22193cf16ce73f82
This commit is contained in:
@@ -335,7 +335,7 @@ public class OnlineNoteDbMigrationIT extends AbstractDaemonTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enableSequencesNoGap() throws Exception {
|
public void enableSequencesNoGap() throws Exception {
|
||||||
testEnableSequences(0, 2, "12");
|
testEnableSequences(0, 3, "13");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ public class RepoSequence {
|
|||||||
private final Project.NameKey projectName;
|
private final Project.NameKey projectName;
|
||||||
private final String refName;
|
private final String refName;
|
||||||
private final Seed seed;
|
private final Seed seed;
|
||||||
|
private final int floor;
|
||||||
private final int batchSize;
|
private final int batchSize;
|
||||||
private final Runnable afterReadRef;
|
private final Runnable afterReadRef;
|
||||||
private final Retryer<RefUpdate.Result> retryer;
|
private final Retryer<RefUpdate.Result> retryer;
|
||||||
@@ -118,7 +119,28 @@ public class RepoSequence {
|
|||||||
seed,
|
seed,
|
||||||
batchSize,
|
batchSize,
|
||||||
Runnables.doNothing(),
|
Runnables.doNothing(),
|
||||||
RETRYER);
|
RETRYER,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepoSequence(
|
||||||
|
GitRepositoryManager repoManager,
|
||||||
|
GitReferenceUpdated gitRefUpdated,
|
||||||
|
Project.NameKey projectName,
|
||||||
|
String name,
|
||||||
|
Seed seed,
|
||||||
|
int batchSize,
|
||||||
|
int floor) {
|
||||||
|
this(
|
||||||
|
repoManager,
|
||||||
|
gitRefUpdated,
|
||||||
|
projectName,
|
||||||
|
name,
|
||||||
|
seed,
|
||||||
|
batchSize,
|
||||||
|
Runnables.doNothing(),
|
||||||
|
RETRYER,
|
||||||
|
floor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -131,6 +153,19 @@ public class RepoSequence {
|
|||||||
int batchSize,
|
int batchSize,
|
||||||
Runnable afterReadRef,
|
Runnable afterReadRef,
|
||||||
Retryer<RefUpdate.Result> retryer) {
|
Retryer<RefUpdate.Result> retryer) {
|
||||||
|
this(repoManager, gitRefUpdated, projectName, name, seed, batchSize, afterReadRef, retryer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepoSequence(
|
||||||
|
GitRepositoryManager repoManager,
|
||||||
|
GitReferenceUpdated gitRefUpdated,
|
||||||
|
Project.NameKey projectName,
|
||||||
|
String name,
|
||||||
|
Seed seed,
|
||||||
|
int batchSize,
|
||||||
|
Runnable afterReadRef,
|
||||||
|
Retryer<RefUpdate.Result> retryer,
|
||||||
|
int floor) {
|
||||||
this.repoManager = checkNotNull(repoManager, "repoManager");
|
this.repoManager = checkNotNull(repoManager, "repoManager");
|
||||||
this.gitRefUpdated = checkNotNull(gitRefUpdated, "gitRefUpdated");
|
this.gitRefUpdated = checkNotNull(gitRefUpdated, "gitRefUpdated");
|
||||||
this.projectName = checkNotNull(projectName, "projectName");
|
this.projectName = checkNotNull(projectName, "projectName");
|
||||||
@@ -144,6 +179,7 @@ public class RepoSequence {
|
|||||||
this.refName = RefNames.REFS_SEQUENCES + name;
|
this.refName = RefNames.REFS_SEQUENCES + name;
|
||||||
|
|
||||||
this.seed = checkNotNull(seed, "seed");
|
this.seed = checkNotNull(seed, "seed");
|
||||||
|
this.floor = floor;
|
||||||
|
|
||||||
checkArgument(batchSize > 0, "expected batchSize > 0, got: %s", batchSize);
|
checkArgument(batchSize > 0, "expected batchSize > 0, got: %s", batchSize);
|
||||||
this.batchSize = batchSize;
|
this.batchSize = batchSize;
|
||||||
@@ -251,15 +287,17 @@ public class RepoSequence {
|
|||||||
@Override
|
@Override
|
||||||
public RefUpdate.Result call() throws Exception {
|
public RefUpdate.Result call() throws Exception {
|
||||||
Ref ref = repo.exactRef(refName);
|
Ref ref = repo.exactRef(refName);
|
||||||
|
int nextCandidate;
|
||||||
afterReadRef.run();
|
afterReadRef.run();
|
||||||
ObjectId oldId;
|
ObjectId oldId;
|
||||||
if (ref == null) {
|
if (ref == null) {
|
||||||
oldId = ObjectId.zeroId();
|
oldId = ObjectId.zeroId();
|
||||||
next = seed.get();
|
nextCandidate = seed.get();
|
||||||
} else {
|
} else {
|
||||||
oldId = ref.getObjectId();
|
oldId = ref.getObjectId();
|
||||||
next = parse(oldId);
|
nextCandidate = parse(oldId);
|
||||||
}
|
}
|
||||||
|
next = Math.max(floor, nextCandidate);
|
||||||
return store(repo, rw, oldId, next + count);
|
return store(repo, rw, oldId, next + count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -560,6 +560,8 @@ public class NoteDbMigrator implements AutoCloseable {
|
|||||||
throws OrmException, IOException {
|
throws OrmException, IOException {
|
||||||
try (ReviewDb db = schemaFactory.open()) {
|
try (ReviewDb db = schemaFactory.open()) {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
final int nextChangeId = db.nextChangeId();
|
||||||
|
|
||||||
RepoSequence seq =
|
RepoSequence seq =
|
||||||
new RepoSequence(
|
new RepoSequence(
|
||||||
repoManager,
|
repoManager,
|
||||||
@@ -569,8 +571,9 @@ public class NoteDbMigrator implements AutoCloseable {
|
|||||||
// If sequenceGap is 0, this writes into the sequence ref the same ID that is returned
|
// If sequenceGap is 0, this writes into the sequence ref the same ID that is returned
|
||||||
// by the call to seq.next() below. If we actually used this as a change ID, that
|
// by the call to seq.next() below. If we actually used this as a change ID, that
|
||||||
// would be a problem, but we just discard it, so this is safe.
|
// would be a problem, but we just discard it, so this is safe.
|
||||||
() -> db.nextChangeId() + sequenceGap - 1,
|
() -> nextChangeId + sequenceGap - 1,
|
||||||
1);
|
1,
|
||||||
|
nextChangeId);
|
||||||
seq.next();
|
seq.next();
|
||||||
}
|
}
|
||||||
return saveState(prev, READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY);
|
return saveState(prev, READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY);
|
||||||
|
|||||||
Reference in New Issue
Block a user