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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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 >, >=, =, <, or <=
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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() {}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 + "\"";
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
* @Operator
|
||||
* public Predicate is(String value) {
|
||||
* if ("starred".equals(value)) {
|
||||
* return new StarredPredicate();
|
||||
* }
|
||||
* if ("unread".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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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> {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user