Merge changes from topic 'sequence'
* changes: Read change ID sequence from notedb Notedb: Add a git repo based sequence implementation
This commit is contained in:
@@ -30,6 +30,7 @@ import com.google.gerrit.reviewdb.client.Project;
|
|||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.Sequences;
|
||||||
import com.google.gerrit.server.account.GroupBackend;
|
import com.google.gerrit.server.account.GroupBackend;
|
||||||
import com.google.gerrit.server.change.ChangeInserter;
|
import com.google.gerrit.server.change.ChangeInserter;
|
||||||
import com.google.gerrit.server.change.ChangeResource;
|
import com.google.gerrit.server.change.ChangeResource;
|
||||||
@@ -69,6 +70,7 @@ public class ReviewProjectAccess extends ProjectAccessHandler<Change.Id> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final ReviewDb db;
|
private final ReviewDb db;
|
||||||
|
private final Sequences seq;
|
||||||
private final IdentifiedUser user;
|
private final IdentifiedUser user;
|
||||||
private final Provider<PostReviewers> reviewersProvider;
|
private final Provider<PostReviewers> reviewersProvider;
|
||||||
private final ProjectCache projectCache;
|
private final ProjectCache projectCache;
|
||||||
@@ -88,6 +90,7 @@ public class ReviewProjectAccess extends ProjectAccessHandler<Change.Id> {
|
|||||||
ChangeInserter.Factory changeInserterFactory,
|
ChangeInserter.Factory changeInserterFactory,
|
||||||
BatchUpdate.Factory updateFactory,
|
BatchUpdate.Factory updateFactory,
|
||||||
Provider<SetParent> setParent,
|
Provider<SetParent> setParent,
|
||||||
|
Sequences seq,
|
||||||
|
|
||||||
@Assisted("projectName") Project.NameKey projectName,
|
@Assisted("projectName") Project.NameKey projectName,
|
||||||
@Nullable @Assisted ObjectId base,
|
@Nullable @Assisted ObjectId base,
|
||||||
@@ -98,6 +101,7 @@ public class ReviewProjectAccess extends ProjectAccessHandler<Change.Id> {
|
|||||||
allProjects, setParent, projectName, base, sectionList,
|
allProjects, setParent, projectName, base, sectionList,
|
||||||
parentProjectName, message, false);
|
parentProjectName, message, false);
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
this.seq = seq;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.reviewersProvider = reviewersProvider;
|
this.reviewersProvider = reviewersProvider;
|
||||||
this.projectCache = projectCache;
|
this.projectCache = projectCache;
|
||||||
@@ -111,7 +115,7 @@ public class ReviewProjectAccess extends ProjectAccessHandler<Change.Id> {
|
|||||||
ProjectConfig config, MetaDataUpdate md, boolean parentProjectUpdate)
|
ProjectConfig config, MetaDataUpdate md, boolean parentProjectUpdate)
|
||||||
throws IOException, OrmException {
|
throws IOException, OrmException {
|
||||||
md.setInsertChangeId(true);
|
md.setInsertChangeId(true);
|
||||||
Change.Id changeId = new Change.Id(db.nextChangeId());
|
Change.Id changeId = new Change.Id(seq.nextChangeId());
|
||||||
RevCommit commit =
|
RevCommit commit =
|
||||||
config.commitToNewRef(md, new PatchSet.Id(changeId,
|
config.commitToNewRef(md, new PatchSet.Id(changeId,
|
||||||
Change.INITIAL_PATCH_SET_ID).toRefName());
|
Change.INITIAL_PATCH_SET_ID).toRefName());
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ public class RefNames {
|
|||||||
/** A change starred by a user */
|
/** A change starred by a user */
|
||||||
public static final String REFS_STARRED_CHANGES = "refs/starred-changes/";
|
public static final String REFS_STARRED_CHANGES = "refs/starred-changes/";
|
||||||
|
|
||||||
|
/** Sequence counters in notedb. */
|
||||||
|
public static final String REFS_SEQUENCES = "refs/sequences/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefix applied to merge commit base nodes.
|
* Prefix applied to merge commit base nodes.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -113,8 +113,15 @@ public interface ReviewDb extends Schema {
|
|||||||
@Sequence
|
@Sequence
|
||||||
int nextAccountGroupId() throws OrmException;
|
int nextAccountGroupId() throws OrmException;
|
||||||
|
|
||||||
/** Next unique id for a {@link Change}. */
|
int FIRST_CHANGE_ID = 1;
|
||||||
@Sequence
|
|
||||||
|
/**
|
||||||
|
* Next unique id for a {@link Change}.
|
||||||
|
*
|
||||||
|
* @deprecated use {@link com.google.gerrit.server.Sequences#nextChangeId()}.
|
||||||
|
*/
|
||||||
|
@Sequence(startWith = FIRST_CHANGE_ID)
|
||||||
|
@Deprecated
|
||||||
int nextChangeId() throws OrmException;
|
int nextChangeId() throws OrmException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ java_library(
|
|||||||
'//lib:grappa',
|
'//lib:grappa',
|
||||||
'//lib:gson',
|
'//lib:gson',
|
||||||
'//lib:guava',
|
'//lib:guava',
|
||||||
|
'//lib:guava-retrying',
|
||||||
'//lib:gwtjsonrpc',
|
'//lib:gwtjsonrpc',
|
||||||
'//lib:gwtorm',
|
'//lib:gwtorm',
|
||||||
'//lib:jsch',
|
'//lib:jsch',
|
||||||
@@ -195,6 +196,7 @@ java_test(
|
|||||||
'//lib:args4j',
|
'//lib:args4j',
|
||||||
'//lib:grappa',
|
'//lib:grappa',
|
||||||
'//lib:guava',
|
'//lib:guava',
|
||||||
|
'//lib:guava-retrying',
|
||||||
'//lib/dropwizard:dropwizard-core',
|
'//lib/dropwizard:dropwizard-core',
|
||||||
'//lib/guice:guice-assistedinject',
|
'//lib/guice:guice-assistedinject',
|
||||||
'//lib/prolog:runtime',
|
'//lib/prolog:runtime',
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ public class ChangeUtil {
|
|||||||
|
|
||||||
private final Provider<CurrentUser> user;
|
private final Provider<CurrentUser> user;
|
||||||
private final Provider<ReviewDb> db;
|
private final Provider<ReviewDb> db;
|
||||||
|
private final Sequences seq;
|
||||||
private final Provider<InternalChangeQuery> queryProvider;
|
private final Provider<InternalChangeQuery> queryProvider;
|
||||||
private final ChangeControl.GenericFactory changeControlFactory;
|
private final ChangeControl.GenericFactory changeControlFactory;
|
||||||
private final RevertedSender.Factory revertedSenderFactory;
|
private final RevertedSender.Factory revertedSenderFactory;
|
||||||
@@ -186,6 +187,7 @@ public class ChangeUtil {
|
|||||||
@Inject
|
@Inject
|
||||||
ChangeUtil(Provider<CurrentUser> user,
|
ChangeUtil(Provider<CurrentUser> user,
|
||||||
Provider<ReviewDb> db,
|
Provider<ReviewDb> db,
|
||||||
|
Sequences seq,
|
||||||
Provider<InternalChangeQuery> queryProvider,
|
Provider<InternalChangeQuery> queryProvider,
|
||||||
ChangeControl.GenericFactory changeControlFactory,
|
ChangeControl.GenericFactory changeControlFactory,
|
||||||
RevertedSender.Factory revertedSenderFactory,
|
RevertedSender.Factory revertedSenderFactory,
|
||||||
@@ -196,6 +198,7 @@ public class ChangeUtil {
|
|||||||
ChangeUpdate.Factory changeUpdateFactory) {
|
ChangeUpdate.Factory changeUpdateFactory) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
this.seq = seq;
|
||||||
this.queryProvider = queryProvider;
|
this.queryProvider = queryProvider;
|
||||||
this.changeControlFactory = changeControlFactory;
|
this.changeControlFactory = changeControlFactory;
|
||||||
this.revertedSenderFactory = revertedSenderFactory;
|
this.revertedSenderFactory = revertedSenderFactory;
|
||||||
@@ -262,7 +265,7 @@ public class ChangeUtil {
|
|||||||
RefControl refControl = ctl.getRefControl();
|
RefControl refControl = ctl.getRefControl();
|
||||||
Change change = new Change(
|
Change change = new Change(
|
||||||
new Change.Key("I" + computedChangeId.name()),
|
new Change.Key("I" + computedChangeId.name()),
|
||||||
new Change.Id(db.get().nextChangeId()),
|
new Change.Id(seq.nextChangeId()),
|
||||||
user.get().getAccountId(),
|
user.get().getAccountId(),
|
||||||
changeToRevert.getDest(),
|
changeToRevert.getDest(),
|
||||||
TimeUtil.nowTs());
|
TimeUtil.nowTs());
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (C) 2016 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.google.gerrit.server;
|
||||||
|
|
||||||
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
import com.google.gerrit.server.notedb.NotesMigration;
|
||||||
|
import com.google.gerrit.server.notedb.RepoSequence;
|
||||||
|
import com.google.gwtorm.server.OrmException;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class Sequences {
|
||||||
|
private final Provider<ReviewDb> db;
|
||||||
|
private final NotesMigration migration;
|
||||||
|
private final RepoSequence changeSeq;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Sequences(Provider<ReviewDb> db,
|
||||||
|
NotesMigration migration,
|
||||||
|
GitRepositoryManager repoManager,
|
||||||
|
AllProjectsName allProjects) {
|
||||||
|
this.db = db;
|
||||||
|
this.migration = migration;
|
||||||
|
if (migration.readChanges()) {
|
||||||
|
changeSeq = new RepoSequence(
|
||||||
|
repoManager, allProjects, "changes", ReviewDb.FIRST_CHANGE_ID, 100);
|
||||||
|
} else {
|
||||||
|
changeSeq = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public int nextChangeId() throws OrmException {
|
||||||
|
if (migration.readChanges()) {
|
||||||
|
return changeSeq.next();
|
||||||
|
} else {
|
||||||
|
return db.get().nextChangeId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ import com.google.gerrit.server.ChangeMessagesUtil;
|
|||||||
import com.google.gerrit.server.ChangeUtil;
|
import com.google.gerrit.server.ChangeUtil;
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.Sequences;
|
||||||
import com.google.gerrit.server.git.BatchUpdate;
|
import com.google.gerrit.server.git.BatchUpdate;
|
||||||
import com.google.gerrit.server.git.CodeReviewCommit;
|
import com.google.gerrit.server.git.CodeReviewCommit;
|
||||||
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
|
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
|
||||||
@@ -71,6 +72,7 @@ import java.util.TimeZone;
|
|||||||
public class CherryPickChange {
|
public class CherryPickChange {
|
||||||
|
|
||||||
private final Provider<ReviewDb> db;
|
private final Provider<ReviewDb> db;
|
||||||
|
private final Sequences seq;
|
||||||
private final Provider<InternalChangeQuery> queryProvider;
|
private final Provider<InternalChangeQuery> queryProvider;
|
||||||
private final GitRepositoryManager gitManager;
|
private final GitRepositoryManager gitManager;
|
||||||
private final TimeZone serverTimeZone;
|
private final TimeZone serverTimeZone;
|
||||||
@@ -84,6 +86,7 @@ public class CherryPickChange {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CherryPickChange(Provider<ReviewDb> db,
|
CherryPickChange(Provider<ReviewDb> db,
|
||||||
|
Sequences seq,
|
||||||
Provider<InternalChangeQuery> queryProvider,
|
Provider<InternalChangeQuery> queryProvider,
|
||||||
@GerritPersonIdent PersonIdent myIdent,
|
@GerritPersonIdent PersonIdent myIdent,
|
||||||
GitRepositoryManager gitManager,
|
GitRepositoryManager gitManager,
|
||||||
@@ -95,6 +98,7 @@ public class CherryPickChange {
|
|||||||
ChangeUpdate.Factory updateFactory,
|
ChangeUpdate.Factory updateFactory,
|
||||||
BatchUpdate.Factory batchUpdateFactory) {
|
BatchUpdate.Factory batchUpdateFactory) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
this.seq = seq;
|
||||||
this.queryProvider = queryProvider;
|
this.queryProvider = queryProvider;
|
||||||
this.gitManager = gitManager;
|
this.gitManager = gitManager;
|
||||||
this.serverTimeZone = myIdent.getTimeZone();
|
this.serverTimeZone = myIdent.getTimeZone();
|
||||||
@@ -233,7 +237,7 @@ public class CherryPickChange {
|
|||||||
IdentifiedUser identifiedUser, String topic, Branch.NameKey sourceBranch)
|
IdentifiedUser identifiedUser, String topic, Branch.NameKey sourceBranch)
|
||||||
throws RestApiException, UpdateException, OrmException {
|
throws RestApiException, UpdateException, OrmException {
|
||||||
Change change =
|
Change change =
|
||||||
new Change(changeKey, new Change.Id(db.get().nextChangeId()),
|
new Change(changeKey, new Change.Id(seq.nextChangeId()),
|
||||||
identifiedUser.getAccountId(), new Branch.NameKey(project,
|
identifiedUser.getAccountId(), new Branch.NameKey(project,
|
||||||
destRef.getName()), TimeUtil.nowTs());
|
destRef.getName()), TimeUtil.nowTs());
|
||||||
change.setTopic(topic);
|
change.setTopic(topic);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import com.google.gerrit.server.ChangeUtil;
|
|||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.Sequences;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.git.BatchUpdate;
|
import com.google.gerrit.server.git.BatchUpdate;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
@@ -77,6 +78,7 @@ public class CreateChange implements
|
|||||||
|
|
||||||
private final Provider<ReviewDb> db;
|
private final Provider<ReviewDb> db;
|
||||||
private final GitRepositoryManager gitManager;
|
private final GitRepositoryManager gitManager;
|
||||||
|
private final Sequences seq;
|
||||||
private final TimeZone serverTimeZone;
|
private final TimeZone serverTimeZone;
|
||||||
private final Provider<CurrentUser> user;
|
private final Provider<CurrentUser> user;
|
||||||
private final ProjectsCollection projectsCollection;
|
private final ProjectsCollection projectsCollection;
|
||||||
@@ -89,6 +91,7 @@ public class CreateChange implements
|
|||||||
@Inject
|
@Inject
|
||||||
CreateChange(Provider<ReviewDb> db,
|
CreateChange(Provider<ReviewDb> db,
|
||||||
GitRepositoryManager gitManager,
|
GitRepositoryManager gitManager,
|
||||||
|
Sequences seq,
|
||||||
@GerritPersonIdent PersonIdent myIdent,
|
@GerritPersonIdent PersonIdent myIdent,
|
||||||
Provider<CurrentUser> user,
|
Provider<CurrentUser> user,
|
||||||
ProjectsCollection projectsCollection,
|
ProjectsCollection projectsCollection,
|
||||||
@@ -99,6 +102,7 @@ public class CreateChange implements
|
|||||||
@GerritServerConfig Config config) {
|
@GerritServerConfig Config config) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.gitManager = gitManager;
|
this.gitManager = gitManager;
|
||||||
|
this.seq = seq;
|
||||||
this.serverTimeZone = myIdent.getTimeZone();
|
this.serverTimeZone = myIdent.getTimeZone();
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.projectsCollection = projectsCollection;
|
this.projectsCollection = projectsCollection;
|
||||||
@@ -194,7 +198,7 @@ public class CreateChange implements
|
|||||||
|
|
||||||
Change change = new Change(
|
Change change = new Change(
|
||||||
getChangeId(id, c),
|
getChangeId(id, c),
|
||||||
new Change.Id(db.get().nextChangeId()),
|
new Change.Id(seq.nextChangeId()),
|
||||||
me.getAccountId(),
|
me.getAccountId(),
|
||||||
new Branch.NameKey(project, refName),
|
new Branch.NameKey(project, refName),
|
||||||
now);
|
now);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import com.google.gerrit.server.ApprovalsUtil;
|
|||||||
import com.google.gerrit.server.CmdLineParserModule;
|
import com.google.gerrit.server.CmdLineParserModule;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.PluginUser;
|
import com.google.gerrit.server.PluginUser;
|
||||||
|
import com.google.gerrit.server.Sequences;
|
||||||
import com.google.gerrit.server.account.AccountByEmailCacheImpl;
|
import com.google.gerrit.server.account.AccountByEmailCacheImpl;
|
||||||
import com.google.gerrit.server.account.AccountCacheImpl;
|
import com.google.gerrit.server.account.AccountCacheImpl;
|
||||||
import com.google.gerrit.server.account.AccountControl;
|
import com.google.gerrit.server.account.AccountControl;
|
||||||
@@ -165,6 +166,7 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
|
|
||||||
bind(IdGenerator.class);
|
bind(IdGenerator.class);
|
||||||
bind(RulesCache.class);
|
bind(RulesCache.class);
|
||||||
|
bind(Sequences.class);
|
||||||
install(authModule);
|
install(authModule);
|
||||||
install(AccountByEmailCacheImpl.module());
|
install(AccountByEmailCacheImpl.module());
|
||||||
install(AccountCacheImpl.module());
|
install(AccountCacheImpl.module());
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ import com.google.gerrit.server.ApprovalsUtil;
|
|||||||
import com.google.gerrit.server.ChangeMessagesUtil;
|
import com.google.gerrit.server.ChangeMessagesUtil;
|
||||||
import com.google.gerrit.server.ChangeUtil;
|
import com.google.gerrit.server.ChangeUtil;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.Sequences;
|
||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.account.AccountResolver;
|
import com.google.gerrit.server.account.AccountResolver;
|
||||||
import com.google.gerrit.server.change.ChangeInserter;
|
import com.google.gerrit.server.change.ChangeInserter;
|
||||||
@@ -284,6 +285,7 @@ public class ReceiveCommits {
|
|||||||
|
|
||||||
private final IdentifiedUser user;
|
private final IdentifiedUser user;
|
||||||
private final ReviewDb db;
|
private final ReviewDb db;
|
||||||
|
private final Sequences seq;
|
||||||
private final Provider<InternalChangeQuery> queryProvider;
|
private final Provider<InternalChangeQuery> queryProvider;
|
||||||
private final ChangeData.Factory changeDataFactory;
|
private final ChangeData.Factory changeDataFactory;
|
||||||
private final ChangeUpdate.Factory updateFactory;
|
private final ChangeUpdate.Factory updateFactory;
|
||||||
@@ -355,6 +357,7 @@ public class ReceiveCommits {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ReceiveCommits(final ReviewDb db,
|
ReceiveCommits(final ReviewDb db,
|
||||||
|
final Sequences seq,
|
||||||
final Provider<InternalChangeQuery> queryProvider,
|
final Provider<InternalChangeQuery> queryProvider,
|
||||||
final SchemaFactory<ReviewDb> schemaFactory,
|
final SchemaFactory<ReviewDb> schemaFactory,
|
||||||
final ChangeData.Factory changeDataFactory,
|
final ChangeData.Factory changeDataFactory,
|
||||||
@@ -401,6 +404,7 @@ public class ReceiveCommits {
|
|||||||
final SetHashtagsOp.Factory hashtagsFactory) throws IOException {
|
final SetHashtagsOp.Factory hashtagsFactory) throws IOException {
|
||||||
this.user = projectControl.getUser().asIdentifiedUser();
|
this.user = projectControl.getUser().asIdentifiedUser();
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
this.seq = seq;
|
||||||
this.queryProvider = queryProvider;
|
this.queryProvider = queryProvider;
|
||||||
this.changeDataFactory = changeDataFactory;
|
this.changeDataFactory = changeDataFactory;
|
||||||
this.updateFactory = updateFactory;
|
this.updateFactory = updateFactory;
|
||||||
@@ -1733,7 +1737,7 @@ public class ReceiveCommits {
|
|||||||
throws OrmException {
|
throws OrmException {
|
||||||
commit = c;
|
commit = c;
|
||||||
change = new Change(changeKey,
|
change = new Change(changeKey,
|
||||||
new Change.Id(db.nextChangeId()),
|
new Change.Id(seq.nextChangeId()),
|
||||||
user.getAccountId(),
|
user.getAccountId(),
|
||||||
magicBranch.dest,
|
magicBranch.dest,
|
||||||
TimeUtil.nowTs());
|
TimeUtil.nowTs());
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
// Copyright (C) 2016 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.google.gerrit.server.notedb;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.CharMatcher;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
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.git.GitRepositoryManager;
|
||||||
|
import com.google.gwtorm.server.OrmException;
|
||||||
|
|
||||||
|
import com.github.rholder.retry.RetryException;
|
||||||
|
import com.github.rholder.retry.Retryer;
|
||||||
|
import com.github.rholder.retry.RetryerBuilder;
|
||||||
|
import com.github.rholder.retry.StopStrategies;
|
||||||
|
import com.github.rholder.retry.WaitStrategies;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.ObjectInserter;
|
||||||
|
import org.eclipse.jgit.lib.ObjectLoader;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for managing an incrementing sequence backed by a git repository.
|
||||||
|
* <p>
|
||||||
|
* The current sequence number is stored as UTF-8 text in a blob pointed to
|
||||||
|
* by a ref in the {@code refs/sequences/*} namespace. Multiple processes can
|
||||||
|
* share the same sequence by incrementing the counter using normal git ref
|
||||||
|
* updates. To amortize the cost of these ref updates, processes can increment
|
||||||
|
* the counter by a larger number and hand out numbers from that range in memory
|
||||||
|
* until they run out. This means concurrent processes will hand out somewhat
|
||||||
|
* non-monotonic numbers.
|
||||||
|
*/
|
||||||
|
public class RepoSequence {
|
||||||
|
@VisibleForTesting
|
||||||
|
static RetryerBuilder<RefUpdate.Result> retryerBuilder() {
|
||||||
|
return RetryerBuilder.<RefUpdate.Result> newBuilder()
|
||||||
|
.retryIfResult(Predicates.equalTo(RefUpdate.Result.LOCK_FAILURE))
|
||||||
|
.withWaitStrategy(
|
||||||
|
WaitStrategies.join(
|
||||||
|
WaitStrategies.exponentialWait(5, TimeUnit.SECONDS),
|
||||||
|
WaitStrategies.randomWait(50, TimeUnit.MILLISECONDS)))
|
||||||
|
.withStopStrategy(StopStrategies.stopAfterDelay(30, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build();
|
||||||
|
|
||||||
|
private final GitRepositoryManager repoManager;
|
||||||
|
private final Project.NameKey projectName;
|
||||||
|
private final String refName;
|
||||||
|
private final int start;
|
||||||
|
private final int batchSize;
|
||||||
|
private final Runnable afterReadRef;
|
||||||
|
private final Retryer<RefUpdate.Result> retryer;
|
||||||
|
|
||||||
|
// Protects all non-final fields.
|
||||||
|
private final Lock counterLock;
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
private int counter;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
int acquireCount;
|
||||||
|
|
||||||
|
public RepoSequence(GitRepositoryManager repoManager,
|
||||||
|
Project.NameKey projectName, String name, int start, int batchSize) {
|
||||||
|
this(repoManager, projectName, name, start, batchSize,
|
||||||
|
Runnables.doNothing(), RETRYER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
RepoSequence(GitRepositoryManager repoManager, Project.NameKey projectName,
|
||||||
|
String name, int start, int batchSize, Runnable afterReadRef,
|
||||||
|
Retryer<RefUpdate.Result> retryer) {
|
||||||
|
this.repoManager = checkNotNull(repoManager, "repoManager");
|
||||||
|
this.projectName = checkNotNull(projectName, "projectName");
|
||||||
|
this.refName = RefNames.REFS_SEQUENCES + checkNotNull(name, "name");
|
||||||
|
this.start = start;
|
||||||
|
checkArgument(batchSize > 0, "expected batchSize > 0, got: %s", batchSize);
|
||||||
|
this.batchSize = batchSize;
|
||||||
|
this.afterReadRef = checkNotNull(afterReadRef, "afterReadRef");
|
||||||
|
this.retryer = checkNotNull(retryer, "retryer");
|
||||||
|
|
||||||
|
counterLock = new ReentrantLock(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int next() throws OrmException {
|
||||||
|
counterLock.lock();
|
||||||
|
try {
|
||||||
|
if (counter >= limit) {
|
||||||
|
acquire();
|
||||||
|
}
|
||||||
|
return counter++;
|
||||||
|
} finally {
|
||||||
|
counterLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acquire() throws OrmException {
|
||||||
|
try (Repository repo = repoManager.openRepository(projectName);
|
||||||
|
RevWalk rw = new RevWalk(repo)) {
|
||||||
|
TryAcquire attempt = new TryAcquire(repo, rw);
|
||||||
|
RefUpdate.Result result = retryer.call(attempt);
|
||||||
|
if (result != RefUpdate.Result.NEW && result != RefUpdate.Result.FORCED) {
|
||||||
|
throw new OrmException("failed to update " + refName + ": " + result);
|
||||||
|
}
|
||||||
|
counter = attempt.next;
|
||||||
|
limit = counter + batchSize;
|
||||||
|
acquireCount++;
|
||||||
|
} catch (ExecutionException | RetryException e) {
|
||||||
|
Throwables.propagateIfInstanceOf(e.getCause(), OrmException.class);
|
||||||
|
throw new OrmException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new OrmException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TryAcquire implements Callable<RefUpdate.Result> {
|
||||||
|
private final Repository repo;
|
||||||
|
private final RevWalk rw;
|
||||||
|
|
||||||
|
private int next;
|
||||||
|
|
||||||
|
private TryAcquire(Repository repo, RevWalk rw) {
|
||||||
|
this.repo = repo;
|
||||||
|
this.rw = rw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefUpdate.Result call() throws Exception {
|
||||||
|
Ref ref = repo.exactRef(refName);
|
||||||
|
afterReadRef.run();
|
||||||
|
ObjectId oldId;
|
||||||
|
if (ref == null) {
|
||||||
|
oldId = ObjectId.zeroId();
|
||||||
|
next = start;
|
||||||
|
} else {
|
||||||
|
oldId = ref.getObjectId();
|
||||||
|
next = parse(oldId);
|
||||||
|
}
|
||||||
|
return store(oldId, next + batchSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parse(ObjectId id) throws IOException, OrmException {
|
||||||
|
ObjectLoader ol = rw.getObjectReader().open(id, OBJ_BLOB);
|
||||||
|
if (ol.getType() != OBJ_BLOB) {
|
||||||
|
// In theory this should be thrown by open but not all implementations
|
||||||
|
// may do it properly (certainly InMemoryRepository doesn't).
|
||||||
|
throw new IncorrectObjectTypeException(id, OBJ_BLOB);
|
||||||
|
}
|
||||||
|
String str = CharMatcher.WHITESPACE.trimFrom(
|
||||||
|
new String(ol.getCachedBytes(), UTF_8));
|
||||||
|
Integer val = Ints.tryParse(str);
|
||||||
|
if (val == null) {
|
||||||
|
throw new OrmException(
|
||||||
|
"invalid value in " + refName + " blob at " + id.name());
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RefUpdate.Result store(ObjectId oldId, int val) throws IOException {
|
||||||
|
ObjectId newId;
|
||||||
|
try (ObjectInserter ins = repo.newObjectInserter()) {
|
||||||
|
newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
|
||||||
|
ins.flush();
|
||||||
|
}
|
||||||
|
RefUpdate ru = repo.updateRef(refName);
|
||||||
|
ru.setExpectedOldObjectId(oldId);
|
||||||
|
ru.setNewObjectId(newId);
|
||||||
|
ru.setForceUpdate(true); // Required for non-commitish updates.
|
||||||
|
return ru.update(rw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
// Copyright (C) 2016 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.google.gerrit.server.notedb;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
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.testutil.InMemoryRepositoryManager;
|
||||||
|
import com.google.gwtorm.server.OrmException;
|
||||||
|
|
||||||
|
import com.github.rholder.retry.BlockStrategy;
|
||||||
|
import com.github.rholder.retry.Retryer;
|
||||||
|
import com.github.rholder.retry.RetryerBuilder;
|
||||||
|
import com.github.rholder.retry.StopStrategies;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.ObjectInserter;
|
||||||
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class RepoSequenceTest {
|
||||||
|
private static final Retryer<RefUpdate.Result> RETRYER =
|
||||||
|
RepoSequence.retryerBuilder().withBlockStrategy(new BlockStrategy() {
|
||||||
|
@Override
|
||||||
|
public void block(long sleepTime) {
|
||||||
|
// Don't sleep in tests.
|
||||||
|
}
|
||||||
|
}).build();
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException exception = ExpectedException.none();
|
||||||
|
|
||||||
|
private InMemoryRepositoryManager repoManager;
|
||||||
|
private Project.NameKey project;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
repoManager = new InMemoryRepositoryManager();
|
||||||
|
project = new Project.NameKey("project");
|
||||||
|
repoManager.createRepository(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneCaller() throws Exception {
|
||||||
|
int max = 20;
|
||||||
|
for (int batchSize = 1; batchSize <= 10; batchSize++) {
|
||||||
|
String name = "batch-size-" + batchSize;
|
||||||
|
RepoSequence s = newSequence(name, 1, batchSize);
|
||||||
|
for (int i = 1; i <= max; i++) {
|
||||||
|
try {
|
||||||
|
assertThat(s.next()).named("next for " + name).isEqualTo(i);
|
||||||
|
} catch (OrmException e) {
|
||||||
|
throw new AssertionError(
|
||||||
|
"failed batchSize=" + batchSize + ", i=" + i, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertThat(s.acquireCount)
|
||||||
|
.named("acquireCount for " + name)
|
||||||
|
.isEqualTo(divCeil(max, batchSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twoCallers() throws Exception {
|
||||||
|
RepoSequence s1 = newSequence("id", 1, 3);
|
||||||
|
RepoSequence s2 = newSequence("id", 1, 3);
|
||||||
|
|
||||||
|
// s1 acquires 1-3; s2 acquires 4-6.
|
||||||
|
assertThat(s1.next()).isEqualTo(1);
|
||||||
|
assertThat(s2.next()).isEqualTo(4);
|
||||||
|
assertThat(s1.next()).isEqualTo(2);
|
||||||
|
assertThat(s2.next()).isEqualTo(5);
|
||||||
|
assertThat(s1.next()).isEqualTo(3);
|
||||||
|
assertThat(s2.next()).isEqualTo(6);
|
||||||
|
|
||||||
|
// s2 acquires 7-9; s1 acquires 10-12.
|
||||||
|
assertThat(s2.next()).isEqualTo(7);
|
||||||
|
assertThat(s1.next()).isEqualTo(10);
|
||||||
|
assertThat(s2.next()).isEqualTo(8);
|
||||||
|
assertThat(s1.next()).isEqualTo(11);
|
||||||
|
assertThat(s2.next()).isEqualTo(9);
|
||||||
|
assertThat(s1.next()).isEqualTo(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void populateEmptyRefWithStartValue() throws Exception {
|
||||||
|
RepoSequence s = newSequence("id", 1234, 10);
|
||||||
|
assertThat(s.next()).isEqualTo(1234);
|
||||||
|
assertThat(readBlob("id")).isEqualTo("1244");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void startIsIgnoredIfRefIsPresent() throws Exception {
|
||||||
|
writeBlob("id", "1234");
|
||||||
|
RepoSequence s = newSequence("id", 3456, 10);
|
||||||
|
assertThat(s.next()).isEqualTo(1234);
|
||||||
|
assertThat(readBlob("id")).isEqualTo("1244");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void retryOnLockFailure() throws Exception {
|
||||||
|
// Seed existing ref value.
|
||||||
|
writeBlob("id", "1");
|
||||||
|
|
||||||
|
final AtomicBoolean doneBgUpdate = new AtomicBoolean(false);
|
||||||
|
Runnable bgUpdate = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!doneBgUpdate.getAndSet(true)) {
|
||||||
|
writeBlob("id", "1234");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RepoSequence s = newSequence("id", 1, 10, bgUpdate, RETRYER);
|
||||||
|
assertThat(doneBgUpdate.get()).isFalse();
|
||||||
|
assertThat(s.next()).isEqualTo(1234);
|
||||||
|
// Single acquire call that results in 2 ref reads.
|
||||||
|
assertThat(s.acquireCount).isEqualTo(1);
|
||||||
|
assertThat(doneBgUpdate.get()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void failOnInvalidValue() throws Exception {
|
||||||
|
ObjectId id = writeBlob("id", "not a number");
|
||||||
|
exception.expect(OrmException.class);
|
||||||
|
exception.expectMessage(
|
||||||
|
"invalid value in refs/sequences/id blob at " + id.name());
|
||||||
|
newSequence("id", 1, 3).next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void failOnWrongType() throws Exception {
|
||||||
|
try (Repository repo = repoManager.openRepository(project)) {
|
||||||
|
TestRepository<Repository> tr = new TestRepository<>(repo);
|
||||||
|
tr.branch(RefNames.REFS_SEQUENCES + "id").commit().create();
|
||||||
|
try {
|
||||||
|
newSequence("id", 1, 3).next();
|
||||||
|
fail();
|
||||||
|
} catch (OrmException e) {
|
||||||
|
assertThat(e.getCause()).isInstanceOf(ExecutionException.class);
|
||||||
|
assertThat(e.getCause().getCause())
|
||||||
|
.isInstanceOf(IncorrectObjectTypeException.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void failAfterRetryerGivesUp() throws Exception {
|
||||||
|
final AtomicInteger bgCounter = new AtomicInteger(1234);
|
||||||
|
Runnable bgUpdate = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
writeBlob("id", Integer.toString(bgCounter.getAndAdd(1000)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RepoSequence s = newSequence(
|
||||||
|
"id", 1, 10, bgUpdate,
|
||||||
|
RetryerBuilder.<RefUpdate.Result> newBuilder()
|
||||||
|
.withStopStrategy(StopStrategies.stopAfterAttempt(3))
|
||||||
|
.build());
|
||||||
|
exception.expect(OrmException.class);
|
||||||
|
exception.expectMessage("failed to update refs/sequences/id: LOCK_FAILURE");
|
||||||
|
s.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RepoSequence newSequence(String name, int start, int batchSize) {
|
||||||
|
return newSequence(
|
||||||
|
name, start, batchSize, Runnables.doNothing(), RETRYER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RepoSequence newSequence(String name, int start, int batchSize,
|
||||||
|
Runnable afterReadRef, Retryer<RefUpdate.Result> retryer) {
|
||||||
|
return new RepoSequence(
|
||||||
|
repoManager, project, name, start, batchSize, afterReadRef, retryer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectId writeBlob(String sequenceName, String value) {
|
||||||
|
String refName = RefNames.REFS_SEQUENCES + sequenceName;
|
||||||
|
try (Repository repo = repoManager.openRepository(project);
|
||||||
|
ObjectInserter ins = repo.newObjectInserter()) {
|
||||||
|
ObjectId newId = ins.insert(OBJ_BLOB, value.getBytes(UTF_8));
|
||||||
|
ins.flush();
|
||||||
|
RefUpdate ru = repo.updateRef(refName);
|
||||||
|
ru.setNewObjectId(newId);
|
||||||
|
assertThat(ru.forceUpdate())
|
||||||
|
.isAnyOf(RefUpdate.Result.NEW, RefUpdate.Result.FORCED);
|
||||||
|
return newId;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readBlob(String sequenceName) throws Exception {
|
||||||
|
String refName = RefNames.REFS_SEQUENCES + sequenceName;
|
||||||
|
try (Repository repo = repoManager.openRepository(project);
|
||||||
|
RevWalk rw = new RevWalk(repo)) {
|
||||||
|
ObjectId id = repo.exactRef(refName).getObjectId();
|
||||||
|
return new String(rw.getObjectReader().open(id).getCachedBytes(), UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long divCeil(float a, float b) {
|
||||||
|
return Math.round(Math.ceil(a / b));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@ import com.google.gerrit.reviewdb.client.Project;
|
|||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.Sequences;
|
||||||
import com.google.gerrit.server.account.AccountManager;
|
import com.google.gerrit.server.account.AccountManager;
|
||||||
import com.google.gerrit.server.account.AuthRequest;
|
import com.google.gerrit.server.account.AuthRequest;
|
||||||
import com.google.gerrit.server.account.GroupCache;
|
import com.google.gerrit.server.account.GroupCache;
|
||||||
@@ -104,24 +105,25 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Inject protected AccountManager accountManager;
|
@Inject protected AccountManager accountManager;
|
||||||
|
@Inject protected AddMembers addMembers;
|
||||||
@Inject protected BatchUpdate.Factory updateFactory;
|
@Inject protected BatchUpdate.Factory updateFactory;
|
||||||
@Inject protected ChangeInserter.Factory changeFactory;
|
|
||||||
@Inject protected PatchSetInserter.Factory patchSetFactory;
|
|
||||||
@Inject protected ChangeControl.GenericFactory changeControlFactory;
|
@Inject protected ChangeControl.GenericFactory changeControlFactory;
|
||||||
|
@Inject protected ChangeInserter.Factory changeFactory;
|
||||||
|
@Inject protected ChangeQueryBuilder queryBuilder;
|
||||||
@Inject protected GerritApi gApi;
|
@Inject protected GerritApi gApi;
|
||||||
|
@Inject protected GroupCache groupCache;
|
||||||
@Inject protected IdentifiedUser.GenericFactory userFactory;
|
@Inject protected IdentifiedUser.GenericFactory userFactory;
|
||||||
@Inject protected IndexCollection indexes;
|
@Inject protected IndexCollection indexes;
|
||||||
@Inject protected InMemoryDatabase schemaFactory;
|
@Inject protected InMemoryDatabase schemaFactory;
|
||||||
@Inject protected InMemoryRepositoryManager repoManager;
|
@Inject protected InMemoryRepositoryManager repoManager;
|
||||||
@Inject protected InternalChangeQuery internalChangeQuery;
|
@Inject protected InternalChangeQuery internalChangeQuery;
|
||||||
@Inject protected NotesMigration notesMigration;
|
@Inject protected NotesMigration notesMigration;
|
||||||
|
@Inject protected PatchSetInserter.Factory patchSetFactory;
|
||||||
@Inject protected ProjectControl.GenericFactory projectControlFactory;
|
@Inject protected ProjectControl.GenericFactory projectControlFactory;
|
||||||
@Inject protected ChangeQueryBuilder queryBuilder;
|
|
||||||
@Inject protected QueryProcessor queryProcessor;
|
@Inject protected QueryProcessor queryProcessor;
|
||||||
@Inject protected SchemaCreator schemaCreator;
|
@Inject protected SchemaCreator schemaCreator;
|
||||||
|
@Inject protected Sequences seq;
|
||||||
@Inject protected ThreadLocalRequestContext requestContext;
|
@Inject protected ThreadLocalRequestContext requestContext;
|
||||||
@Inject protected GroupCache groupCache;
|
|
||||||
@Inject protected AddMembers addMembers;
|
|
||||||
|
|
||||||
protected LifecycleManager lifecycle;
|
protected LifecycleManager lifecycle;
|
||||||
protected ReviewDb db;
|
protected ReviewDb db;
|
||||||
@@ -1396,7 +1398,7 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
|
|||||||
Project.NameKey project = new Project.NameKey(
|
Project.NameKey project = new Project.NameKey(
|
||||||
repo.getRepository().getDescription().getRepositoryName());
|
repo.getRepository().getDescription().getRepositoryName());
|
||||||
|
|
||||||
Change.Id id = new Change.Id(db.nextChangeId());
|
Change.Id id = new Change.Id(seq.nextChangeId());
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
key = "I" + Hashing.sha1().newHasher()
|
key = "I" + Hashing.sha1().newHasher()
|
||||||
.putInt(id.get())
|
.putInt(id.get())
|
||||||
|
|||||||
20
lib/BUCK
20
lib/BUCK
@@ -68,6 +68,26 @@ maven_jar(
|
|||||||
license = 'Apache2.0',
|
license = 'Apache2.0',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
maven_jar(
|
||||||
|
name = 'guava-retrying',
|
||||||
|
id = 'com.github.rholder:guava-retrying:2.0.0',
|
||||||
|
sha1 = '974bc0a04a11cc4806f7c20a34703bd23c34e7f4',
|
||||||
|
license = 'Apache2.0',
|
||||||
|
deps = [':jsr305'],
|
||||||
|
)
|
||||||
|
|
||||||
|
maven_jar(
|
||||||
|
name = 'jsr305',
|
||||||
|
id = 'com.google.code.findbugs:jsr305:2.0.2',
|
||||||
|
sha1 = '516c03b21d50a644d538de0f0369c620989cd8f0',
|
||||||
|
license = 'Apache2.0',
|
||||||
|
attach_source = False,
|
||||||
|
# Whitelist lib targets that have jsr305 as a dependency. Generally speaking
|
||||||
|
# Gerrit core should not depend on these annotations, and instead use
|
||||||
|
# equivalent annotations in com.google.gerrit.common.
|
||||||
|
visibility = ['//lib:guava-retrying'],
|
||||||
|
)
|
||||||
|
|
||||||
maven_jar(
|
maven_jar(
|
||||||
name = 'velocity',
|
name = 'velocity',
|
||||||
id = 'org.apache.velocity:velocity:1.7',
|
id = 'org.apache.velocity:velocity:1.7',
|
||||||
|
|||||||
Reference in New Issue
Block a user