Only recheck mergeable on reindex with a flag

The mergeability computation is expensive and should be redundant
after it's been run once. Protect this behavior with a flag that
defaults to false, and instruct users to run reindex with the flag in
the release notes.

Change-Id: I3c6140b9a727165b8b43712a0d162c530db048a6
This commit is contained in:
Dave Borowitz
2014-01-10 15:14:00 -08:00
parent 94f8861a8d
commit fbc01d6388
3 changed files with 79 additions and 57 deletions

View File

@@ -19,6 +19,7 @@ Schema Change
*WARNING:* This release contains schema changes. To upgrade:
----
java -jar gerrit.war init -d site_path
java -jar gerrit.war reindex --recheck-mergeability -d site_path
----
*WARNING:* Upgrading to 2.9.x requires the server be first upgraded to 2.1.7 (or

View File

@@ -47,6 +47,7 @@ import com.google.gerrit.server.account.UniversalGroupBackend;
import com.google.gerrit.server.cache.CacheRemovalListener;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.change.ChangeKindCache;
import com.google.gerrit.server.change.MergeabilityChecker;
import com.google.gerrit.server.change.MergeabilityChecksExecutor;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.config.CanonicalWebUrl;
@@ -116,6 +117,9 @@ public class Reindex extends SiteProgram {
@Option(name = "--output", usage = "Prefix for output; path for local disk index, or prefix for remote index")
private String outputBase;
@Option(name = "--recheck-mergeable", usage = "Recheck mergeable flag on all changes")
private boolean recheckMergeable;
@Option(name = "--verbose", usage = "Output debug information for each change")
private boolean verbose;
@@ -195,58 +199,12 @@ public class Reindex extends SiteProgram {
install(new DefaultCacheFactory.Module());
factory(ChangeData.Factory.class);
factory(ProjectState.Factory.class);
bind(new TypeLiteral<List<CommentLinkInfo>>() {})
.toProvider(CommentLinkProvider.class).in(SINGLETON);
bind(IdentifiedUser.class).toProvider(Providers.<IdentifiedUser>of(null));
bind(CurrentUser.class).to(IdentifiedUser.class);
bind(String.class).annotatedWith(CanonicalWebUrl.class)
.toProvider(CanonicalWebUrlProvider.class);
factory(IncludingGroupMembership.Factory.class);
bind(GroupBackend.class).to(UniversalGroupBackend.class).in(SINGLETON);
DynamicSet.setOf(binder(), GroupBackend.class);
bind(InternalGroupBackend.class).in(SINGLETON);
DynamicSet.bind(binder(), GroupBackend.class).to(SystemGroupBackend.class);
DynamicSet.bind(binder(), GroupBackend.class).to(InternalGroupBackend.class);
factory(InternalUser.Factory.class);
factory(PatchSetInserter.Factory.class);
bind(ChangeHooks.class).to(DisabledChangeHooks.class);
bind(ReplacePatchSetSender.Factory.class).toProvider(
Providers.<ReplacePatchSetSender.Factory>of(null));
factory(CapabilityControl.Factory.class);
factory(MergeUtil.Factory.class);
DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class);
DynamicSet.setOf(binder(), CommitValidationListener.class);
factory(CommitValidators.Factory.class);
}
});
modules.add(AccountCacheImpl.module());
modules.add(AccountByEmailCacheImpl.module());
modules.add(ChangeKindCache.module());
modules.add(GroupCacheImpl.module());
modules.add(GroupIncludeCacheImpl.module());
modules.add(ProjectCacheImpl.module());
modules.add(SectionSortCache.module());
modules.add(new AccessControlModule());
modules.add(new GitModule());
modules.add(new NoteDbModule());
modules.add(new PrologModule());
modules.add(new AbstractModule() {
@Override
protected void configure() {
}
@Provides
@Singleton
@MergeabilityChecksExecutor
public WorkQueue.Executor createMergeabilityChecksExecutor(
WorkQueue queues) {
return queues.createQueue(1, "MergeabilityChecks");
if (recheckMergeable) {
install(new MergeabilityModule());
} else {
bind(MergeabilityChecker.class)
.toProvider(Providers.<MergeabilityChecker> of(null));
}
}
});
@@ -294,6 +252,59 @@ public class Reindex extends SiteProgram {
}
}
private static class MergeabilityModule extends FactoryModule {
@Override
public void configure() {
factory(ProjectState.Factory.class);
bind(new TypeLiteral<List<CommentLinkInfo>>() {})
.toProvider(CommentLinkProvider.class).in(SINGLETON);
bind(IdentifiedUser.class).toProvider(Providers.<IdentifiedUser>of(null));
bind(CurrentUser.class).to(IdentifiedUser.class);
bind(String.class).annotatedWith(CanonicalWebUrl.class)
.toProvider(CanonicalWebUrlProvider.class);
factory(IncludingGroupMembership.Factory.class);
bind(GroupBackend.class).to(UniversalGroupBackend.class).in(SINGLETON);
DynamicSet.setOf(binder(), GroupBackend.class);
bind(InternalGroupBackend.class).in(SINGLETON);
DynamicSet.bind(binder(), GroupBackend.class).to(SystemGroupBackend.class);
DynamicSet.bind(binder(), GroupBackend.class).to(InternalGroupBackend.class);
factory(InternalUser.Factory.class);
factory(PatchSetInserter.Factory.class);
bind(ChangeHooks.class).to(DisabledChangeHooks.class);
bind(ReplacePatchSetSender.Factory.class).toProvider(
Providers.<ReplacePatchSetSender.Factory>of(null));
factory(CapabilityControl.Factory.class);
factory(MergeUtil.Factory.class);
DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class);
DynamicSet.setOf(binder(), CommitValidationListener.class);
factory(CommitValidators.Factory.class);
install(AccountCacheImpl.module());
install(AccountByEmailCacheImpl.module());
install(ChangeKindCache.module());
install(GroupCacheImpl.module());
install(GroupIncludeCacheImpl.module());
install(ProjectCacheImpl.module());
install(SectionSortCache.module());
install(new AccessControlModule());
install(new GitModule());
install(new NoteDbModule());
install(new PrologModule());
}
@Provides
@Singleton
@MergeabilityChecksExecutor
public WorkQueue.Executor createMergeabilityChecksExecutor(
WorkQueue queues) {
return queues.createQueue(1, "MergeabilityChecks");
}
}
private int indexAll() throws Exception {
ReviewDb db = sysInjector.getInstance(ReviewDb.class);
ProgressMonitor pm = new TextProgressMonitor();

View File

@@ -27,6 +27,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -118,7 +119,7 @@ public class ChangeBatchIndexer {
GitRepositoryManager repoManager,
@IndexExecutor ListeningExecutorService executor,
ChangeIndexer.Factory indexerFactory,
MergeabilityChecker mergeabilityChecker) {
@Nullable MergeabilityChecker mergeabilityChecker) {
this.schemaFactory = schemaFactory;
this.changeDataFactory = changeDataFactory;
this.repoManager = repoManager;
@@ -149,10 +150,7 @@ public class ChangeBatchIndexer {
final AtomicBoolean ok = new AtomicBoolean(true);
for (final Project.NameKey project : projects) {
try {
mergeabilityChecker.update(project);
} catch (IOException e) {
log.error("Error in mergeability checker", e);
if (!updateMergeable(project)) {
ok.set(false);
}
final ListenableFuture<?> future = executor.submit(reindexProject(
@@ -210,6 +208,18 @@ public class ChangeBatchIndexer {
return new Result(sw, ok.get(), doneTask.getCount(), failedTask.getCount());
}
private boolean updateMergeable(Project.NameKey project) {
if (mergeabilityChecker != null) {
try {
mergeabilityChecker.update(project);
} catch (IOException e) {
log.error("Error in mergeability checker", e);
return false;
}
}
return true;
}
private Callable<Void> reindexProject(final ChangeIndexer indexer,
final Project.NameKey project, final Task done, final Task failed,
final PrintWriter verboseWriter) {