Move general index classes from gerrit-server to gerrit-index

These classes do not depend on any Gerrit server functionality, and
could even be used to define an index without depending on the
gerrit-server package. This allows for a clearer separation of BUILD
rules; the QueryParser and antlr targets don't escape the gerrit-index
package.

The general layout thus far is to put index definition code in
com.google.gerrit.index, and query-related code (predicates, etc.)  in
com.google.gerrit.index.query.

The gerrit-index package is still of limited utility on its own, because
QueryProcessor and InternalQuery still live in the server package, and
untangling their dependencies will still be a bit more work.

Change-Id: I3c4616d08ecf19d5ccd1b9b91b3fd0b1fcedd901
This commit is contained in:
Dave Borowitz
2017-08-08 09:53:39 -04:00
parent 94f077b5d2
commit e47be68709
156 changed files with 424 additions and 363 deletions

View File

@@ -19,12 +19,12 @@ import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.change.ChangeTriplet;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData;

View File

@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
@@ -37,7 +38,6 @@ import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.InternalChangeQuery;

View File

@@ -26,6 +26,7 @@ import com.google.gerrit.extensions.common.GroupBaseInfo;
import com.google.gerrit.extensions.common.SuggestedReviewerInfo;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.MetricMaker;
@@ -42,7 +43,6 @@ import com.google.gerrit.server.change.SuggestReviewers;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.query.QueryResult;
import com.google.gerrit.server.query.account.AccountPredicates;
import com.google.gerrit.server.query.account.AccountQueryBuilder;
import com.google.gerrit.server.query.account.AccountQueryProcessor;

View File

@@ -22,13 +22,13 @@ import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
import com.google.gerrit.server.api.accounts.AccountInfoComparator;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryResult;
import com.google.gerrit.server.query.account.AccountPredicates;
import com.google.gerrit.server.query.account.AccountQueryBuilder;
import com.google.gerrit.server.query.account.AccountQueryProcessor;

View File

@@ -81,6 +81,7 @@ import com.google.gerrit.extensions.config.DownloadCommand;
import com.google.gerrit.extensions.config.DownloadScheme;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -117,7 +118,6 @@ import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.QueryResult;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeData.ChangedLines;
import com.google.gerrit.server.query.change.PluginDefinedAttributesFactory;

View File

@@ -24,10 +24,10 @@ import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.group.GroupIndex;
import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.query.QueryResult;
import com.google.gerrit.server.query.group.GroupQueryBuilder;
import com.google.gerrit.server.query.group.GroupQueryProcessor;
import com.google.gwtorm.server.OrmException;

View File

@@ -14,6 +14,9 @@
package com.google.gerrit.server.index;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.Schema;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.account.AccountIndex;

View File

@@ -1,148 +0,0 @@
// 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;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CharMatcher;
import com.google.gwtorm.server.OrmException;
import java.io.IOException;
import java.sql.Timestamp;
/**
* Definition of a field stored in the secondary index.
*
* @param <I> input type from which documents are created and search results are returned.
* @param <T> type that should be extracted from the input object when converting to an index
* document.
*/
public final class FieldDef<I, T> {
public static FieldDef.Builder<String> exact(String name) {
return new FieldDef.Builder<>(FieldType.EXACT, name);
}
public static FieldDef.Builder<String> fullText(String name) {
return new FieldDef.Builder<>(FieldType.FULL_TEXT, name);
}
public static FieldDef.Builder<Integer> intRange(String name) {
return new FieldDef.Builder<>(FieldType.INTEGER_RANGE, name).stored();
}
public static FieldDef.Builder<Integer> integer(String name) {
return new FieldDef.Builder<>(FieldType.INTEGER, name);
}
public static FieldDef.Builder<String> prefix(String name) {
return new FieldDef.Builder<>(FieldType.PREFIX, name);
}
public static FieldDef.Builder<byte[]> storedOnly(String name) {
return new FieldDef.Builder<>(FieldType.STORED_ONLY, name).stored();
}
public static FieldDef.Builder<Timestamp> timestamp(String name) {
return new FieldDef.Builder<>(FieldType.TIMESTAMP, name);
}
@FunctionalInterface
public interface Getter<I, T> {
T get(I input) throws OrmException, IOException;
}
public static class Builder<T> {
private final FieldType<T> type;
private final String name;
private boolean stored;
public Builder(FieldType<T> type, String name) {
this.type = checkNotNull(type);
this.name = checkNotNull(name);
}
public Builder<T> stored() {
this.stored = true;
return this;
}
public <I> FieldDef<I, T> build(Getter<I, T> getter) {
return new FieldDef<>(name, type, stored, false, getter);
}
public <I> FieldDef<I, Iterable<T>> buildRepeatable(Getter<I, Iterable<T>> getter) {
return new FieldDef<>(name, type, stored, true, getter);
}
}
private final String name;
private final FieldType<?> type;
private final boolean stored;
private final boolean repeatable;
private final Getter<I, T> getter;
private FieldDef(
String name, FieldType<?> type, boolean stored, boolean repeatable, Getter<I, T> getter) {
checkArgument(
!(repeatable && type == FieldType.INTEGER_RANGE),
"Range queries against repeated fields are unsupported");
this.name = checkName(name);
this.type = checkNotNull(type);
this.stored = stored;
this.repeatable = repeatable;
this.getter = checkNotNull(getter);
}
private static String checkName(String name) {
CharMatcher m = CharMatcher.anyOf("abcdefghijklmnopqrstuvwxyz0123456789_");
checkArgument(name != null && m.matchesAllOf(name), "illegal field name: %s", name);
return name;
}
/** @return name of the field. */
public String getName() {
return name;
}
/** @return type of the field; for repeatable fields, the inner type, not the iterable type. */
public FieldType<?> getType() {
return type;
}
/** @return whether the field should be stored in the index. */
public boolean isStored() {
return stored;
}
/**
* Get the field contents from the input object.
*
* @param input input object.
* @return the field value(s) to index.
* @throws OrmException
*/
public T get(I input) throws OrmException {
try {
return getter.get(input);
} catch (IOException e) {
throw new OrmException(e);
}
}
/** @return whether the field is repeatable. */
public boolean isRepeatable() {
return repeatable;
}
}

View File

@@ -1,63 +0,0 @@
// 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;
import java.sql.Timestamp;
/** Document field types supported by the secondary index system. */
public class FieldType<T> {
/** A single integer-valued field. */
public static final FieldType<Integer> INTEGER = new FieldType<>("INTEGER");
/** A single-integer-valued field matched using range queries. */
public static final FieldType<Integer> INTEGER_RANGE = new FieldType<>("INTEGER_RANGE");
/** A single integer-valued field. */
public static final FieldType<Long> LONG = new FieldType<>("LONG");
/** A single date/time-valued field. */
public static final FieldType<Timestamp> TIMESTAMP = new FieldType<>("TIMESTAMP");
/** A string field searched using exact-match semantics. */
public static final FieldType<String> EXACT = new FieldType<>("EXACT");
/** A string field searched using prefix. */
public static final FieldType<String> PREFIX = new FieldType<>("PREFIX");
/** A string field searched using fuzzy-match semantics. */
public static final FieldType<String> FULL_TEXT = new FieldType<>("FULL_TEXT");
/** A field that is only stored as raw bytes and cannot be queried. */
public static final FieldType<byte[]> STORED_ONLY = new FieldType<>("STORED_ONLY");
private final String name;
private FieldType(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
public static IllegalArgumentException badFieldType(FieldType<?> t) {
return new IllegalArgumentException("unknown index field type " + t);
}
}

View File

@@ -1,132 +0,0 @@
// 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;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.query.DataSource;
import com.google.gerrit.server.query.Predicate;
import com.google.gwtorm.server.OrmException;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
/**
* Secondary index implementation for arbitrary documents.
*
* <p>Documents are inserted into the index and are queried by converting special {@link
* com.google.gerrit.server.query.Predicate} instances into index-aware predicates that use the
* index search results as a source.
*
* <p>Implementations must be thread-safe and should batch inserts/updates where appropriate.
*/
public interface Index<K, V> {
/** @return the schema version used by this index. */
Schema<V> getSchema();
/** Stop and await termination of all executor threads */
default void stop() {}
/** Close this index. */
void close();
/**
* Update a document in the index.
*
* <p>Semantically equivalent to deleting the document and reinserting it with new field values. A
* document that does not already exist is created. Results may not be immediately visible to
* searchers, but should be visible within a reasonable amount of time.
*
* @param obj document object
* @throws IOException
*/
void replace(V obj) throws IOException;
/**
* Delete a document from the index by key.
*
* @param key document key
* @throws IOException
*/
void delete(K key) throws IOException;
/**
* Delete all documents from the index.
*
* @throws IOException
*/
void deleteAll() throws IOException;
/**
* Convert the given operator predicate into a source searching the index and returning only the
* documents matching that predicate.
*
* <p>This method may be called multiple times for variations on the same predicate or multiple
* predicate subtrees in the course of processing a single query, so it should not have any side
* effects (e.g. starting a search in the background).
*
* @param p the predicate to match. Must be a tree containing only AND, OR, or NOT predicates as
* internal nodes, and {@link IndexPredicate}s as leaves.
* @param opts query options not implied by the predicate, such as start and limit.
* @return a source of documents matching the predicate, returned in a defined order depending on
* the type of documents.
* @throws QueryParseException if the predicate could not be converted to an indexed data source.
*/
DataSource<V> getSource(Predicate<V> p, QueryOptions opts) throws QueryParseException;
/**
* Get a single document from the index.
*
* @param key document key.
* @param opts query options. Options that do not make sense in the context of a single document,
* such as start, will be ignored.
* @return a single document if present.
* @throws IOException
*/
default Optional<V> get(K key, QueryOptions opts) throws IOException {
opts = opts.withStart(0).withLimit(2);
List<V> results;
try {
results = getSource(keyPredicate(key), opts).read().toList();
} catch (QueryParseException e) {
throw new IOException("Unexpected QueryParseException during get()", e);
} catch (OrmException e) {
throw new IOException(e);
}
switch (results.size()) {
case 0:
return Optional.empty();
case 1:
return Optional.of(results.get(0));
default:
throw new IOException("Multiple results found in index for key " + key + ": " + results);
}
}
/**
* Get a predicate that looks up a single document by key.
*
* @param key document key.
* @return a single predicate.
*/
Predicate<V> keyPredicate(K key);
/**
* Mark whether this index is up-to-date and ready to serve reads.
*
* @param ready whether the index is ready
* @throws IOException
*/
void markReady(boolean ready) throws IOException;
}

View File

@@ -1,103 +0,0 @@
// 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;
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.events.LifecycleListener;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
/** Dynamic pointers to the index versions used for searching and writing. */
public abstract class IndexCollection<K, V, I extends Index<K, V>> implements LifecycleListener {
private final CopyOnWriteArrayList<I> writeIndexes;
private final AtomicReference<I> searchIndex;
protected IndexCollection() {
this.writeIndexes = Lists.newCopyOnWriteArrayList();
this.searchIndex = new AtomicReference<>();
}
/** @return the current search index version. */
public I getSearchIndex() {
return searchIndex.get();
}
public void setSearchIndex(I index) {
I old = searchIndex.getAndSet(index);
if (old != null && old != index && !writeIndexes.contains(old)) {
old.close();
}
}
public Collection<I> getWriteIndexes() {
return Collections.unmodifiableCollection(writeIndexes);
}
public synchronized I addWriteIndex(I index) {
int version = index.getSchema().getVersion();
for (int i = 0; i < writeIndexes.size(); i++) {
if (writeIndexes.get(i).getSchema().getVersion() == version) {
return writeIndexes.set(i, index);
}
}
writeIndexes.add(index);
return null;
}
public synchronized void removeWriteIndex(int version) {
int removeIndex = -1;
for (int i = 0; i < writeIndexes.size(); i++) {
if (writeIndexes.get(i).getSchema().getVersion() == version) {
removeIndex = i;
break;
}
}
if (removeIndex >= 0) {
try {
writeIndexes.get(removeIndex).close();
} finally {
writeIndexes.remove(removeIndex);
}
}
}
public I getWriteIndex(int version) {
for (I i : writeIndexes) {
if (i.getSchema().getVersion() == version) {
return i;
}
}
return null;
}
@Override
public void start() {}
@Override
public void stop() {
I read = searchIndex.get();
if (read != null) {
read.close();
}
for (I write : writeIndexes) {
if (write != read) {
write.stop();
write.close();
}
}
}
}

View File

@@ -1,112 +0,0 @@
// Copyright (C) 2015 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 com.google.auto.value.AutoValue;
import java.util.function.IntConsumer;
import org.eclipse.jgit.lib.Config;
/**
* Implementation-specific configuration for secondary indexes.
*
* <p>Contains configuration that is tied to a specific index implementation but is otherwise
* global, i.e. not tied to a specific {@link Index} and schema version.
*/
@AutoValue
public abstract class IndexConfig {
private static final int DEFAULT_MAX_TERMS = 1024;
public static IndexConfig createDefault() {
return builder().build();
}
public static Builder fromConfig(Config cfg) {
Builder b = builder();
setIfPresent(cfg, "maxLimit", b::maxLimit);
setIfPresent(cfg, "maxPages", b::maxPages);
setIfPresent(cfg, "maxTerms", b::maxTerms);
return b;
}
private static void setIfPresent(Config cfg, String name, IntConsumer setter) {
int n = cfg.getInt("index", null, name, 0);
if (n != 0) {
setter.accept(n);
}
}
public static Builder builder() {
return new AutoValue_IndexConfig.Builder()
.maxLimit(Integer.MAX_VALUE)
.maxPages(Integer.MAX_VALUE)
.maxTerms(DEFAULT_MAX_TERMS)
.separateChangeSubIndexes(false);
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder maxLimit(int maxLimit);
abstract int maxLimit();
public abstract Builder maxPages(int maxPages);
abstract int maxPages();
public abstract Builder maxTerms(int maxTerms);
abstract int maxTerms();
public abstract Builder separateChangeSubIndexes(boolean separate);
abstract IndexConfig autoBuild();
public IndexConfig build() {
IndexConfig cfg = autoBuild();
checkLimit(cfg.maxLimit(), "maxLimit");
checkLimit(cfg.maxPages(), "maxPages");
checkLimit(cfg.maxTerms(), "maxTerms");
return cfg;
}
}
private static void checkLimit(int limit, String name) {
checkArgument(limit > 0, "%s must be positive: %s", name, limit);
}
/**
* @return maximum limit supported by the underlying index, or limited for performance reasons.
*/
public abstract int maxLimit();
/**
* @return maximum number of pages (limit / start) supported by the underlying index, or limited
* for performance reasons.
*/
public abstract int maxPages();
/**
* @return maximum number of total index query terms supported by the underlying index, or limited
* for performance reasons.
*/
public abstract int maxTerms();
/**
* @return whether different subsets of changes may be stored in different physical sub-indexes.
*/
public abstract boolean separateChangeSubIndexes();
}

View File

@@ -1,73 +0,0 @@
// 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;
import com.google.gerrit.common.Nullable;
/**
* 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,
@Nullable 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;
}
@Nullable
public final SiteIndexer<K, V, I> getSiteIndexer() {
return siteIndexer;
}
}

View File

@@ -23,6 +23,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.SchemaDefinitions;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.WorkQueue;

View File

@@ -1,40 +0,0 @@
// 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;
import com.google.gerrit.server.query.OperatorPredicate;
/** Index-aware predicate that includes a field type annotation. */
public abstract class IndexPredicate<I> extends OperatorPredicate<I> {
private final FieldDef<I, ?> def;
protected IndexPredicate(FieldDef<I, ?> def, String value) {
super(def.getName(), value);
this.def = def;
}
protected IndexPredicate(FieldDef<I, ?> def, String name, String value) {
super(name, value);
this.def = def;
}
public FieldDef<I, ?> getField() {
return def;
}
public FieldType<?> getType() {
return def.getType();
}
}

View File

@@ -1,23 +0,0 @@
// 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.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.query.Predicate;
public interface IndexRewriter<T> {
Predicate<T> rewrite(Predicate<T> in, QueryOptions opts) throws QueryParseException;
}

View File

@@ -21,6 +21,7 @@ import static com.google.gerrit.server.index.change.ChangeField.PROJECT;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.index.account.AccountField;

View File

@@ -1,126 +0,0 @@
// 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.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.query.DataSource;
import com.google.gerrit.server.query.Paginated;
import com.google.gerrit.server.query.Predicate;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import java.util.Collection;
import java.util.List;
/**
* Wrapper combining an {@link IndexPredicate} together with a {@link DataSource} that returns
* matching results from the index.
*
* <p>Appropriate to return as the rootmost predicate that can be processed using the secondary
* index; such predicates must also implement {@link DataSource} to be chosen by the query
* processor.
*
* @param <I> The type of the IDs by which the entities are stored in the index.
* @param <T> The type of the entities that are stored in the index.
*/
public class IndexedQuery<I, T> extends Predicate<T> implements DataSource<T>, Paginated<T> {
protected final Index<I, T> index;
private QueryOptions opts;
private final Predicate<T> pred;
protected DataSource<T> source;
public IndexedQuery(Index<I, T> index, Predicate<T> pred, QueryOptions opts)
throws QueryParseException {
this.index = index;
this.opts = opts;
this.pred = pred;
this.source = index.getSource(pred, this.opts);
}
@Override
public int getChildCount() {
return 1;
}
@Override
public Predicate<T> getChild(int i) {
if (i == 0) {
return pred;
}
throw new ArrayIndexOutOfBoundsException(i);
}
@Override
public List<Predicate<T>> getChildren() {
return ImmutableList.of(pred);
}
@Override
public QueryOptions getOptions() {
return opts;
}
@Override
public int getCardinality() {
return source != null ? source.getCardinality() : opts.limit();
}
@Override
public ResultSet<T> read() throws OrmException {
return source.read();
}
@Override
public ResultSet<T> restart(int start) throws OrmException {
opts = opts.withStart(start);
try {
source = index.getSource(pred, opts);
} catch (QueryParseException e) {
// Don't need to show this exception to the user; the only thing that
// changed about pred was its start, and any other QPEs that might happen
// should have already thrown from the constructor.
throw new OrmException(e);
}
// Don't convert start to a limit, since the caller of this method (see
// AndSource) has calculated the actual number to skip.
return read();
}
@Override
public Predicate<T> copy(Collection<? extends Predicate<T>> children) {
return this;
}
@Override
public int hashCode() {
return pred.hashCode();
}
@Override
public boolean equals(Object other) {
if (other == null || getClass() != other.getClass()) {
return false;
}
IndexedQuery<?, ?> o = (IndexedQuery<?, ?>) other;
return pred.equals(o.pred) && opts.equals(o.opts);
}
@Override
public String toString() {
return MoreObjects.toStringHelper("index").add("p", pred).add("opts", opts).toString();
}
}

View File

@@ -1,52 +0,0 @@
// Copyright (C) 2014 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.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.index.RangeUtil.Range;
import com.google.gwtorm.server.OrmException;
public abstract class IntegerRangePredicate<T> extends IndexPredicate<T> {
private final Range range;
protected IntegerRangePredicate(FieldDef<T, Integer> type, String value)
throws QueryParseException {
super(type, value);
range = RangeUtil.getRange(value, Integer.MIN_VALUE, Integer.MAX_VALUE);
if (range == null) {
throw new QueryParseException("Invalid range predicate: " + value);
}
}
protected abstract Integer getValueInt(T object) throws OrmException;
public boolean match(T object) throws OrmException {
Integer valueInt = getValueInt(object);
if (valueInt == null) {
return false;
}
return valueInt >= range.min && valueInt <= range.max;
}
/** Return the minimum value of this predicate's range, inclusive. */
public int getMinimumValue() {
return range.min;
}
/** Return the maximum value of this predicate's range, inclusive. */
public int getMaximumValue() {
return range.max;
}
}

View File

@@ -18,6 +18,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.SiteIndexer;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

View File

@@ -1,56 +0,0 @@
// Copyright (C) 2015 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 com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import java.util.Set;
@AutoValue
public abstract class QueryOptions {
public static QueryOptions create(IndexConfig config, int start, int limit, Set<String> fields) {
checkArgument(start >= 0, "start must be nonnegative: %s", start);
checkArgument(limit > 0, "limit must be positive: %s", limit);
return new AutoValue_QueryOptions(config, start, limit, ImmutableSet.copyOf(fields));
}
public QueryOptions convertForBackend() {
// Increase the limit rather than skipping, since we don't know how many
// skipped results would have been filtered out by the enclosing AndSource.
int backendLimit = config().maxLimit();
int limit = Ints.saturatedCast((long) limit() + start());
limit = Math.min(limit, backendLimit);
return create(config(), 0, limit, fields());
}
public abstract IndexConfig config();
public abstract int start();
public abstract int limit();
public abstract ImmutableSet<String> fields();
public QueryOptions withLimit(int newLimit) {
return create(config(), start(), newLimit, fields());
}
public QueryOptions withStart(int newStart) {
return create(config(), newStart, limit(), fields());
}
}

View File

@@ -1,118 +0,0 @@
// Copyright (C) 2014 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.primitives.Ints;
import com.google.gerrit.common.Nullable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class RangeUtil {
private static final Pattern RANGE_PATTERN = Pattern.compile("(>|>=|=|<|<=|)([+-]?\\d+)$");
private RangeUtil() {}
public static class Range {
/** The prefix of the query, before the range component. */
public final String prefix;
/** The minimum value specified in the query, inclusive. */
public final int min;
/** The maximum value specified in the query, inclusive. */
public final int max;
public Range(String prefix, int min, int max) {
this.prefix = prefix;
this.min = min;
this.max = max;
}
}
/**
* Determine the range of values being requested in the given query.
*
* @param rangeQuery the raw query, e.g. "{@code added:>12345}"
* @param minValue the minimum possible value for the field, inclusive
* @param maxValue the maximum possible value for the field, inclusive
* @return the calculated {@link Range}, or null if the query is invalid
*/
@Nullable
public static Range getRange(String rangeQuery, int minValue, int maxValue) {
Matcher m = RANGE_PATTERN.matcher(rangeQuery);
String prefix;
String test;
Integer queryInt;
if (m.find()) {
prefix = rangeQuery.substring(0, m.start());
test = m.group(1);
queryInt = value(m.group(2));
if (queryInt == null) {
return null;
}
} else {
return null;
}
return getRange(prefix, test, queryInt, minValue, maxValue);
}
/**
* Determine the range of values being requested in the given query.
*
* @param prefix a prefix string which is copied into the range
* @param test the test operator, one of &gt;, &gt;=, =, &lt;, or &lt;=
* @param queryInt the integer being queried
* @param minValue the minimum possible value for the field, inclusive
* @param maxValue the maximum possible value for the field, inclusive
* @return the calculated {@link Range}
*/
public static Range getRange(
String prefix, String test, int queryInt, int minValue, int maxValue) {
int min;
int max;
switch (test) {
case "=":
default:
min = max = queryInt;
break;
case ">":
min = Ints.saturatedCast(queryInt + 1L);
max = maxValue;
break;
case ">=":
min = queryInt;
max = maxValue;
break;
case "<":
min = minValue;
max = Ints.saturatedCast(queryInt - 1L);
break;
case "<=":
min = minValue;
max = queryInt;
break;
}
return new Range(prefix, min, max);
}
private static Integer value(String value) {
if (value.startsWith("+")) {
value = value.substring(1);
}
return Ints.tryParse(value);
}
}

View File

@@ -1,25 +0,0 @@
// 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;
public abstract class RegexPredicate<I> extends IndexPredicate<I> {
protected RegexPredicate(FieldDef<I, ?> def, String value) {
super(def, value);
}
protected RegexPredicate(FieldDef<I, ?> def, String name, String value) {
super(def, name, value);
}
}

View File

@@ -1,210 +0,0 @@
// 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;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gwtorm.server.OrmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Specific version of a secondary index schema. */
public class Schema<T> {
public static class Builder<T> {
private final List<FieldDef<T, ?>> fields = new ArrayList<>();
public Builder<T> add(Schema<T> schema) {
this.fields.addAll(schema.getFields().values());
return this;
}
@SafeVarargs
public final Builder<T> add(FieldDef<T, ?>... fields) {
this.fields.addAll(Arrays.asList(fields));
return this;
}
@SafeVarargs
public final Builder<T> remove(FieldDef<T, ?>... fields) {
this.fields.removeAll(Arrays.asList(fields));
return this;
}
public Schema<T> build() {
return new Schema<>(ImmutableList.copyOf(fields));
}
}
private static final Logger log = LoggerFactory.getLogger(Schema.class);
public static class Values<T> {
private final FieldDef<T, ?> field;
private final Iterable<?> values;
private Values(FieldDef<T, ?> field, Iterable<?> values) {
this.field = field;
this.values = values;
}
public FieldDef<T, ?> getField() {
return field;
}
public Iterable<?> getValues() {
return values;
}
}
private static <T> FieldDef<T, ?> checkSame(FieldDef<T, ?> f1, FieldDef<T, ?> f2) {
checkState(f1 == f2, "Mismatched %s fields: %s != %s", f1.getName(), f1, f2);
return f1;
}
private final ImmutableMap<String, FieldDef<T, ?>> fields;
private final ImmutableMap<String, FieldDef<T, ?>> storedFields;
private int version;
public Schema(Iterable<FieldDef<T, ?>> fields) {
this(0, fields);
}
public Schema(int version, Iterable<FieldDef<T, ?>> fields) {
this.version = version;
ImmutableMap.Builder<String, FieldDef<T, ?>> b = ImmutableMap.builder();
ImmutableMap.Builder<String, FieldDef<T, ?>> sb = ImmutableMap.builder();
for (FieldDef<T, ?> f : fields) {
b.put(f.getName(), f);
if (f.isStored()) {
sb.put(f.getName(), f);
}
}
this.fields = b.build();
this.storedFields = sb.build();
}
public final int getVersion() {
return version;
}
/**
* Get all fields in this schema.
*
* <p>This is primarily useful for iteration. Most callers should prefer one of the helper methods
* {@link #getField(FieldDef, FieldDef...)} or {@link #hasField(FieldDef)} to looking up fields by
* name
*
* @return all fields in this schema indexed by name.
*/
public final ImmutableMap<String, FieldDef<T, ?>> getFields() {
return fields;
}
/** @return all fields in this schema where {@link FieldDef#isStored()} is true. */
public final ImmutableMap<String, FieldDef<T, ?>> getStoredFields() {
return storedFields;
}
/**
* Look up fields in this schema.
*
* @param first the preferred field to look up.
* @param rest additional fields to look up.
* @return the first field in the schema matching {@code first} or {@code rest}, in order, or
* absent if no field matches.
*/
@SafeVarargs
public final Optional<FieldDef<T, ?>> getField(FieldDef<T, ?> first, FieldDef<T, ?>... rest) {
FieldDef<T, ?> field = fields.get(first.getName());
if (field != null) {
return Optional.of(checkSame(field, first));
}
for (FieldDef<T, ?> f : rest) {
field = fields.get(f.getName());
if (field != null) {
return Optional.of(checkSame(field, f));
}
}
return Optional.empty();
}
/**
* Check whether a field is present in this schema.
*
* @param field field to look up.
* @return whether the field is present.
*/
public final boolean hasField(FieldDef<T, ?> field) {
FieldDef<T, ?> f = fields.get(field.getName());
if (f == null) {
return false;
}
checkSame(f, field);
return true;
}
/**
* Build all fields in the schema from an input object.
*
* <p>Null values are omitted, as are fields which cause errors, which are logged.
*
* @param obj input object.
* @return all non-null field values from the object.
*/
public final Iterable<Values<T>> buildFields(T obj) {
return FluentIterable.from(fields.values())
.transform(
new Function<FieldDef<T, ?>, Values<T>>() {
@Override
public Values<T> apply(FieldDef<T, ?> f) {
Object v;
try {
v = f.get(obj);
} catch (OrmException e) {
log.error(String.format("error getting field %s of %s", f.getName(), obj), e);
return null;
}
if (v == null) {
return null;
} else if (f.isRepeatable()) {
return new Values<>(f, (Iterable<?>) v);
} else {
return new Values<>(f, Collections.singleton(v));
}
}
})
.filter(Predicates.notNull());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).addValue(fields.keySet()).toString();
}
public void setVersion(int version) {
this.version = version;
}
}

View File

@@ -1,66 +0,0 @@
// 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;
import com.google.common.collect.Iterables;
import com.google.gerrit.common.Nullable;
/**
* 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();
}
@Nullable
public final Schema<V> getPrevious() {
if (schemas.size() <= 1) {
return null;
}
return Iterables.get(schemas.descendingMap().values(), 1);
}
}

View File

@@ -1,118 +0,0 @@
// 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 com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.PersonIdent;
public class SchemaUtil {
public static <V> ImmutableSortedMap<Integer, Schema<V>> schemasFromClass(
Class<?> schemasClass, Class<V> valueClass) {
Map<Integer, Schema<V>> schemas = new HashMap<>();
for (Field f : schemasClass.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())
&& Modifier.isFinal(f.getModifiers())
&& Schema.class.isAssignableFrom(f.getType())) {
ParameterizedType t = (ParameterizedType) f.getGenericType();
if (t.getActualTypeArguments()[0] == valueClass) {
try {
f.setAccessible(true);
@SuppressWarnings("unchecked")
Schema<V> schema = (Schema<V>) f.get(null);
checkArgument(f.getName().startsWith("V"));
schema.setVersion(Integer.parseInt(f.getName().substring(1)));
schemas.put(schema.getVersion(), schema);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
} else {
throw new IllegalArgumentException(
"non-" + schemasClass.getSimpleName() + " schema: " + f);
}
}
}
if (schemas.isEmpty()) {
throw new ExceptionInInitializerError("no ChangeSchemas found");
}
return ImmutableSortedMap.copyOf(schemas);
}
public static <V> Schema<V> schema(Collection<FieldDef<V, ?>> fields) {
return new Schema<>(ImmutableList.copyOf(fields));
}
@SafeVarargs
public static <V> Schema<V> schema(Schema<V> schema, FieldDef<V, ?>... moreFields) {
return new Schema<>(
new ImmutableList.Builder<FieldDef<V, ?>>()
.addAll(schema.getFields().values())
.addAll(ImmutableList.copyOf(moreFields))
.build());
}
@SafeVarargs
public static <V> Schema<V> schema(FieldDef<V, ?>... fields) {
return schema(ImmutableList.copyOf(fields));
}
public static Set<String> getPersonParts(PersonIdent person) {
if (person == null) {
return ImmutableSet.of();
}
return getNameParts(person.getName(), Collections.singleton(person.getEmailAddress()));
}
public static Set<String> getNameParts(String name) {
return getNameParts(name, Collections.emptySet());
}
public static Set<String> getNameParts(String name, Iterable<String> emails) {
Splitter at = Splitter.on('@');
Splitter s = Splitter.on(CharMatcher.anyOf("@.- /_")).omitEmptyStrings();
HashSet<String> parts = new HashSet<>();
for (String email : emails) {
if (email == null) {
continue;
}
String lowerEmail = email.toLowerCase(Locale.US);
parts.add(lowerEmail);
Iterables.addAll(parts, at.split(lowerEmail));
Iterables.addAll(parts, s.split(lowerEmail));
}
if (name != null) {
Iterables.addAll(parts, s.split(name.toLowerCase(Locale.US)));
}
return parts;
}
private SchemaUtil() {}
}

View File

@@ -16,6 +16,9 @@ package com.google.gerrit.server.index;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.Schema;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;

View File

@@ -1,145 +0,0 @@
// 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.checkNotNull;
import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.util.io.NullOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class SiteIndexer<K, V, I extends Index<K, V>> {
private static final Logger log = LoggerFactory.getLogger(SiteIndexer.class);
public static class Result {
private final long elapsedNanos;
private final boolean success;
private final int done;
private final int failed;
public Result(Stopwatch sw, boolean success, int done, int failed) {
this.elapsedNanos = sw.elapsed(TimeUnit.NANOSECONDS);
this.success = success;
this.done = done;
this.failed = failed;
}
public boolean success() {
return success;
}
public int doneCount() {
return done;
}
public int failedCount() {
return failed;
}
public long elapsed(TimeUnit timeUnit) {
return timeUnit.convert(elapsedNanos, TimeUnit.NANOSECONDS);
}
}
protected int totalWork = -1;
protected OutputStream progressOut = NullOutputStream.INSTANCE;
protected PrintWriter verboseWriter = new PrintWriter(NullOutputStream.INSTANCE);
public void setTotalWork(int num) {
totalWork = num;
}
public void setProgressOut(OutputStream out) {
progressOut = checkNotNull(out);
}
public void setVerboseOut(OutputStream out) {
verboseWriter = new PrintWriter(checkNotNull(out));
}
public abstract Result indexAll(I index);
protected final void addErrorListener(
ListenableFuture<?> future, String desc, ProgressMonitor progress, AtomicBoolean ok) {
future.addListener(
new ErrorListener(future, desc, progress, ok), MoreExecutors.directExecutor());
}
private static class ErrorListener implements Runnable {
private final ListenableFuture<?> future;
private final String desc;
private final ProgressMonitor progress;
private final AtomicBoolean ok;
private ErrorListener(
ListenableFuture<?> future, String desc, ProgressMonitor progress, AtomicBoolean ok) {
this.future = future;
this.desc = desc;
this.progress = progress;
this.ok = ok;
}
@Override
public void run() {
try {
future.get();
} catch (RejectedExecutionException e) {
// Server shutdown, don't spam the logs.
failSilently();
} catch (ExecutionException | InterruptedException e) {
fail(e);
} catch (RuntimeException e) {
failAndThrow(e);
} catch (Error e) {
// Can't join with RuntimeException because "RuntimeException |
// Error" becomes Throwable, which messes with signatures.
failAndThrow(e);
} finally {
synchronized (progress) {
progress.update(1);
}
}
}
private void failSilently() {
ok.set(false);
}
private void fail(Throwable t) {
log.error("Failed to index " + desc, t);
ok.set(false);
}
private void failAndThrow(RuntimeException e) {
fail(e);
throw e;
}
private void failAndThrow(Error e) {
fail(e);
throw e;
}
}
}

View File

@@ -1,40 +0,0 @@
// 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;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gwtjsonrpc.common.JavaSqlTimestampHelper;
import java.sql.Timestamp;
import java.util.Date;
// TODO: Migrate this to IntegerRangePredicate
public abstract class TimestampRangePredicate<I> extends IndexPredicate<I> {
protected static Timestamp parse(String value) throws QueryParseException {
try {
return JavaSqlTimestampHelper.parseTimestamp(value);
} catch (IllegalArgumentException e) {
// parseTimestamp's errors are specific and helpful, so preserve them.
throw new QueryParseException(e.getMessage(), e);
}
}
protected TimestampRangePredicate(FieldDef<I, Timestamp> def, String name, String value) {
super(def, name, value);
}
public abstract Date getMinTimestamp();
public abstract Date getMaxTimestamp();
}

View File

@@ -22,8 +22,12 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.IndexDefinition.IndexFactory;
import com.google.gerrit.index.Schema;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.index.IndexDefinition.IndexFactory;
import com.google.inject.ProvisionException;
import java.io.IOException;
import java.util.Collection;

View File

@@ -14,19 +14,19 @@
package com.google.gerrit.server.index.account;
import static com.google.gerrit.server.index.FieldDef.exact;
import static com.google.gerrit.server.index.FieldDef.integer;
import static com.google.gerrit.server.index.FieldDef.prefix;
import static com.google.gerrit.server.index.FieldDef.timestamp;
import static com.google.gerrit.index.FieldDef.exact;
import static com.google.gerrit.index.FieldDef.integer;
import static com.google.gerrit.index.FieldDef.prefix;
import static com.google.gerrit.index.FieldDef.timestamp;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.SchemaUtil;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.SchemaUtil;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.Locale;

View File

@@ -14,11 +14,11 @@
package com.google.gerrit.server.index.account;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.account.AccountPredicates;
public interface AccountIndex extends Index<Account.Id, AccountState> {

View File

@@ -15,9 +15,9 @@
package com.google.gerrit.server.index.account;
import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.IndexCollection;
import com.google.inject.Inject;
import com.google.inject.Singleton;

View File

@@ -15,9 +15,9 @@
package com.google.gerrit.server.index.account;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.inject.Inject;
public class AccountIndexDefinition

View File

@@ -16,11 +16,11 @@ package com.google.gerrit.server.index.account;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.gerrit.index.IndexRewriter;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.IndexRewriter;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.query.Predicate;
import com.google.inject.Inject;
import com.google.inject.Singleton;

View File

@@ -18,10 +18,10 @@ import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.events.AccountIndexedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.Index;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.Index;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;

View File

@@ -14,11 +14,11 @@
package com.google.gerrit.server.index.account;
import static com.google.gerrit.server.index.SchemaUtil.schema;
import static com.google.gerrit.index.SchemaUtil.schema;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.SchemaDefinitions;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.SchemaDefinitions;
public class AccountSchemaDefinitions extends SchemaDefinitions<AccountState> {
@Deprecated

View File

@@ -20,12 +20,12 @@ import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.index.SiteIndexer;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.Accounts;
import com.google.gerrit.server.index.IndexExecutor;
import com.google.gerrit.server.index.SiteIndexer;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;

View File

@@ -14,14 +14,14 @@
package com.google.gerrit.server.index.account;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexedQuery;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexedQuery;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.query.DataSource;
import com.google.gerrit.server.query.Predicate;
public class IndexedAccountQuery extends IndexedQuery<Account.Id, AccountState>
implements DataSource<AccountState> {

View File

@@ -28,6 +28,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.MultimapBuilder;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.index.SiteIndexer;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -36,7 +37,6 @@ import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.MultiProgressMonitor.Task;
import com.google.gerrit.server.index.IndexExecutor;
import com.google.gerrit.server.index.SiteIndexer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.change.ChangeData;

View File

@@ -16,13 +16,13 @@ package com.google.gerrit.server.index.change;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.server.index.FieldDef.exact;
import static com.google.gerrit.server.index.FieldDef.fullText;
import static com.google.gerrit.server.index.FieldDef.intRange;
import static com.google.gerrit.server.index.FieldDef.integer;
import static com.google.gerrit.server.index.FieldDef.prefix;
import static com.google.gerrit.server.index.FieldDef.storedOnly;
import static com.google.gerrit.server.index.FieldDef.timestamp;
import static com.google.gerrit.index.FieldDef.exact;
import static com.google.gerrit.index.FieldDef.fullText;
import static com.google.gerrit.index.FieldDef.intRange;
import static com.google.gerrit.index.FieldDef.integer;
import static com.google.gerrit.index.FieldDef.prefix;
import static com.google.gerrit.index.FieldDef.storedOnly;
import static com.google.gerrit.index.FieldDef.timestamp;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
@@ -36,6 +36,8 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.SchemaUtil;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -48,8 +50,6 @@ import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.StarredChangesUtil;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.SchemaUtil;
import com.google.gerrit.server.index.change.StalenessChecker.RefState;
import com.google.gerrit.server.index.change.StalenessChecker.RefStatePattern;
import com.google.gerrit.server.mail.Address;

View File

@@ -14,10 +14,10 @@
package com.google.gerrit.server.index.change;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.query.Predicate;
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.Predicate;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.LegacyChangeIdPredicate;

View File

@@ -15,8 +15,8 @@
package com.google.gerrit.server.index.change;
import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
import com.google.inject.Singleton;

View File

@@ -15,8 +15,8 @@
package com.google.gerrit.server.index.change;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.index.IndexDefinition;
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;

View File

@@ -18,20 +18,20 @@ import static com.google.gerrit.server.query.change.ChangeStatusPredicate.open;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.IndexRewriter;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.query.AndPredicate;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.LimitPredicate;
import com.google.gerrit.index.query.NotPredicate;
import com.google.gerrit.index.query.OrPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.index.IndexRewriter;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.query.AndPredicate;
import com.google.gerrit.server.query.LimitPredicate;
import com.google.gerrit.server.query.NotPredicate;
import com.google.gerrit.server.query.OrPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.AndChangeSource;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeDataSource;

View File

@@ -24,12 +24,12 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.extensions.events.ChangeIndexedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.Index;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexExecutor;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration;

View File

@@ -14,10 +14,10 @@
package com.google.gerrit.server.index.change;
import static com.google.gerrit.server.index.SchemaUtil.schema;
import static com.google.gerrit.index.SchemaUtil.schema;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.SchemaDefinitions;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.SchemaDefinitions;
import com.google.gerrit.server.query.change.ChangeData;
public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> {

View File

@@ -14,10 +14,10 @@
package com.google.gerrit.server.index.change;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeDataSource;
import java.io.IOException;

View File

@@ -21,15 +21,15 @@ import static com.google.gerrit.server.index.change.ChangeField.PROJECT;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.IndexedQuery;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.index.IndexedQuery;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.query.DataSource;
import com.google.gerrit.server.query.Matchable;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeDataSource;
import com.google.gwtorm.server.OrmException;

View File

@@ -30,11 +30,11 @@ import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.query.change.ChangeData;

View File

@@ -21,12 +21,12 @@ import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.index.SiteIndexer;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.group.Groups;
import com.google.gerrit.server.index.IndexExecutor;
import com.google.gerrit.server.index.SiteIndexer;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;

View File

@@ -14,15 +14,15 @@
package com.google.gerrit.server.index.group;
import static com.google.gerrit.server.index.FieldDef.exact;
import static com.google.gerrit.server.index.FieldDef.fullText;
import static com.google.gerrit.server.index.FieldDef.integer;
import static com.google.gerrit.server.index.FieldDef.prefix;
import static com.google.gerrit.server.index.FieldDef.timestamp;
import static com.google.gerrit.index.FieldDef.exact;
import static com.google.gerrit.index.FieldDef.fullText;
import static com.google.gerrit.index.FieldDef.integer;
import static com.google.gerrit.index.FieldDef.prefix;
import static com.google.gerrit.index.FieldDef.timestamp;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.SchemaUtil;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.SchemaUtil;
import java.sql.Timestamp;
/** Secondary index schemas for groups. */

View File

@@ -14,10 +14,10 @@
package com.google.gerrit.server.index.group;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.group.GroupPredicates;
public interface GroupIndex extends Index<AccountGroup.UUID, AccountGroup> {

View File

@@ -15,8 +15,8 @@
package com.google.gerrit.server.index.group;
import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.IndexCollection;
import com.google.inject.Inject;
import com.google.inject.Singleton;

View File

@@ -15,8 +15,8 @@
package com.google.gerrit.server.index.group;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.IndexDefinition;
import com.google.inject.Inject;
public class GroupIndexDefinition

View File

@@ -16,11 +16,11 @@ package com.google.gerrit.server.index.group;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.gerrit.index.IndexRewriter;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.IndexRewriter;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.query.Predicate;
import com.google.inject.Inject;
import com.google.inject.Singleton;

View File

@@ -18,9 +18,9 @@ import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.events.GroupIndexedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.Index;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.index.Index;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;

View File

@@ -14,11 +14,11 @@
package com.google.gerrit.server.index.group;
import static com.google.gerrit.server.index.SchemaUtil.schema;
import static com.google.gerrit.index.SchemaUtil.schema;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.SchemaDefinitions;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.SchemaDefinitions;
public class GroupSchemaDefinitions extends SchemaDefinitions<AccountGroup> {
@Deprecated

View File

@@ -14,13 +14,13 @@
package com.google.gerrit.server.index.group;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexedQuery;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexedQuery;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.query.DataSource;
import com.google.gerrit.server.query.Predicate;
public class IndexedGroupQuery extends IndexedQuery<AccountGroup.UUID, AccountGroup>
implements DataSource<AccountGroup> {

View File

@@ -19,6 +19,7 @@ import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -32,7 +33,6 @@ import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
import com.google.gerrit.server.git.NotifyConfig;
import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.SingleGroupUser;

View File

@@ -1,131 +0,0 @@
// Copyright (C) 2009 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.query;
import static com.google.common.base.Preconditions.checkState;
import com.google.gwtorm.server.OrmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** Requires all predicates to be true. */
public class AndPredicate<T> extends Predicate<T> implements Matchable<T> {
private final List<Predicate<T>> children;
private final int cost;
@SafeVarargs
protected AndPredicate(Predicate<T>... that) {
this(Arrays.asList(that));
}
protected AndPredicate(Collection<? extends Predicate<T>> that) {
List<Predicate<T>> t = new ArrayList<>(that.size());
int c = 0;
for (Predicate<T> p : that) {
if (getClass() == p.getClass()) {
for (Predicate<T> gp : p.getChildren()) {
t.add(gp);
c += gp.estimateCost();
}
} else {
t.add(p);
c += p.estimateCost();
}
}
children = t;
cost = c;
}
@Override
public final List<Predicate<T>> getChildren() {
return Collections.unmodifiableList(children);
}
@Override
public final int getChildCount() {
return children.size();
}
@Override
public final Predicate<T> getChild(int i) {
return children.get(i);
}
@Override
public Predicate<T> copy(Collection<? extends Predicate<T>> children) {
return new AndPredicate<>(children);
}
@Override
public boolean isMatchable() {
for (Predicate<T> c : children) {
if (!c.isMatchable()) {
return false;
}
}
return true;
}
@Override
public boolean match(T object) throws OrmException {
for (Predicate<T> c : children) {
checkState(
c.isMatchable(),
"match invoked, but child predicate %s doesn't implement %s",
c,
Matchable.class.getName());
if (!c.asMatchable().match(object)) {
return false;
}
}
return true;
}
@Override
public int getCost() {
return cost;
}
@Override
public int hashCode() {
return getChild(0).hashCode() * 31 + getChild(1).hashCode();
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
return getClass() == other.getClass()
&& getChildren().equals(((Predicate<?>) other).getChildren());
}
@Override
public String toString() {
final StringBuilder r = new StringBuilder();
r.append("(");
for (int i = 0; i < getChildCount(); i++) {
if (i != 0) {
r.append(" ");
}
r.append(getChild(i));
}
r.append(")");
return r.toString();
}
}

View File

@@ -1,200 +0,0 @@
// 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.query;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.Throwables;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.gwtorm.server.ListResultSet;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import com.google.gwtorm.server.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class AndSource<T> extends AndPredicate<T>
implements DataSource<T>, Comparator<Predicate<T>> {
protected final DataSource<T> source;
private final IsVisibleToPredicate<T> isVisibleToPredicate;
private final int start;
private final int cardinality;
public AndSource(Collection<? extends Predicate<T>> that) {
this(that, null, 0);
}
public AndSource(Predicate<T> that, IsVisibleToPredicate<T> isVisibleToPredicate) {
this(that, isVisibleToPredicate, 0);
}
public AndSource(Predicate<T> that, IsVisibleToPredicate<T> isVisibleToPredicate, int start) {
this(ImmutableList.of(that), isVisibleToPredicate, start);
}
public AndSource(
Collection<? extends Predicate<T>> that,
IsVisibleToPredicate<T> isVisibleToPredicate,
int start) {
super(that);
checkArgument(start >= 0, "negative start: %s", start);
this.isVisibleToPredicate = isVisibleToPredicate;
this.start = start;
int c = Integer.MAX_VALUE;
DataSource<T> s = null;
int minCost = Integer.MAX_VALUE;
for (Predicate<T> p : sort(getChildren())) {
if (p instanceof DataSource) {
c = Math.min(c, ((DataSource<?>) p).getCardinality());
int cost = p.estimateCost();
if (cost < minCost) {
s = toDataSource(p);
minCost = cost;
}
}
}
this.source = s;
this.cardinality = c;
}
@Override
public ResultSet<T> read() throws OrmException {
try {
return readImpl();
} catch (OrmRuntimeException err) {
if (err.getCause() != null) {
Throwables.throwIfInstanceOf(err.getCause(), OrmException.class);
}
throw new OrmException(err);
}
}
private ResultSet<T> readImpl() throws OrmException {
if (source == null) {
throw new OrmException("No DataSource: " + this);
}
List<T> r = new ArrayList<>();
T last = null;
int nextStart = 0;
boolean skipped = false;
for (T data : buffer(source.read())) {
if (!isMatchable() || match(data)) {
r.add(data);
} else {
skipped = true;
}
last = data;
nextStart++;
}
if (skipped && last != null && source instanceof Paginated) {
// If our source is a paginated source and we skipped at
// least one of its results, we may not have filled the full
// limit the caller wants. Restart the source and continue.
//
@SuppressWarnings("unchecked")
Paginated<T> p = (Paginated<T>) source;
while (skipped && r.size() < p.getOptions().limit() + start) {
skipped = false;
ResultSet<T> next = p.restart(nextStart);
for (T data : buffer(next)) {
if (match(data)) {
r.add(data);
} else {
skipped = true;
}
nextStart++;
}
}
}
if (start >= r.size()) {
r = ImmutableList.of();
} else if (start > 0) {
r = ImmutableList.copyOf(r.subList(start, r.size()));
}
return new ListResultSet<>(r);
}
@Override
public boolean isMatchable() {
return isVisibleToPredicate != null || super.isMatchable();
}
@Override
public boolean match(T object) throws OrmException {
if (isVisibleToPredicate != null && !isVisibleToPredicate.match(object)) {
return false;
}
if (super.isMatchable() && !super.match(object)) {
return false;
}
return true;
}
private Iterable<T> buffer(ResultSet<T> scanner) {
return FluentIterable.from(Iterables.partition(scanner, 50))
.transformAndConcat(this::transformBuffer);
}
protected List<T> transformBuffer(List<T> buffer) throws OrmRuntimeException {
return buffer;
}
@Override
public int getCardinality() {
return cardinality;
}
private List<Predicate<T>> sort(Collection<? extends Predicate<T>> that) {
List<Predicate<T>> r = new ArrayList<>(that);
Collections.sort(r, this);
return r;
}
@Override
public int compare(Predicate<T> a, Predicate<T> b) {
int ai = a instanceof DataSource ? 0 : 1;
int bi = b instanceof DataSource ? 0 : 1;
int cmp = ai - bi;
if (cmp == 0) {
cmp = a.estimateCost() - b.estimateCost();
}
if (cmp == 0 && a instanceof DataSource && b instanceof DataSource) {
DataSource<?> as = (DataSource<?>) a;
DataSource<?> bs = (DataSource<?>) b;
cmp = as.getCardinality() - bs.getCardinality();
}
return cmp;
}
@SuppressWarnings("unchecked")
private DataSource<T> toDataSource(Predicate<T> pred) {
return (DataSource<T>) pred;
}
}

View File

@@ -1,26 +0,0 @@
// Copyright (C) 2014 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.query;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
public interface DataSource<T> {
/** @return an estimate of the number of results from {@link #read()}. */
int getCardinality();
/** @return read from the database and return the results. */
ResultSet<T> read() throws OrmException;
}

View File

@@ -1,56 +0,0 @@
// Copyright (C) 2009 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.query;
/** Predicate to filter a field by matching integer value. */
public abstract class IntPredicate<T> extends OperatorPredicate<T> {
private final int intValue;
public IntPredicate(String name, String value) {
super(name, value);
this.intValue = Integer.parseInt(value);
}
public IntPredicate(String name, int intValue) {
super(name, String.valueOf(intValue));
this.intValue = intValue;
}
public int intValue() {
return intValue;
}
@Override
public int hashCode() {
return getOperator().hashCode() * 31 + intValue;
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (getClass() == other.getClass()) {
final IntPredicate<?> p = (IntPredicate<?>) other;
return getOperator().equals(p.getOperator()) && intValue() == p.intValue();
}
return false;
}
@Override
public String toString() {
return getOperator() + ":" + getValue();
}
}

View File

@@ -16,11 +16,13 @@ package com.google.gerrit.server.query;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.index.query.QueryResult;
import com.google.gwtorm.server.OrmException;
import java.util.List;
import java.util.Set;

View File

@@ -1,21 +0,0 @@
// 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.query;
public abstract class IsVisibleToPredicate<T> extends OperatorPredicate<T> implements Matchable<T> {
public IsVisibleToPredicate(String name, String value) {
super(name, value);
}
}

View File

@@ -1,42 +0,0 @@
// Copyright (C) 2014 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.query;
import com.google.gerrit.index.query.QueryParseException;
public class LimitPredicate<T> extends IntPredicate<T> implements Matchable<T> {
@SuppressWarnings("unchecked")
public static Integer getLimit(String fieldName, Predicate<?> p) {
IntPredicate<?> ip = QueryBuilder.find(p, IntPredicate.class, fieldName);
return ip != null ? ip.intValue() : null;
}
public LimitPredicate(String fieldName, int limit) throws QueryParseException {
super(fieldName, limit);
if (limit <= 0) {
throw new QueryParseException("limit must be positive: " + limit);
}
}
@Override
public boolean match(T object) {
return true;
}
@Override
public int getCost() {
return 0;
}
}

View File

@@ -1,29 +0,0 @@
// 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.query;
import com.google.gwtorm.server.OrmException;
public interface Matchable<T> {
/**
* Does this predicate match this object?
*
* @throws OrmException
*/
boolean match(T object) throws OrmException;
/** @return a cost estimate to run this predicate, higher figures cost more. */
int getCost();
}

View File

@@ -1,99 +0,0 @@
// Copyright (C) 2009 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.query;
import static com.google.common.base.Preconditions.checkState;
import com.google.gwtorm.server.OrmException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** Negates the result of another predicate. */
public class NotPredicate<T> extends Predicate<T> implements Matchable<T> {
private final Predicate<T> that;
protected NotPredicate(Predicate<T> that) {
if (that instanceof NotPredicate) {
throw new IllegalArgumentException("Double negation unsupported");
}
this.that = that;
}
@Override
public final List<Predicate<T>> getChildren() {
return Collections.singletonList(that);
}
@Override
public final int getChildCount() {
return 1;
}
@Override
public final Predicate<T> getChild(int i) {
if (i != 0) {
throw new ArrayIndexOutOfBoundsException(i);
}
return that;
}
@Override
public Predicate<T> copy(Collection<? extends Predicate<T>> children) {
if (children.size() != 1) {
throw new IllegalArgumentException("Expected exactly one child");
}
return new NotPredicate<>(children.iterator().next());
}
@Override
public boolean isMatchable() {
return that.isMatchable();
}
@Override
public boolean match(T object) throws OrmException {
checkState(
that.isMatchable(),
"match invoked, but child predicate %s doesn't implement %s",
that,
Matchable.class.getName());
return !that.asMatchable().match(object);
}
@Override
public int getCost() {
return that.estimateCost();
}
@Override
public int hashCode() {
return ~that.hashCode();
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
return getClass() == other.getClass()
&& getChildren().equals(((Predicate<?>) other).getChildren());
}
@Override
public final String toString() {
return "-" + that.toString();
}
}

View File

@@ -1,71 +0,0 @@
// Copyright (C) 2009 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.query;
import com.google.gerrit.index.query.QueryParser;
import java.util.Collection;
/** Predicate to filter a field by matching value. */
public abstract class OperatorPredicate<T> extends Predicate<T> {
protected final String name;
protected final String value;
public OperatorPredicate(String name, String value) {
this.name = name;
this.value = value;
}
public String getOperator() {
return name;
}
public String getValue() {
return value;
}
@Override
public Predicate<T> copy(Collection<? extends Predicate<T>> children) {
if (!children.isEmpty()) {
throw new IllegalArgumentException("Expected 0 children");
}
return this;
}
@Override
public int hashCode() {
return getOperator().hashCode() * 31 + getValue().hashCode();
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (getClass() == other.getClass()) {
final OperatorPredicate<?> p = (OperatorPredicate<?>) other;
return getOperator().equals(p.getOperator()) && getValue().equals(p.getValue());
}
return false;
}
@Override
public String toString() {
final String val = getValue();
if (QueryParser.isSingleWord(val)) {
return getOperator() + ":" + val;
}
return getOperator() + ":\"" + val + "\"";
}
}

View File

@@ -1,131 +0,0 @@
// Copyright (C) 2009 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.query;
import static com.google.common.base.Preconditions.checkState;
import com.google.gwtorm.server.OrmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** Requires one predicate to be true. */
public class OrPredicate<T> extends Predicate<T> implements Matchable<T> {
private final List<Predicate<T>> children;
private final int cost;
@SafeVarargs
protected OrPredicate(Predicate<T>... that) {
this(Arrays.asList(that));
}
protected OrPredicate(Collection<? extends Predicate<T>> that) {
List<Predicate<T>> t = new ArrayList<>(that.size());
int c = 0;
for (Predicate<T> p : that) {
if (getClass() == p.getClass()) {
for (Predicate<T> gp : p.getChildren()) {
t.add(gp);
c += gp.estimateCost();
}
} else {
t.add(p);
c += p.estimateCost();
}
}
children = t;
cost = c;
}
@Override
public final List<Predicate<T>> getChildren() {
return Collections.unmodifiableList(children);
}
@Override
public final int getChildCount() {
return children.size();
}
@Override
public final Predicate<T> getChild(int i) {
return children.get(i);
}
@Override
public Predicate<T> copy(Collection<? extends Predicate<T>> children) {
return new OrPredicate<>(children);
}
@Override
public boolean isMatchable() {
for (Predicate<T> c : children) {
if (!c.isMatchable()) {
return false;
}
}
return true;
}
@Override
public boolean match(T object) throws OrmException {
for (Predicate<T> c : children) {
checkState(
c.isMatchable(),
"match invoked, but child predicate %s doesn't implement %s",
c,
Matchable.class.getName());
if (c.asMatchable().match(object)) {
return true;
}
}
return false;
}
@Override
public int getCost() {
return cost;
}
@Override
public int hashCode() {
return getChild(0).hashCode() * 31 + getChild(1).hashCode();
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
return getClass() == other.getClass()
&& getChildren().equals(((Predicate<?>) other).getChildren());
}
@Override
public String toString() {
final StringBuilder r = new StringBuilder();
r.append("(");
for (int i = 0; i < getChildCount(); i++) {
if (i != 0) {
r.append(" OR ");
}
r.append(getChild(i));
}
r.append(")");
return r.toString();
}
}

View File

@@ -1,25 +0,0 @@
// Copyright (C) 2010 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.query;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
public interface Paginated<T> {
QueryOptions getOptions();
ResultSet<T> restart(int start) throws OrmException;
}

View File

@@ -1,165 +0,0 @@
// Copyright (C) 2009 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.query;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.collect.Iterables;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* An abstract predicate tree for any form of query.
*
* <p>Implementations should be immutable, such that the meaning of a predicate never changes once
* constructed. They should ensure their immutable promise by defensively copying any structures
* which might be modified externally, but was passed into the object's constructor.
*
* <p>However, implementations <i>may</i> retain non-thread-safe caches internally, to speed up
* evaluation operations within the context of one thread's evaluation of the predicate. As a
* result, callers should assume predicates are not thread-safe, but that two predicate graphs
* produce the same results given the same inputs if they are {@link #equals(Object)}.
*
* <p>Predicates should support deep inspection whenever possible, so that generic algorithms can be
* written to operate against them. Predicates which contain other predicates should override {@link
* #getChildren()} to return the list of children nested within the predicate.
*
* @param <T> type of object the predicate can evaluate in memory.
*/
public abstract class Predicate<T> {
/** A predicate that matches any input, always, with no cost. */
@SuppressWarnings("unchecked")
public static <T> Predicate<T> any() {
return (Predicate<T>) Any.INSTANCE;
}
/** Combine the passed predicates into a single AND node. */
@SafeVarargs
public static <T> Predicate<T> and(Predicate<T>... that) {
if (that.length == 1) {
return that[0];
}
return new AndPredicate<>(that);
}
/** Combine the passed predicates into a single AND node. */
public static <T> Predicate<T> and(Collection<? extends Predicate<T>> that) {
if (that.size() == 1) {
return Iterables.getOnlyElement(that);
}
return new AndPredicate<>(that);
}
/** Combine the passed predicates into a single OR node. */
@SafeVarargs
public static <T> Predicate<T> or(Predicate<T>... that) {
if (that.length == 1) {
return that[0];
}
return new OrPredicate<>(that);
}
/** Combine the passed predicates into a single OR node. */
public static <T> Predicate<T> or(Collection<? extends Predicate<T>> that) {
if (that.size() == 1) {
return Iterables.getOnlyElement(that);
}
return new OrPredicate<>(that);
}
/** Invert the passed node. */
public static <T> Predicate<T> not(Predicate<T> that) {
if (that instanceof NotPredicate) {
// Negate of a negate is the original predicate.
//
return that.getChild(0);
}
return new NotPredicate<>(that);
}
/** Get the children of this predicate, if any. */
public List<Predicate<T>> getChildren() {
return Collections.emptyList();
}
/** Same as {@code getChildren().size()} */
public int getChildCount() {
return getChildren().size();
}
/** Same as {@code getChildren().get(i)} */
public Predicate<T> getChild(int i) {
return getChildren().get(i);
}
/** Create a copy of this predicate, with new children. */
public abstract Predicate<T> copy(Collection<? extends Predicate<T>> children);
public boolean isMatchable() {
return this instanceof Matchable;
}
@SuppressWarnings("unchecked")
public Matchable<T> asMatchable() {
checkState(isMatchable(), "not matchable");
return (Matchable<T>) this;
}
/** @return a cost estimate to run this predicate, higher figures cost more. */
public int estimateCost() {
if (!isMatchable()) {
return 1;
}
return asMatchable().getCost();
}
@Override
public abstract int hashCode();
@Override
public abstract boolean equals(Object other);
private static class Any<T> extends Predicate<T> implements Matchable<T> {
private static final Any<Object> INSTANCE = new Any<>();
private Any() {}
@Override
public Predicate<T> copy(Collection<? extends Predicate<T>> children) {
return this;
}
@Override
public boolean match(T object) {
return true;
}
@Override
public int getCost() {
return 0;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public boolean equals(Object other) {
return other == this;
}
}
}

View File

@@ -1,352 +0,0 @@
// Copyright (C) 2009 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.query;
import static com.google.gerrit.index.query.QueryParser.AND;
import static com.google.gerrit.index.query.QueryParser.DEFAULT_FIELD;
import static com.google.gerrit.index.query.QueryParser.EXACT_PHRASE;
import static com.google.gerrit.index.query.QueryParser.FIELD_NAME;
import static com.google.gerrit.index.query.QueryParser.NOT;
import static com.google.gerrit.index.query.QueryParser.OR;
import static com.google.gerrit.index.query.QueryParser.SINGLE_WORD;
import static com.google.gerrit.server.query.Predicate.and;
import static com.google.gerrit.server.query.Predicate.not;
import static com.google.gerrit.server.query.Predicate.or;
import com.google.common.base.Strings;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryParser;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.antlr.runtime.tree.Tree;
/**
* Base class to support writing parsers for query languages.
*
* <p>Subclasses may document their supported query operators by declaring public methods that
* perform the query conversion into a {@link Predicate}. For example, to support "is:starred",
* "is:unread", and nothing else, a subclass may write:
*
* <pre>
* &#064;Operator
* public Predicate is(String value) {
* if (&quot;starred&quot;.equals(value)) {
* return new StarredPredicate();
* }
* if (&quot;unread&quot;.equals(value)) {
* return new UnreadPredicate();
* }
* throw new IllegalArgumentException();
* }
* </pre>
*
* <p>The available operator methods are discovered at runtime via reflection. Method names (after
* being converted to lowercase), correspond to operators in the query language, method string
* values correspond to the operator argument. Methods must be declared {@code public}, returning
* {@link Predicate}, accepting one {@link String}, and annotated with the {@link Operator}
* annotation.
*
* <p>Subclasses may also declare a handler for values which appear without operator by overriding
* {@link #defaultField(String)}.
*
* @param <T> type of object the predicates can evaluate in memory.
*/
public abstract class QueryBuilder<T> {
/** Converts a value string passed to an operator into a {@link Predicate}. */
public interface OperatorFactory<T, Q extends QueryBuilder<T>> {
Predicate<T> create(Q builder, String value) throws QueryParseException;
}
/**
* Defines the operators known by a QueryBuilder.
*
* <p>This class is thread-safe and may be reused or cached.
*
* @param <T> type of object the predicates can evaluate in memory.
* @param <Q> type of the query builder subclass.
*/
public static class Definition<T, Q extends QueryBuilder<T>> {
private final Map<String, OperatorFactory<T, Q>> opFactories = new HashMap<>();
public Definition(Class<Q> clazz) {
// Guess at the supported operators by scanning methods.
//
Class<?> c = clazz;
while (c != QueryBuilder.class) {
for (Method method : c.getDeclaredMethods()) {
if (method.getAnnotation(Operator.class) != null
&& Predicate.class.isAssignableFrom(method.getReturnType())
&& method.getParameterTypes().length == 1
&& method.getParameterTypes()[0] == String.class
&& (method.getModifiers() & Modifier.ABSTRACT) == 0
&& (method.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC) {
final String name = method.getName().toLowerCase();
if (!opFactories.containsKey(name)) {
opFactories.put(name, new ReflectionFactory<T, Q>(name, method));
}
}
}
c = c.getSuperclass();
}
}
}
/**
* Locate a predicate in the predicate tree.
*
* @param p the predicate to find.
* @param clazz type of the predicate instance.
* @return the predicate, null if not found.
*/
@SuppressWarnings("unchecked")
public static <T, P extends Predicate<T>> P find(Predicate<T> p, Class<P> clazz) {
if (clazz.isAssignableFrom(p.getClass())) {
return (P) p;
}
for (Predicate<T> c : p.getChildren()) {
P r = find(c, clazz);
if (r != null) {
return r;
}
}
return null;
}
/**
* Locate a predicate in the predicate tree.
*
* @param p the predicate to find.
* @param clazz type of the predicate instance.
* @param name name of the operator.
* @return the first instance of a predicate having the given type, as found by a depth-first
* search.
*/
@SuppressWarnings("unchecked")
public static <T, P extends OperatorPredicate<T>> P find(
Predicate<T> p, Class<P> clazz, String name) {
if (p instanceof OperatorPredicate
&& ((OperatorPredicate<?>) p).getOperator().equals(name)
&& clazz.isAssignableFrom(p.getClass())) {
return (P) p;
}
for (Predicate<T> c : p.getChildren()) {
P r = find(c, clazz, name);
if (r != null) {
return r;
}
}
return null;
}
protected final Definition<T, ? extends QueryBuilder<T>> builderDef;
protected final Map<String, OperatorFactory<?, ?>> opFactories;
@SuppressWarnings({"unchecked", "rawtypes"})
protected QueryBuilder(Definition<T, ? extends QueryBuilder<T>> def) {
builderDef = def;
opFactories = (Map) def.opFactories;
}
/**
* Parse a user-supplied query string into a predicate.
*
* @param query the query string.
* @return predicate representing the user query.
* @throws QueryParseException the query string is invalid and cannot be parsed by this parser.
* This may be due to a syntax error, may be due to an operator not being supported, or due to
* an invalid value being passed to a recognized operator.
*/
public Predicate<T> parse(String query) throws QueryParseException {
if (Strings.isNullOrEmpty(query)) {
throw new QueryParseException("query is empty");
}
return toPredicate(QueryParser.parse(query));
}
/**
* Parse multiple user-supplied query strings into a list of predicates.
*
* @param queries the query strings.
* @return predicates representing the user query, in the same order as the input.
* @throws QueryParseException one of the query strings is invalid and cannot be parsed by this
* parser. This may be due to a syntax error, may be due to an operator not being supported,
* or due to an invalid value being passed to a recognized operator.
*/
public List<Predicate<T>> parse(List<String> queries) throws QueryParseException {
List<Predicate<T>> predicates = new ArrayList<>(queries.size());
for (String query : queries) {
predicates.add(parse(query));
}
return predicates;
}
private Predicate<T> toPredicate(Tree r) throws QueryParseException, IllegalArgumentException {
switch (r.getType()) {
case AND:
return and(children(r));
case OR:
return or(children(r));
case NOT:
return not(toPredicate(onlyChildOf(r)));
case DEFAULT_FIELD:
return defaultField(onlyChildOf(r));
case FIELD_NAME:
return operator(r.getText(), onlyChildOf(r));
default:
throw error("Unsupported operator: " + r);
}
}
private Predicate<T> operator(String name, Tree val) throws QueryParseException {
switch (val.getType()) {
// Expand multiple values, "foo:(a b c)", as though they were written
// out with the longer form, "foo:a foo:b foo:c".
//
case AND:
case OR:
{
List<Predicate<T>> p = new ArrayList<>(val.getChildCount());
for (int i = 0; i < val.getChildCount(); i++) {
final Tree c = val.getChild(i);
if (c.getType() != DEFAULT_FIELD) {
throw error("Nested operator not expected: " + c);
}
p.add(operator(name, onlyChildOf(c)));
}
return val.getType() == AND ? and(p) : or(p);
}
case SINGLE_WORD:
case EXACT_PHRASE:
if (val.getChildCount() != 0) {
throw error("Expected no children under: " + val);
}
return operator(name, val.getText());
default:
throw error("Unsupported node in operator " + name + ": " + val);
}
}
@SuppressWarnings("unchecked")
private Predicate<T> operator(String name, String value) throws QueryParseException {
@SuppressWarnings("rawtypes")
OperatorFactory f = opFactories.get(name);
if (f == null) {
throw error("Unsupported operator " + name + ":" + value);
}
return f.create(this, value);
}
private Predicate<T> defaultField(Tree r) throws QueryParseException {
switch (r.getType()) {
case SINGLE_WORD:
case EXACT_PHRASE:
if (r.getChildCount() != 0) {
throw error("Expected no children under: " + r);
}
return defaultField(r.getText());
default:
throw error("Unsupported node: " + r);
}
}
/**
* Handle a value present outside of an operator.
*
* <p>This default implementation always throws an "Unsupported query: " message containing the
* input text. Subclasses may override this method to perform do-what-i-mean guesses based on the
* input string.
*
* @param value the value supplied by itself in the query.
* @return predicate representing this value.
* @throws QueryParseException the parser does not recognize this value.
*/
protected Predicate<T> defaultField(String value) throws QueryParseException {
throw error("Unsupported query:" + value);
}
private List<Predicate<T>> children(Tree r) throws QueryParseException, IllegalArgumentException {
List<Predicate<T>> p = new ArrayList<>(r.getChildCount());
for (int i = 0; i < r.getChildCount(); i++) {
p.add(toPredicate(r.getChild(i)));
}
return p;
}
private Tree onlyChildOf(Tree r) throws QueryParseException {
if (r.getChildCount() != 1) {
throw error("Expected exactly one child: " + r);
}
return r.getChild(0);
}
protected static QueryParseException error(String msg) {
return new QueryParseException(msg);
}
protected static QueryParseException error(String msg, Throwable why) {
return new QueryParseException(msg, why);
}
/** Denotes a method which is a query operator. */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
protected @interface Operator {}
private static class ReflectionFactory<T, Q extends QueryBuilder<T>>
implements OperatorFactory<T, Q> {
private final String name;
private final Method method;
ReflectionFactory(String name, Method method) {
this.name = name;
this.method = method;
}
@SuppressWarnings("unchecked")
@Override
public Predicate<T> create(Q builder, String value) throws QueryParseException {
try {
return (Predicate<T>) method.invoke(builder, value);
} catch (RuntimeException | IllegalAccessException e) {
throw error("Error in operator " + name + ":" + value, e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof QueryParseException) {
throw (QueryParseException) e.getCause();
}
throw error("Error in operator " + name + ":" + value, e.getCause());
}
}
}
}

View File

@@ -19,19 +19,23 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Ordering;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.IndexRewriter;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.SchemaDefinitions;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.LimitPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountLimits;
import com.google.gerrit.server.index.Index;
import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexRewriter;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.index.SchemaDefinitions;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import com.google.gwtorm.server.ResultSet;

View File

@@ -1,51 +0,0 @@
// Copyright (C) 2014 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.query;
import com.google.auto.value.AutoValue;
import com.google.gerrit.common.Nullable;
import java.util.List;
/** Results of a query over entities. */
@AutoValue
public abstract class QueryResult<T> {
static <T> QueryResult<T> create(
@Nullable String query, Predicate<T> predicate, int limit, List<T> entites) {
boolean more;
if (entites.size() > limit) {
more = true;
entites = entites.subList(0, limit);
} else {
more = false;
}
return new AutoValue_QueryResult<>(query, predicate, entites, more);
}
/** @return the original query string, or null if the query was created programmatically. */
@Nullable
public abstract String query();
/** @return the predicate after all rewriting and other modification by the query subsystem. */
public abstract Predicate<T> predicate();
/** @return the query results. */
public abstract List<T> entities();
/**
* @return whether the query could be retried with {@link QueryProcessor#setStart(int)} to produce
* more results. Never true if {@link #entities()} is empty.
*/
public abstract boolean more();
}

View File

@@ -14,10 +14,10 @@
package com.google.gerrit.server.query.account;
import com.google.gerrit.index.query.IsVisibleToPredicate;
import com.google.gerrit.server.account.AccountControl;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.IndexUtils;
import com.google.gerrit.server.query.IsVisibleToPredicate;
import com.google.gwtorm.server.OrmException;
public class AccountIsVisibleToPredicate extends IsVisibleToPredicate<AccountState> {

View File

@@ -16,14 +16,14 @@ package com.google.gerrit.server.query.account;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryBuilder;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.index.account.AccountField;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryBuilder;
import java.util.List;
public class AccountPredicates {

View File

@@ -18,14 +18,14 @@ import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.errors.NotSignedInException;
import com.google.gerrit.index.query.LimitPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryBuilder;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.query.LimitPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryBuilder;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;

View File

@@ -17,17 +17,17 @@ package com.google.gerrit.server.query.account;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.query.account.AccountQueryBuilder.FIELD_LIMIT;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.query.AndSource;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountControl;
import com.google.gerrit.server.account.AccountLimits;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gerrit.server.index.account.AccountIndexRewriter;
import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
import com.google.gerrit.server.query.AndSource;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryProcessor;
import com.google.inject.Inject;
import com.google.inject.Provider;

View File

@@ -20,10 +20,10 @@ import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gerrit.server.query.InternalQuery;
import com.google.gwtorm.server.OrmException;

View File

@@ -14,9 +14,9 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.server.query.AndSource;
import com.google.gerrit.server.query.IsVisibleToPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.index.query.AndSource;
import com.google.gerrit.index.query.IsVisibleToPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import java.util.Collection;

View File

@@ -14,7 +14,7 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.index.FieldDef;
import com.google.gwtorm.server.OrmException;
public class BooleanPredicate extends ChangeIndexPredicate {

View File

@@ -14,7 +14,7 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.server.query.DataSource;
import com.google.gerrit.index.query.DataSource;
public interface ChangeDataSource extends DataSource<ChangeData> {
/** @return true if all returned ChangeData.hasChange() will be true. */

View File

@@ -14,11 +14,11 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.query.Matchable;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeQueryBuilder.Arguments;
public abstract class ChangeIndexPredicate extends IndexPredicate<ChangeData>

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.index.query.IsVisibleToPredicate;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
@@ -24,7 +25,6 @@ import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.IsVisibleToPredicate;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;

View File

@@ -14,8 +14,8 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.server.query.Matchable;
import com.google.gerrit.server.query.OperatorPredicate;
import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.OperatorPredicate;
public abstract class ChangeOperatorPredicate extends OperatorPredicate<ChangeData>
implements Matchable<ChangeData> {

View File

@@ -29,6 +29,12 @@ import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.common.errors.NotSignedInException;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.SchemaUtil;
import com.google.gerrit.index.query.LimitPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryBuilder;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -53,9 +59,6 @@ import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.strategy.SubmitDryRun;
import com.google.gerrit.server.group.ListMembers;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.SchemaUtil;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
@@ -69,9 +72,6 @@ import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ListChildProjects;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.LimitPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryBuilder;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

View File

@@ -19,12 +19,13 @@ import static com.google.gerrit.server.query.change.ChangeQueryBuilder.FIELD_LIM
import com.google.gerrit.extensions.common.PluginDefinedInfo;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountLimits;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.index.QueryOptions;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexRewriter;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
@@ -32,7 +33,6 @@ import com.google.gerrit.server.index.change.IndexedChangeQuery;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryProcessor;
import com.google.inject.Inject;
import com.google.inject.Provider;

View File

@@ -14,9 +14,9 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.RegexPredicate;
import com.google.gerrit.server.query.Matchable;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.RegexPredicate;
public abstract class ChangeRegexPredicate extends RegexPredicate<ChangeData>
implements Matchable<ChangeData> {

View File

@@ -14,11 +14,11 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.query.Predicate;
import com.google.gwtorm.server.OrmException;
import java.util.ArrayList;
import java.util.List;

View File

@@ -14,11 +14,11 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.IndexedChangeQuery;
import com.google.gerrit.server.query.Predicate;
import com.google.gwtorm.server.OrmException;
public class CommentPredicate extends ChangeIndexPredicate {

View File

@@ -18,8 +18,8 @@ import static com.google.gerrit.server.index.change.ChangeField.COMMIT;
import static com.google.gerrit.server.index.change.ChangeField.EXACT_COMMIT;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.index.FieldDef;
import com.google.gwtorm.server.OrmException;
public class CommitPredicate extends ChangeIndexPredicate {

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -25,7 +26,6 @@ import com.google.gerrit.server.git.strategy.SubmitDryRun;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeQueryBuilder.Arguments;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;

View File

@@ -14,8 +14,8 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.change.ChangeQueryBuilder.Arguments;
import com.google.gwtorm.server.OrmException;

View File

@@ -17,11 +17,11 @@ package com.google.gerrit.server.query.change;
import static com.google.gerrit.server.index.change.ChangeField.FUZZY_TOPIC;
import com.google.common.collect.Iterables;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.IndexedChangeQuery;
import com.google.gerrit.server.query.Predicate;
import com.google.gwtorm.server.OrmException;
public class FuzzyTopicPredicate extends ChangeIndexPredicate {

View File

@@ -14,10 +14,10 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.query.IntegerRangePredicate;
import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.index.FieldDef;
import com.google.gerrit.server.index.IntegerRangePredicate;
import com.google.gerrit.server.query.Matchable;
public abstract class IntegerRangeChangePredicate extends IntegerRangePredicate<ChangeData>
implements Matchable<ChangeData> {

View File

@@ -15,25 +15,25 @@
package com.google.gerrit.server.query.change;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.server.query.Predicate.and;
import static com.google.gerrit.server.query.Predicate.not;
import static com.google.gerrit.server.query.Predicate.or;
import static com.google.gerrit.index.query.Predicate.and;
import static com.google.gerrit.index.query.Predicate.not;
import static com.google.gerrit.index.query.Predicate.or;
import static com.google.gerrit.server.query.change.ChangeStatusPredicate.open;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.query.InternalQuery;
import com.google.gerrit.server.query.Predicate;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.io.IOException;

View File

@@ -16,9 +16,9 @@ package com.google.gerrit.server.query.change;
import static com.google.gerrit.server.index.change.ChangeField.REVIEWEDBY;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.query.Predicate;
import com.google.gwtorm.server.OrmException;
import java.util.ArrayList;
import java.util.Collection;

View File

@@ -15,12 +15,12 @@
package com.google.gerrit.server.query.change;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.index.query.AndPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryBuilder;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
import com.google.gerrit.server.query.AndPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryBuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

Some files were not shown because too many files have changed in this diff Show More