Encapsulate per-index utilities in a pair of generic classes

This collects the schema definitions (superseding the static
ChangeSchemas utilities) into a class called SchemaDefinitions.
Additionally, the backend-specific implementation classes (index
collection, site indexer, etc.) are collected into a class called
IndexDefinition. (We use the longer "definition" rather than "type"
because the latter is already used to describe the backend
implementation.)

The total set of supported index definitions is bound in IndexModule,
which provides them as a Collection<IndexDefinition<?, ?, ?>>.
Alternatively, callers that can't get the injected implementations
(notably InitIndex) can access the fully-static list of schema
definitions.

Abstract out LuceneChangeIndex.Factory into a generic IndexFactory
interface. At this point the only things that a particular backend
implementation needs to implement are:

 - The IndexFactory that constructs a per-implementation index
   implementation given a schema definition. Eventually this will
   expand to one IndexFactory implementation per index definition.
 - A listener that populates the IndexCollection for each supported
   index definition.

This change uses the Collection<IndexDefinition> in most places where
it is possible, with a few exceptions that will require a bit more
work:

 - LuceneVersionManager, which is used directly by some SSH commands
   to manipulate the index.
 - Reindex, which needs a different scheme for passing flags.

Change-Id: Ia5724cfecaae6335e7c0df24cd41c87b2bb5e36a
This commit is contained in:
Dave Borowitz 2016-03-17 14:00:49 +01:00
parent b518e69abc
commit 886746ff6f
18 changed files with 345 additions and 94 deletions

View File

@ -26,7 +26,6 @@ import com.google.gerrit.pgm.Daemon;
import com.google.gerrit.pgm.Init;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.AsyncReceiveCommits;
import com.google.gerrit.server.index.change.ChangeSchemas;
import com.google.gerrit.server.ssh.NoSshModule;
import com.google.gerrit.server.util.SocketUtil;
import com.google.gerrit.server.util.SystemLog;
@ -142,8 +141,7 @@ public class GerritServer {
cfg.setBoolean("index", "lucene", "testInmemory", true);
cfg.setString("gitweb", null, "cgi", "");
daemon.setEnableHttpd(desc.httpd());
daemon.setLuceneModule(new LuceneIndexModule(
ChangeSchemas.getLatest().getVersion(), 0));
daemon.setLuceneModule(LuceneIndexModule.singleVersionAllLatest(0));
daemon.setDatabaseForTesting(ImmutableList.<Module>of(
new InMemoryTestingDatabaseModule(cfg)));
daemon.start();

View File

@ -123,10 +123,6 @@ public class LuceneChangeIndex implements ChangeIndex {
return QueryBuilder.intTerm(LEGACY_ID.getName(), id.get());
}
static interface Factory {
LuceneChangeIndex create(Schema<ChangeData> schema);
}
private final SitePaths sitePaths;
private final FillArgs fillArgs;
private final ListeningExecutorService executor;

View File

@ -14,44 +14,69 @@
package com.google.gerrit.lucene;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.index.IndexModule;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeSchemas;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import org.apache.lucene.search.BooleanQuery;
import org.eclipse.jgit.lib.Config;
import java.util.Collection;
import java.util.Map;
public class LuceneIndexModule extends LifecycleModule {
private static final String SINGLE_VERSIONS =
"LuceneIndexModule/SingleVersions";
public static LuceneIndexModule singleVersionAllLatest(int threads) {
return new LuceneIndexModule(ImmutableMap.<String, Integer> of(), threads);
}
public static LuceneIndexModule singleVersionWithExplicitVersions(
Map<String, Integer> versions, int threads) {
return new LuceneIndexModule(versions, threads);
}
public static LuceneIndexModule latestVersionWithOnlineUpgrade() {
return new LuceneIndexModule(null, 0);
}
static boolean isInMemoryTest(Config cfg) {
return cfg.getBoolean("index", "lucene", "testInmemory", false);
}
private final Integer singleVersion;
private final int threads;
private final Map<String, Integer> singleVersions;
public LuceneIndexModule() {
this(null, 0);
}
public LuceneIndexModule(Integer singleVersion, int threads) {
this.singleVersion = singleVersion;
private LuceneIndexModule(Map<String, Integer> singleVersions, int threads) {
this.singleVersions = singleVersions;
this.threads = threads;
}
@Override
protected void configure() {
factory(LuceneChangeIndex.Factory.class);
install(
new FactoryModuleBuilder()
.implement(ChangeIndex.class, LuceneChangeIndex.class)
.build(ChangeIndex.Factory.class));
install(new IndexModule(threads));
if (singleVersion == null) {
if (singleVersions == null) {
install(new MultiVersionModule());
} else {
install(new SingleVersionModule());
@ -77,34 +102,48 @@ public class LuceneIndexModule extends LifecycleModule {
@Override
public void configure() {
listener().to(SingleVersionListener.class);
}
@Provides
@Singleton
LuceneChangeIndex getIndex(LuceneChangeIndex.Factory factory) {
Schema<ChangeData> schema = singleVersion != null
? ChangeSchemas.get(singleVersion)
: ChangeSchemas.getLatest();
return factory.create(schema);
bind(new TypeLiteral<Map<String, Integer>>() {})
.annotatedWith(Names.named(SINGLE_VERSIONS))
.toInstance(singleVersions);
}
}
@Singleton
static class SingleVersionListener implements LifecycleListener {
private final ChangeIndexCollection indexes;
private final LuceneChangeIndex index;
private final Collection<IndexDefinition<?, ?, ?>> defs;
private final Map<String, Integer> singleVersions;
@Inject
SingleVersionListener(ChangeIndexCollection indexes,
LuceneChangeIndex index) {
this.indexes = indexes;
this.index = index;
SingleVersionListener(
Collection<IndexDefinition<?, ?, ?>> defs,
@Named(SINGLE_VERSIONS) Map<String, Integer> singleVersions) {
this.defs = defs;
this.singleVersions = singleVersions;
}
@Override
public void start() {
indexes.setSearchIndex(index);
indexes.addWriteIndex(index);
for (IndexDefinition<?, ?, ?> def : defs) {
start(def);
}
}
private <K, V, I extends Index<K, V>> void start(
IndexDefinition<K, V, I> def) {
Schema<V> schema;
Integer v = singleVersions.get(def.getName());
if (v == null) {
schema = def.getLatest();
} else {
schema = def.getSchemas().get(v);
if (schema == null) {
throw new ProvisionException(String.format(
"Unrecognized %s schema version: %s", def.getName(), v));
}
}
I index = def.getIndexFactory().create(schema);
def.getIndexCollection().setSearchIndex(index);
def.getIndexCollection().addWriteIndex(index);
}
@Override

View File

@ -25,10 +25,9 @@ import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.index.OnlineReindexer;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.change.AllChangesIndexer;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeSchemas;
import com.google.gerrit.server.index.change.ChangeIndexDefintion;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
import com.google.inject.ProvisionException;
@ -97,7 +96,7 @@ public class LuceneVersionManager implements LifecycleListener {
private final SitePaths sitePaths;
private final LuceneChangeIndex.Factory indexFactory;
private final ChangeIndexCollection indexes;
private final AllChangesIndexer allChangesIndexer;
private final ChangeIndexDefintion changeDef;
private final boolean onlineUpgrade;
private OnlineReindexer<Change.Id, ChangeData, ChangeIndex> reindexer;
@ -107,11 +106,11 @@ public class LuceneVersionManager implements LifecycleListener {
SitePaths sitePaths,
LuceneChangeIndex.Factory indexFactory,
ChangeIndexCollection indexes,
AllChangesIndexer allChangesIndexer) {
ChangeIndexDefintion changeDef) {
this.sitePaths = sitePaths;
this.indexFactory = indexFactory;
this.indexes = indexes;
this.allChangesIndexer = allChangesIndexer;
this.changeDef = changeDef;
this.onlineUpgrade = cfg.getBoolean("index", null, "onlineUpgrade", true);
}
@ -161,7 +160,8 @@ public class LuceneVersionManager implements LifecycleListener {
}
markNotReady(cfg, versions.values(), write);
LuceneChangeIndex searchIndex = indexFactory.create(search.schema);
LuceneChangeIndex searchIndex =
(LuceneChangeIndex) indexFactory.create(search.schema);
indexes.setSearchIndex(searchIndex);
for (Version v : write) {
if (v.schema != null) {
@ -175,7 +175,7 @@ public class LuceneVersionManager implements LifecycleListener {
int latest = write.get(0).version;
if (onlineUpgrade && latest != search.version) {
reindexer = new OnlineReindexer<>(indexes, allChangesIndexer, latest);
reindexer = new OnlineReindexer<>(changeDef, latest);
reindexer.start();
}
}
@ -227,7 +227,7 @@ public class LuceneVersionManager implements LifecycleListener {
private TreeMap<Integer, Version> scanVersions(Config cfg) {
TreeMap<Integer, Version> versions = Maps.newTreeMap();
for (Schema<ChangeData> schema : ChangeSchemas.ALL.values()) {
for (Schema<ChangeData> schema : changeDef.getSchemas().values()) {
Path p = getDir(sitePaths, CHANGES_PREFIX, schema);
boolean isDir = Files.isDirectory(p);
if (Files.exists(p) && !isDir) {

View File

@ -403,7 +403,9 @@ public class Daemon extends SiteProgram {
}
switch (indexType) {
case LUCENE:
return luceneModule != null ? luceneModule : new LuceneIndexModule();
return luceneModule != null
? luceneModule
: LuceneIndexModule.latestVersionWithOnlineUpgrade();
default:
throw new IllegalStateException("unsupported index.type = " + indexType);
}

View File

@ -29,12 +29,12 @@ import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.ScanningChangeCacheImpl;
import com.google.gerrit.server.index.IndexModule;
import com.google.gerrit.server.index.SiteIndexer;
import com.google.gerrit.server.index.IndexModule.IndexType;
import com.google.gerrit.server.index.SiteIndexer;
import com.google.gerrit.server.index.change.AllChangesIndexer;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeSchemas;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Injector;
@ -48,7 +48,9 @@ import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.util.io.NullOutputStream;
import org.kohsuke.args4j.Option;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -56,9 +58,9 @@ public class Reindex extends SiteProgram {
@Option(name = "--threads", usage = "Number of threads to use for indexing")
private int threads = Runtime.getRuntime().availableProcessors();
@Option(name = "--schema-version",
usage = "Schema version to reindex; default is most recent version")
private Integer version;
@Option(name = "--changes-schema-version",
usage = "Schema version to reindex, for changes; default is most recent version")
private Integer changesVersion;
@Option(name = "--verbose", usage = "Output debug information for each change")
private boolean verbose;
@ -83,9 +85,6 @@ public class Reindex extends SiteProgram {
checkNotSlaveMode();
disableLuceneAutomaticCommit();
disableChangeCache();
if (version == null) {
version = ChangeSchemas.getLatest().getVersion();
}
LifecycleManager dbManager = new LifecycleManager();
dbManager.add(dbInjector);
dbManager.start();
@ -121,11 +120,16 @@ public class Reindex extends SiteProgram {
}
private Injector createSysInjector() {
Map<String, Integer> versions = new HashMap<>();
if (changesVersion != null) {
versions.put(ChangeSchemaDefinitions.INSTANCE.getName(), changesVersion);
}
List<Module> modules = Lists.newArrayList();
Module changeIndexModule;
switch (IndexModule.getIndexType(dbInjector)) {
case LUCENE:
changeIndexModule = new LuceneIndexModule(version, threads);
changeIndexModule = LuceneIndexModule.singleVersionWithExplicitVersions(
versions, threads);
break;
default:
throw new IllegalStateException("unsupported index.type");

View File

@ -21,8 +21,9 @@ import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.InitStep;
import com.google.gerrit.pgm.init.api.Section;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.index.IndexModule;
import com.google.gerrit.server.index.IndexModule.IndexType;
import com.google.gerrit.server.index.change.ChangeSchemas;
import com.google.gerrit.server.index.SchemaDefinitions;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@ -57,8 +58,11 @@ class InitIndex implements InitStep {
ui.header("Index");
IndexType type = index.select("Type", "type", IndexType.LUCENE);
AbstractLuceneIndex.setReady(
site, ChangeSchemas.getLatest().getVersion(), true);
for (SchemaDefinitions<?> def : IndexModule.ALL_SCHEMA_DEFS) {
// TODO(dborowitz): Totally broken for non-change indexes.
AbstractLuceneIndex.setReady(
site, def.getLatest().getVersion(), true);
}
if ((site.isNew || isEmptySite()) && type == IndexType.LUCENE) {
} else {
final String message = String.format(

View File

@ -14,15 +14,24 @@
package com.google.gerrit.server.index;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.DummyChangeIndex;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.AbstractModule;
public class DummyIndexModule extends AbstractModule {
private static class DummyChangeIndexFactory implements ChangeIndex.Factory {
@Override
public ChangeIndex create(Schema<ChangeData> schema) {
throw new UnsupportedOperationException();
}
}
@Override
protected void configure() {
install(new IndexModule(1));
bind(IndexConfig.class).toInstance(IndexConfig.createDefault());
bind(Index.class).toInstance(new DummyChangeIndex());
bind(ChangeIndex.Factory.class).toInstance(new DummyChangeIndexFactory());
}
}

View File

@ -0,0 +1,71 @@
// 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.index;
import com.google.common.collect.ImmutableSortedMap;
/**
* Definition of an index over a Gerrit data type.
* <p>
* An <em>index</em> includes a set of schema definitions along with the
* specific implementations used to query the secondary index implementation in
* a running server. If you are just interested in the static definition of one
* or more schemas, see the implementations of {@link SchemaDefinitions}.
*/
public abstract class IndexDefinition<K, V, I extends Index<K, V>> {
public interface IndexFactory<K, V, I extends Index<K, V>> {
I create(Schema<V> schema);
}
private final SchemaDefinitions<V> schemaDefs;
private final IndexCollection<K, V, I> indexCollection;
private final IndexFactory<K, V, I> indexFactory;
private final SiteIndexer<K, V, I> siteIndexer;
protected IndexDefinition(
SchemaDefinitions<V> schemaDefs,
IndexCollection<K, V, I> indexCollection,
IndexFactory<K, V, I> indexFactory,
SiteIndexer<K, V, I> siteIndexer) {
this.schemaDefs = schemaDefs;
this.indexCollection = indexCollection;
this.indexFactory = indexFactory;
this.siteIndexer = siteIndexer;
}
public final String getName() {
return schemaDefs.getName();
}
public final ImmutableSortedMap<Integer, Schema<V>> getSchemas() {
return schemaDefs.getSchemas();
}
public final Schema<V> getLatest() {
return schemaDefs.getLatest();
}
public final IndexCollection<K, V, I> getIndexCollection() {
return indexCollection;
}
public final IndexFactory<K, V, I> getIndexFactory() {
return indexFactory;
}
public final SiteIndexer<K, V, I> getSiteIndexer() {
return siteIndexer;
}
}

View File

@ -17,21 +17,31 @@ package com.google.gerrit.server.index;
import static com.google.gerrit.server.git.QueueProvider.QueueType.BATCH;
import static com.google.gerrit.server.git.QueueProvider.QueueType.INTERACTIVE;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexDefintion;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.index.change.IndexRewriter;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.Config;
import java.util.Collection;
import java.util.Set;
/**
* Module for non-indexer-specific secondary index setup.
* <p>
@ -43,6 +53,10 @@ public class IndexModule extends LifecycleModule {
LUCENE
}
public static final ImmutableCollection<SchemaDefinitions<?>> ALL_SCHEMA_DEFS =
ImmutableList.<SchemaDefinitions<?>> of(
ChangeSchemaDefinitions.INSTANCE);
/** Type of secondary index. */
public static IndexType getIndexType(Injector injector) {
Config cfg = injector.getInstance(
@ -74,6 +88,33 @@ public class IndexModule extends LifecycleModule {
factory(ChangeIndexer.Factory.class);
}
@Provides
Collection<IndexDefinition<?, ?, ?>> getIndexDefinitions(
ChangeIndexDefintion changes) {
Collection<IndexDefinition<?, ?, ?>> result =
ImmutableList.<IndexDefinition<?, ?, ?>> of(changes);
Set<String> expected = FluentIterable.from(ALL_SCHEMA_DEFS)
.transform(new Function<SchemaDefinitions<?>, String>() {
@Override
public String apply(SchemaDefinitions<?> in) {
return in.getName();
}
}).toSet();
Set<String> actual = FluentIterable.from(result)
.transform(new Function<IndexDefinition<?, ?, ?>, String>() {
@Override
public String apply(IndexDefinition<?, ?, ?> in) {
return in.getName();
}
}).toSet();
if (!expected.equals(actual)) {
throw new ProvisionException(
"need index definitions for all schemas: "
+ expected + " != " + actual);
}
return result;
}
@Provides
@Singleton
ChangeIndexer getChangeIndexer(

View File

@ -36,11 +36,10 @@ public class OnlineReindexer<K, V, I extends Index<K, V>> {
private final AtomicBoolean running = new AtomicBoolean();
public OnlineReindexer(
IndexCollection<K, V, I> indexes,
SiteIndexer<K, V, I> batchIndexer,
IndexDefinition<K, V, I> def,
int version) {
this.indexes = indexes;
this.batchIndexer = batchIndexer;
this.indexes = def.getIndexCollection();
this.batchIndexer = def.getSiteIndexer();
this.version = version;
}

View File

@ -0,0 +1,58 @@
// 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.index;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableSortedMap;
/**
* Definitions of the various schema versions over a given Gerrit data type.
* <p>
* A <em>schema</em> is a description of the fields that are indexed over the
* given data type. This class contains all the versions of a schema defined
* over its data type, exposed as a map of version number to schema definition.
* If you are interested in the classes responsible for backend-specific runtime
* implementations, see the implementations of {@link IndexDefinition}.
*/
public abstract class SchemaDefinitions<V> {
private final String name;
private final ImmutableSortedMap<Integer, Schema<V>> schemas;
protected SchemaDefinitions(String name, Class<V> valueClass) {
this.name = checkNotNull(name);
this.schemas = SchemaUtil.schemasFromClass(getClass(), valueClass);
}
public final String getName() {
return name;
}
public final ImmutableSortedMap<Integer, Schema<V>> getSchemas() {
return schemas;
}
public final Schema<V> get(int version) {
Schema<V> schema = schemas.get(version);
checkArgument(schema != null,
"Unrecognized %s schema version: %s", name, version);
return schema;
}
public final Schema<V> getLatest() {
return schemas.lastEntry().getValue();
}
}

View File

@ -19,8 +19,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@ -37,9 +37,9 @@ import java.util.Map;
import java.util.Set;
public class SchemaUtil {
public static <V> ImmutableMap<Integer, Schema<V>> schemasFromClass(
public static <V> ImmutableSortedMap<Integer, Schema<V>> schemasFromClass(
Class<?> schemasClass, Class<V> valueClass) {
Map<Integer, Schema<V>> schemas = Maps.newTreeMap();
Map<Integer, Schema<V>> schemas = Maps.newHashMap();
for (Field f : schemasClass.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())
&& Modifier.isFinal(f.getModifiers())
@ -65,7 +65,7 @@ public class SchemaUtil {
if (schemas.isEmpty()) {
throw new ExceptionInInitializerError("no ChangeSchemas found");
}
return ImmutableMap.copyOf(schemas);
return ImmutableSortedMap.copyOf(schemas);
}
public static <V> Schema<V> schema(Collection<FieldDef<V, ?>> fields) {

View File

@ -16,7 +16,11 @@ package com.google.gerrit.server.index.change;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.query.change.ChangeData;
public interface ChangeIndex extends Index<Change.Id, ChangeData> {
public interface Factory extends
IndexDefinition.IndexFactory<Change.Id, ChangeData, ChangeIndex> {
}
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2013 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.index.change;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
public class ChangeIndexDefintion
extends IndexDefinition<Change.Id, ChangeData, ChangeIndex> {
@Inject
ChangeIndexDefintion(
ChangeIndexCollection indexCollection,
ChangeIndex.Factory indexFactory,
AllChangesIndexer allChangesIndexer) {
super(ChangeSchemaDefinitions.INSTANCE, indexCollection, indexFactory,
allChangesIndexer);
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2013 The Android Open Source Project
// 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.
@ -14,17 +14,13 @@
package com.google.gerrit.server.index.change;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.server.index.SchemaUtil.schema;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.SchemaUtil;
import com.google.gerrit.server.index.SchemaDefinitions;
import com.google.gerrit.server.query.change.ChangeData;
/** Secondary index schemas for changes. */
public class ChangeSchemas {
public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> {
@Deprecated
static final Schema<ChangeData> V25 = schema(
ChangeField.LEGACY_ID,
@ -102,16 +98,10 @@ public class ChangeSchemas {
static final Schema<ChangeData> V27 = schema(V26.getFields().values());
public static final ImmutableMap<Integer, Schema<ChangeData>> ALL =
SchemaUtil.schemasFromClass(ChangeSchemas.class, ChangeData.class);
public static final ChangeSchemaDefinitions INSTANCE =
new ChangeSchemaDefinitions();
public static Schema<ChangeData> get(int version) {
Schema<ChangeData> schema = ALL.get(version);
checkArgument(schema != null, "Unrecognized schema version: %s", version);
return schema;
}
public static Schema<ChangeData> getLatest() {
return Iterables.getLast(ALL.values());
private ChangeSchemaDefinitions() {
super("changes", ChangeData.class);
}
}

View File

@ -14,7 +14,6 @@
package com.google.gerrit.testutil;
import static com.google.common.base.Preconditions.checkState;
import static com.google.inject.Scopes.SINGLETON;
import com.google.common.util.concurrent.MoreExecutors;
@ -49,7 +48,7 @@ import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.PerThreadRequestScope;
import com.google.gerrit.server.git.SendEmailExecutor;
import com.google.gerrit.server.index.IndexModule.IndexType;
import com.google.gerrit.server.index.change.ChangeSchemas;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.DiffExecutor;
@ -74,10 +73,12 @@ import com.google.inject.servlet.RequestScoped;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
public class InMemoryModule extends FactoryModule {
@ -97,8 +98,6 @@ public class InMemoryModule extends FactoryModule {
cfg.unset("cache", null, "directory");
cfg.setString("index", null, "type", "lucene");
cfg.setBoolean("index", "lucene", "testInmemory", true);
cfg.setInt("index", "lucene", "testVersion",
ChangeSchemas.getLatest().getVersion());
cfg.setInt("sendemail", null, "threadPoolSize", 0);
cfg.setBoolean("receive", null, "enableSignedPush", false);
cfg.setString("receive", null, "certNonceSeed", "sekret");
@ -234,16 +233,20 @@ public class InMemoryModule extends FactoryModule {
private Module luceneIndexModule() {
try {
Map<String, Integer> singleVersions = new HashMap<>();
int version = cfg.getInt("index", "lucene", "testVersion", -1);
checkState(ChangeSchemas.ALL.containsKey(version),
"invalid index.lucene.testVersion %s", version);
if (version > 0) {
singleVersions.put(ChangeSchemaDefinitions.INSTANCE.getName(), version);
}
Class<?> clazz =
Class.forName("com.google.gerrit.lucene.LuceneIndexModule");
Constructor<?> c = clazz.getConstructor(Integer.class, int.class);
return (Module) c.newInstance(version, 0);
Method m = clazz.getMethod(
"singleVersionWithExplicitVersions", Map.class, int.class);
return (Module) m.invoke(null, singleVersions, 0);
} catch (ClassNotFoundException | SecurityException | NoSuchMethodException
| IllegalArgumentException | InstantiationException
| IllegalAccessException | InvocationTargetException e) {
| IllegalArgumentException | IllegalAccessException
| InvocationTargetException e) {
e.printStackTrace();
ProvisionException pe = new ProvisionException(e.getMessage());
pe.initCause(e);
throw pe;

View File

@ -337,7 +337,7 @@ public class WebAppInitializer extends GuiceServletContextListener
private Module createIndexModule() {
switch (indexType) {
case LUCENE:
return new LuceneIndexModule();
return LuceneIndexModule.latestVersionWithOnlineUpgrade();
default:
throw new IllegalStateException("unsupported index.type = " + indexType);
}