Merge branch 'stable-2.15' into stable-2.16
* stable-2.15:
ElasticContainer: Use 7.0.0-alpha2
Change-Id: I3ac909ab9e19da41e2c2b03b966f4abc507c3c54
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
deleted file mode 100644
index 722e6d8..0000000
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
+++ /dev/null
@@ -1,207 +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.elasticsearch;
-
-import static com.google.gerrit.server.index.account.AccountField.ID;
-
-import com.google.common.collect.Lists;
-import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
-import com.google.gerrit.elasticsearch.builders.QueryBuilder;
-import com.google.gerrit.elasticsearch.builders.SearchSourceBuilder;
-import com.google.gerrit.elasticsearch.bulk.BulkRequest;
-import com.google.gerrit.elasticsearch.bulk.IndexRequest;
-import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
-import com.google.gerrit.index.QueryOptions;
-import com.google.gerrit.index.Schema;
-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.AccountCache;
-import com.google.gerrit.server.account.AccountState;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.index.IndexUtils;
-import com.google.gerrit.server.index.account.AccountField;
-import com.google.gerrit.server.index.account.AccountIndex;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.ResultSet;
-import com.google.inject.Provider;
-import com.google.inject.assistedinject.Assisted;
-import com.google.inject.assistedinject.AssistedInject;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import org.apache.http.HttpStatus;
-import org.apache.http.StatusLine;
-import org.elasticsearch.client.Response;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, AccountState>
- implements AccountIndex {
- private static final Logger log = LoggerFactory.getLogger(ElasticAccountIndex.class);
-
- static class AccountMapping {
- final MappingProperties accounts;
-
- AccountMapping(Schema<AccountState> schema, ElasticQueryAdapter adapter) {
- this.accounts = ElasticMapping.createMapping(schema, adapter);
- }
- }
-
- private static final String ACCOUNTS = "accounts";
-
- private final AccountMapping mapping;
- private final Provider<AccountCache> accountCache;
- private final Schema<AccountState> schema;
-
- @AssistedInject
- ElasticAccountIndex(
- ElasticConfiguration cfg,
- SitePaths sitePaths,
- Provider<AccountCache> accountCache,
- ElasticRestClientProvider client,
- @Assisted Schema<AccountState> schema) {
- super(cfg, sitePaths, schema, client, ACCOUNTS);
- this.accountCache = accountCache;
- this.mapping = new AccountMapping(schema, client.adapter());
- this.schema = schema;
- }
-
- @Override
- public void replace(AccountState as) throws IOException {
- BulkRequest bulk =
- new IndexRequest(getId(as), indexName, type, client.adapter())
- .add(new UpdateRequest<>(schema, as));
-
- String uri = getURI(type, BULK);
- Response response = postRequest(uri, bulk, getRefreshParam());
- int statusCode = response.getStatusLine().getStatusCode();
- if (statusCode != HttpStatus.SC_OK) {
- throw new IOException(
- String.format(
- "Failed to replace account %s in index %s: %s",
- as.getAccount().getId(), indexName, statusCode));
- }
- }
-
- @Override
- public DataSource<AccountState> getSource(Predicate<AccountState> p, QueryOptions opts)
- throws QueryParseException {
- return new QuerySource(p, opts);
- }
-
- @Override
- protected String getDeleteActions(Account.Id a) {
- return delete(type, a);
- }
-
- @Override
- protected String getMappings() {
- return getMappingsForSingleType(ACCOUNTS, mapping.accounts);
- }
-
- @Override
- protected String getId(AccountState as) {
- return as.getAccount().getId().toString();
- }
-
- private class QuerySource implements DataSource<AccountState> {
- private final String search;
- private final Set<String> fields;
-
- QuerySource(Predicate<AccountState> p, QueryOptions opts) throws QueryParseException {
- QueryBuilder qb = queryBuilder.toQueryBuilder(p);
- fields = IndexUtils.accountFields(opts);
- SearchSourceBuilder searchSource =
- new SearchSourceBuilder(client.adapter())
- .query(qb)
- .from(opts.start())
- .size(opts.limit())
- .fields(Lists.newArrayList(fields));
-
- JsonArray sortArray = getSortArray(AccountField.ID.getName());
- search = getSearch(searchSource, sortArray);
- }
-
- @Override
- public int getCardinality() {
- return 10;
- }
-
- @Override
- public ResultSet<AccountState> read() throws OrmException {
- try {
- List<AccountState> results = Collections.emptyList();
- String uri = getURI(type, SEARCH);
- Response response = postRequest(uri, search);
- StatusLine statusLine = response.getStatusLine();
- if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
- String content = getContent(response);
- JsonObject obj =
- new JsonParser().parse(content).getAsJsonObject().getAsJsonObject("hits");
- if (obj.get("hits") != null) {
- JsonArray json = obj.getAsJsonArray("hits");
- results = Lists.newArrayListWithCapacity(json.size());
- for (int i = 0; i < json.size(); i++) {
- results.add(toAccountState(json.get(i)));
- }
- }
- } else {
- log.error(statusLine.getReasonPhrase());
- }
- final List<AccountState> r = Collections.unmodifiableList(results);
- return new ResultSet<AccountState>() {
- @Override
- public Iterator<AccountState> iterator() {
- return r.iterator();
- }
-
- @Override
- public List<AccountState> toList() {
- return r;
- }
-
- @Override
- public void close() {
- // Do nothing.
- }
- };
- } catch (IOException e) {
- throw new OrmException(e);
- }
- }
-
- private AccountState toAccountState(JsonElement json) {
- JsonElement source = json.getAsJsonObject().get("_source");
- if (source == null) {
- source = json.getAsJsonObject().get("fields");
- }
-
- Account.Id id = new Account.Id(source.getAsJsonObject().get(ID.getName()).getAsInt());
- // Use the AccountCache rather than depending on any stored fields in the
- // document (of which there shouldn't be any). The most expensive part to
- // compute anyway is the effective group IDs, and we don't have a good way
- // to reindex when those change.
- return accountCache.get().get(id);
- }
- }
-}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
deleted file mode 100644
index 264822e..0000000
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
+++ /dev/null
@@ -1,465 +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.elasticsearch;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.gerrit.server.index.change.ChangeField.APPROVAL_CODEC;
-import static com.google.gerrit.server.index.change.ChangeField.CHANGE_CODEC;
-import static com.google.gerrit.server.index.change.ChangeField.PATCH_SET_CODEC;
-import static com.google.gerrit.server.index.change.ChangeIndexRewriter.CLOSED_STATUSES;
-import static com.google.gerrit.server.index.change.ChangeIndexRewriter.OPEN_STATUSES;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.commons.codec.binary.Base64.decodeBase64;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.Sets;
-import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
-import com.google.gerrit.elasticsearch.builders.QueryBuilder;
-import com.google.gerrit.elasticsearch.builders.SearchSourceBuilder;
-import com.google.gerrit.elasticsearch.bulk.BulkRequest;
-import com.google.gerrit.elasticsearch.bulk.DeleteRequest;
-import com.google.gerrit.elasticsearch.bulk.IndexRequest;
-import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
-import com.google.gerrit.index.QueryOptions;
-import com.google.gerrit.index.Schema;
-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.Change;
-import com.google.gerrit.reviewdb.client.Change.Id;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.ReviewerByEmailSet;
-import com.google.gerrit.server.ReviewerSet;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.index.IndexUtils;
-import com.google.gerrit.server.index.change.ChangeField;
-import com.google.gerrit.server.index.change.ChangeIndex;
-import com.google.gerrit.server.index.change.ChangeIndexRewriter;
-import com.google.gerrit.server.project.SubmitRuleOptions;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.query.change.ChangeDataSource;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.ResultSet;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.http.HttpStatus;
-import org.apache.http.StatusLine;
-import org.elasticsearch.client.Response;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/** Secondary index implementation using Elasticsearch. */
-class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
- implements ChangeIndex {
- private static final Logger log = LoggerFactory.getLogger(ElasticChangeIndex.class);
-
- static class ChangeMapping {
- final MappingProperties changes;
- final MappingProperties openChanges;
- final MappingProperties closedChanges;
-
- ChangeMapping(Schema<ChangeData> schema, ElasticQueryAdapter adapter) {
- MappingProperties mapping = ElasticMapping.createMapping(schema, adapter);
- this.changes = mapping;
- this.openChanges = mapping;
- this.closedChanges = mapping;
- }
- }
-
- private static final String CHANGES = "changes";
- private static final String OPEN_CHANGES = "open_" + CHANGES;
- private static final String CLOSED_CHANGES = "closed_" + CHANGES;
- private static final String ALL_CHANGES = OPEN_CHANGES + "," + CLOSED_CHANGES;
- private final ChangeMapping mapping;
- private final Provider<ReviewDb> db;
- private final ChangeData.Factory changeDataFactory;
- private final Schema<ChangeData> schema;
-
- @Inject
- ElasticChangeIndex(
- ElasticConfiguration cfg,
- Provider<ReviewDb> db,
- ChangeData.Factory changeDataFactory,
- SitePaths sitePaths,
- ElasticRestClientProvider client,
- @Assisted Schema<ChangeData> schema) {
- super(cfg, sitePaths, schema, client, CHANGES, ALL_CHANGES);
- this.db = db;
- this.changeDataFactory = changeDataFactory;
- this.schema = schema;
- this.mapping = new ChangeMapping(schema, client.adapter());
- }
-
- @Override
- public void replace(ChangeData cd) throws IOException {
- String deleteIndex;
- String insertIndex;
-
- try {
- if (cd.change().getStatus().isOpen()) {
- insertIndex = OPEN_CHANGES;
- deleteIndex = CLOSED_CHANGES;
- } else {
- insertIndex = CLOSED_CHANGES;
- deleteIndex = OPEN_CHANGES;
- }
- } catch (OrmException e) {
- throw new IOException(e);
- }
-
- ElasticQueryAdapter adapter = client.adapter();
- BulkRequest bulk =
- new IndexRequest(getId(cd), indexName, adapter.getType(insertIndex), adapter)
- .add(new UpdateRequest<>(schema, cd));
- if (!adapter.usePostV5Type()) {
- bulk.add(new DeleteRequest(cd.getId().toString(), indexName, deleteIndex, adapter));
- }
-
- String uri = getURI(type, BULK);
- Response response = postRequest(uri, bulk, getRefreshParam());
- int statusCode = response.getStatusLine().getStatusCode();
- if (statusCode != HttpStatus.SC_OK) {
- throw new IOException(
- String.format(
- "Failed to replace change %s in index %s: %s", cd.getId(), indexName, statusCode));
- }
- }
-
- @Override
- public ChangeDataSource getSource(Predicate<ChangeData> p, QueryOptions opts)
- throws QueryParseException {
- Set<Change.Status> statuses = ChangeIndexRewriter.getPossibleStatus(p);
- List<String> indexes = Lists.newArrayListWithCapacity(2);
- if (client.adapter().usePostV5Type()) {
- if (!Sets.intersection(statuses, OPEN_STATUSES).isEmpty()
- || !Sets.intersection(statuses, CLOSED_STATUSES).isEmpty()) {
- indexes.add(ElasticQueryAdapter.POST_V5_TYPE);
- }
- } else {
- if (!Sets.intersection(statuses, OPEN_STATUSES).isEmpty()) {
- indexes.add(OPEN_CHANGES);
- }
- if (!Sets.intersection(statuses, CLOSED_STATUSES).isEmpty()) {
- indexes.add(CLOSED_CHANGES);
- }
- }
- return new QuerySource(indexes, p, opts);
- }
-
- @Override
- protected String getDeleteActions(Id c) {
- if (client.adapter().usePostV5Type()) {
- return delete(ElasticQueryAdapter.POST_V5_TYPE, c);
- }
- return delete(OPEN_CHANGES, c) + delete(CLOSED_CHANGES, c);
- }
-
- @Override
- protected String getMappings() {
- if (client.adapter().usePostV5Type()) {
- return getMappingsFor(ElasticQueryAdapter.POST_V5_TYPE, mapping.changes);
- }
- return gson.toJson(ImmutableMap.of(MAPPINGS, mapping));
- }
-
- @Override
- protected String getId(ChangeData cd) {
- return cd.getId().toString();
- }
-
- private class QuerySource implements ChangeDataSource {
- private final String search;
- private final Set<String> fields;
- private final List<String> types;
-
- QuerySource(List<String> types, Predicate<ChangeData> p, QueryOptions opts)
- throws QueryParseException {
- QueryBuilder qb = queryBuilder.toQueryBuilder(p);
- fields = IndexUtils.changeFields(opts);
- SearchSourceBuilder searchSource =
- new SearchSourceBuilder(client.adapter())
- .query(qb)
- .from(opts.start())
- .size(opts.limit())
- .fields(Lists.newArrayList(fields));
-
- search = getSearch(searchSource, getSortArray());
- this.types = types;
- }
-
- @Override
- public int getCardinality() {
- return 10;
- }
-
- @Override
- public ResultSet<ChangeData> read() throws OrmException {
- try {
- List<ChangeData> results = Collections.emptyList();
- String uri = getURI(types);
- Response response = postRequest(uri, search);
- StatusLine statusLine = response.getStatusLine();
- if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
- String content = getContent(response);
- JsonObject obj =
- new JsonParser().parse(content).getAsJsonObject().getAsJsonObject("hits");
- if (obj.get("hits") != null) {
- JsonArray json = obj.getAsJsonArray("hits");
- results = Lists.newArrayListWithCapacity(json.size());
- for (int i = 0; i < json.size(); i++) {
- results.add(toChangeData(json.get(i)));
- }
- }
- } else {
- log.error(statusLine.getReasonPhrase());
- }
- final List<ChangeData> r = Collections.unmodifiableList(results);
- return new ResultSet<ChangeData>() {
- @Override
- public Iterator<ChangeData> iterator() {
- return r.iterator();
- }
-
- @Override
- public List<ChangeData> toList() {
- return r;
- }
-
- @Override
- public void close() {
- // Do nothing.
- }
- };
- } catch (IOException e) {
- throw new OrmException(e);
- }
- }
-
- @Override
- public boolean hasChange() {
- return false;
- }
-
- private ChangeData toChangeData(JsonElement json) {
- JsonElement sourceElement = json.getAsJsonObject().get("_source");
- if (sourceElement == null) {
- sourceElement = json.getAsJsonObject().get("fields");
- }
- JsonObject source = sourceElement.getAsJsonObject();
- JsonElement c = source.get(ChangeField.CHANGE.getName());
-
- if (c == null) {
- int id = source.get(ChangeField.LEGACY_ID.getName()).getAsInt();
- // IndexUtils#changeFields ensures either CHANGE or PROJECT is always present.
- String projectName = checkNotNull(source.get(ChangeField.PROJECT.getName()).getAsString());
- return changeDataFactory.create(
- db.get(), new Project.NameKey(projectName), new Change.Id(id));
- }
-
- ChangeData cd =
- changeDataFactory.create(
- db.get(), CHANGE_CODEC.decode(Base64.decodeBase64(c.getAsString())));
-
- // Patch sets.
- cd.setPatchSets(decodeProtos(source, ChangeField.PATCH_SET.getName(), PATCH_SET_CODEC));
-
- // Approvals.
- if (source.get(ChangeField.APPROVAL.getName()) != null) {
- cd.setCurrentApprovals(
- decodeProtos(source, ChangeField.APPROVAL.getName(), APPROVAL_CODEC));
- } else if (fields.contains(ChangeField.APPROVAL.getName())) {
- cd.setCurrentApprovals(Collections.emptyList());
- }
-
- JsonElement addedElement = source.get(ChangeField.ADDED.getName());
- JsonElement deletedElement = source.get(ChangeField.DELETED.getName());
- if (addedElement != null && deletedElement != null) {
- // Changed lines.
- int added = addedElement.getAsInt();
- int deleted = deletedElement.getAsInt();
- cd.setChangedLines(added, deleted);
- }
-
- // Star.
- JsonElement starredElement = source.get(ChangeField.STAR.getName());
- if (starredElement != null) {
- ListMultimap<Account.Id, String> stars =
- MultimapBuilder.hashKeys().arrayListValues().build();
- JsonArray starBy = starredElement.getAsJsonArray();
- if (starBy.size() > 0) {
- for (int i = 0; i < starBy.size(); i++) {
- String[] indexableFields = starBy.get(i).getAsString().split(":");
- Account.Id id = Account.Id.parse(indexableFields[0]);
- stars.put(id, indexableFields[1]);
- }
- }
- cd.setStars(stars);
- }
-
- // Mergeable.
- JsonElement mergeableElement = source.get(ChangeField.MERGEABLE.getName());
- if (mergeableElement != null) {
- String mergeable = mergeableElement.getAsString();
- if ("1".equals(mergeable)) {
- cd.setMergeable(true);
- } else if ("0".equals(mergeable)) {
- cd.setMergeable(false);
- }
- }
-
- // Reviewed-by.
- if (source.get(ChangeField.REVIEWEDBY.getName()) != null) {
- JsonArray reviewedBy = source.get(ChangeField.REVIEWEDBY.getName()).getAsJsonArray();
- if (reviewedBy.size() > 0) {
- Set<Account.Id> accounts = Sets.newHashSetWithExpectedSize(reviewedBy.size());
- for (int i = 0; i < reviewedBy.size(); i++) {
- int aId = reviewedBy.get(i).getAsInt();
- if (reviewedBy.size() == 1 && aId == ChangeField.NOT_REVIEWED) {
- break;
- }
- accounts.add(new Account.Id(aId));
- }
- cd.setReviewedBy(accounts);
- }
- } else if (fields.contains(ChangeField.REVIEWEDBY.getName())) {
- cd.setReviewedBy(Collections.emptySet());
- }
-
- if (source.get(ChangeField.REVIEWER.getName()) != null) {
- cd.setReviewers(
- ChangeField.parseReviewerFieldValues(
- FluentIterable.from(source.get(ChangeField.REVIEWER.getName()).getAsJsonArray())
- .transform(JsonElement::getAsString)));
- } else if (fields.contains(ChangeField.REVIEWER.getName())) {
- cd.setReviewers(ReviewerSet.empty());
- }
-
- if (source.get(ChangeField.REVIEWER_BY_EMAIL.getName()) != null) {
- cd.setReviewersByEmail(
- ChangeField.parseReviewerByEmailFieldValues(
- FluentIterable.from(
- source.get(ChangeField.REVIEWER_BY_EMAIL.getName()).getAsJsonArray())
- .transform(JsonElement::getAsString)));
- } else if (fields.contains(ChangeField.REVIEWER_BY_EMAIL.getName())) {
- cd.setReviewersByEmail(ReviewerByEmailSet.empty());
- }
-
- if (source.get(ChangeField.PENDING_REVIEWER.getName()) != null) {
- cd.setPendingReviewers(
- ChangeField.parseReviewerFieldValues(
- FluentIterable.from(
- source.get(ChangeField.PENDING_REVIEWER.getName()).getAsJsonArray())
- .transform(JsonElement::getAsString)));
- } else if (fields.contains(ChangeField.PENDING_REVIEWER.getName())) {
- cd.setPendingReviewers(ReviewerSet.empty());
- }
-
- if (source.get(ChangeField.PENDING_REVIEWER_BY_EMAIL.getName()) != null) {
- cd.setPendingReviewersByEmail(
- ChangeField.parseReviewerByEmailFieldValues(
- FluentIterable.from(
- source
- .get(ChangeField.PENDING_REVIEWER_BY_EMAIL.getName())
- .getAsJsonArray())
- .transform(JsonElement::getAsString)));
- } else if (fields.contains(ChangeField.PENDING_REVIEWER_BY_EMAIL.getName())) {
- cd.setPendingReviewersByEmail(ReviewerByEmailSet.empty());
- }
- decodeSubmitRecords(
- source,
- ChangeField.STORED_SUBMIT_RECORD_STRICT.getName(),
- ChangeField.SUBMIT_RULE_OPTIONS_STRICT,
- cd);
- decodeSubmitRecords(
- source,
- ChangeField.STORED_SUBMIT_RECORD_LENIENT.getName(),
- ChangeField.SUBMIT_RULE_OPTIONS_LENIENT,
- cd);
- decodeUnresolvedCommentCount(source, ChangeField.UNRESOLVED_COMMENT_COUNT.getName(), cd);
-
- if (fields.contains(ChangeField.REF_STATE.getName())) {
- cd.setRefStates(getByteArray(source, ChangeField.REF_STATE.getName()));
- }
- if (fields.contains(ChangeField.REF_STATE_PATTERN.getName())) {
- cd.setRefStatePatterns(getByteArray(source, ChangeField.REF_STATE_PATTERN.getName()));
- }
-
- return cd;
- }
-
- private Iterable<byte[]> getByteArray(JsonObject source, String name) {
- JsonElement element = source.get(name);
- return element != null
- ? Iterables.transform(element.getAsJsonArray(), e -> Base64.decodeBase64(e.getAsString()))
- : Collections.emptyList();
- }
-
- private void decodeSubmitRecords(
- JsonObject doc, String fieldName, SubmitRuleOptions opts, ChangeData out) {
- JsonArray records = doc.getAsJsonArray(fieldName);
- if (records == null) {
- return;
- }
- ChangeField.parseSubmitRecords(
- FluentIterable.from(records)
- .transform(i -> new String(decodeBase64(i.toString()), UTF_8))
- .toList(),
- opts,
- out);
- }
-
- private void decodeUnresolvedCommentCount(JsonObject doc, String fieldName, ChangeData out) {
- JsonElement count = doc.get(fieldName);
- if (count == null) {
- return;
- }
- out.setUnresolvedCommentCount(count.getAsInt());
- }
-
- private JsonArray getSortArray() {
- JsonObject properties = new JsonObject();
- properties.addProperty(ORDER, "desc");
- client.adapter().setIgnoreUnmapped(properties);
-
- JsonArray sortArray = new JsonArray();
- addNamedElement(ChangeField.UPDATED.getName(), properties, sortArray);
- addNamedElement(ChangeField.LEGACY_ID.getName(), properties, sortArray);
- return sortArray;
- }
- }
-
- private String getURI(List<String> types) throws UnsupportedEncodingException {
- String joinedTypes = String.join(",", types);
- return getURI(joinedTypes, SEARCH);
- }
-}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
deleted file mode 100644
index 79701e1..0000000
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright (C) 2017 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.elasticsearch;
-
-import com.google.common.collect.Lists;
-import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
-import com.google.gerrit.elasticsearch.builders.QueryBuilder;
-import com.google.gerrit.elasticsearch.builders.SearchSourceBuilder;
-import com.google.gerrit.elasticsearch.bulk.BulkRequest;
-import com.google.gerrit.elasticsearch.bulk.IndexRequest;
-import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
-import com.google.gerrit.index.QueryOptions;
-import com.google.gerrit.index.Schema;
-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.account.GroupCache;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.group.InternalGroup;
-import com.google.gerrit.server.index.IndexUtils;
-import com.google.gerrit.server.index.group.GroupField;
-import com.google.gerrit.server.index.group.GroupIndex;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.ResultSet;
-import com.google.inject.Provider;
-import com.google.inject.assistedinject.Assisted;
-import com.google.inject.assistedinject.AssistedInject;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import org.apache.http.HttpStatus;
-import org.apache.http.StatusLine;
-import org.elasticsearch.client.Response;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ElasticGroupIndex extends AbstractElasticIndex<AccountGroup.UUID, InternalGroup>
- implements GroupIndex {
- private static final Logger log = LoggerFactory.getLogger(ElasticGroupIndex.class);
-
- static class GroupMapping {
- final MappingProperties groups;
-
- GroupMapping(Schema<InternalGroup> schema, ElasticQueryAdapter adapter) {
- this.groups = ElasticMapping.createMapping(schema, adapter);
- }
- }
-
- private static final String GROUPS = "groups";
-
- private final GroupMapping mapping;
- private final Provider<GroupCache> groupCache;
- private final Schema<InternalGroup> schema;
-
- @AssistedInject
- ElasticGroupIndex(
- ElasticConfiguration cfg,
- SitePaths sitePaths,
- Provider<GroupCache> groupCache,
- ElasticRestClientProvider client,
- @Assisted Schema<InternalGroup> schema) {
- super(cfg, sitePaths, schema, client, GROUPS);
- this.groupCache = groupCache;
- this.mapping = new GroupMapping(schema, client.adapter());
- this.schema = schema;
- }
-
- @Override
- public void replace(InternalGroup group) throws IOException {
- BulkRequest bulk =
- new IndexRequest(getId(group), indexName, type, client.adapter())
- .add(new UpdateRequest<>(schema, group));
-
- String uri = getURI(type, BULK);
- Response response = postRequest(uri, bulk, getRefreshParam());
- int statusCode = response.getStatusLine().getStatusCode();
- if (statusCode != HttpStatus.SC_OK) {
- throw new IOException(
- String.format(
- "Failed to replace group %s in index %s: %s",
- group.getGroupUUID().get(), indexName, statusCode));
- }
- }
-
- @Override
- public DataSource<InternalGroup> getSource(Predicate<InternalGroup> p, QueryOptions opts)
- throws QueryParseException {
- return new QuerySource(p, opts);
- }
-
- @Override
- protected String getDeleteActions(AccountGroup.UUID g) {
- return delete(type, g);
- }
-
- @Override
- protected String getMappings() {
- return getMappingsForSingleType(GROUPS, mapping.groups);
- }
-
- @Override
- protected String getId(InternalGroup group) {
- return group.getGroupUUID().get();
- }
-
- private class QuerySource implements DataSource<InternalGroup> {
- private final String search;
- private final Set<String> fields;
-
- QuerySource(Predicate<InternalGroup> p, QueryOptions opts) throws QueryParseException {
- QueryBuilder qb = queryBuilder.toQueryBuilder(p);
- fields = IndexUtils.groupFields(opts);
- SearchSourceBuilder searchSource =
- new SearchSourceBuilder(client.adapter())
- .query(qb)
- .from(opts.start())
- .size(opts.limit())
- .fields(Lists.newArrayList(fields));
-
- JsonArray sortArray = getSortArray(GroupField.UUID.getName());
- search = getSearch(searchSource, sortArray);
- }
-
- @Override
- public int getCardinality() {
- return 10;
- }
-
- @Override
- public ResultSet<InternalGroup> read() throws OrmException {
- try {
- List<InternalGroup> results = Collections.emptyList();
- String uri = getURI(type, SEARCH);
- Response response = postRequest(uri, search);
- StatusLine statusLine = response.getStatusLine();
- if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
- String content = getContent(response);
- JsonObject obj =
- new JsonParser().parse(content).getAsJsonObject().getAsJsonObject("hits");
- if (obj.get("hits") != null) {
- JsonArray json = obj.getAsJsonArray("hits");
- results = Lists.newArrayListWithCapacity(json.size());
- for (int i = 0; i < json.size(); i++) {
- results.add(toAccountGroup(json.get(i)).get());
- }
- }
- } else {
- log.error(statusLine.getReasonPhrase());
- }
- final List<InternalGroup> r = Collections.unmodifiableList(results);
- return new ResultSet<InternalGroup>() {
- @Override
- public Iterator<InternalGroup> iterator() {
- return r.iterator();
- }
-
- @Override
- public List<InternalGroup> toList() {
- return r;
- }
-
- @Override
- public void close() {
- // Do nothing.
- }
- };
- } catch (IOException e) {
- throw new OrmException(e);
- }
- }
-
- private Optional<InternalGroup> toAccountGroup(JsonElement json) {
- JsonElement source = json.getAsJsonObject().get("_source");
- if (source == null) {
- source = json.getAsJsonObject().get("fields");
- }
-
- AccountGroup.UUID uuid =
- new AccountGroup.UUID(
- source.getAsJsonObject().get(GroupField.UUID.getName()).getAsString());
- // Use the GroupCache rather than depending on any stored fields in the
- // document (of which there shouldn't be any).
- return groupCache.get().get(uuid);
- }
- }
-}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
similarity index 63%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
rename to java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index c21299f..3b589b2 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -14,45 +14,70 @@
package com.google.gerrit.elasticsearch;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gson.FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.codec.binary.Base64.decodeBase64;
+import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.flogger.FluentLogger;
import com.google.common.io.CharStreams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
+import com.google.gerrit.elasticsearch.builders.QueryBuilder;
import com.google.gerrit.elasticsearch.builders.SearchSourceBuilder;
import com.google.gerrit.elasticsearch.bulk.DeleteRequest;
+import com.google.gerrit.index.FieldDef;
+import com.google.gerrit.index.FieldType;
import com.google.gerrit.index.Index;
+import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.Schema;
+import com.google.gerrit.index.query.DataSource;
+import com.google.gerrit.index.query.FieldBundle;
+import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.index.IndexUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gwtorm.protobuf.ProtobufCodec;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.sql.Timestamp;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
+import org.apache.http.StatusLine;
+import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
protected static final String BULK = "_bulk";
protected static final String MAPPINGS = "mappings";
protected static final String ORDER = "order";
@@ -197,6 +222,50 @@
return new DeleteRequest(id.toString(), indexName, type, client.adapter()).toString();
}
+ protected abstract V fromDocument(JsonObject doc, Set<String> fields);
+
+ protected FieldBundle toFieldBundle(JsonObject doc) {
+ Map<String, FieldDef<V, ?>> allFields = getSchema().getFields();
+ ListMultimap<String, Object> rawFields = ArrayListMultimap.create();
+ for (Map.Entry<String, JsonElement> element :
+ doc.get(client.adapter().rawFieldsKey()).getAsJsonObject().entrySet()) {
+ checkArgument(
+ allFields.containsKey(element.getKey()), "Unrecognized field " + element.getKey());
+ FieldType<?> type = allFields.get(element.getKey()).getType();
+ Iterable<JsonElement> innerItems =
+ element.getValue().isJsonArray()
+ ? element.getValue().getAsJsonArray()
+ : Collections.singleton(element.getValue());
+ for (JsonElement inner : innerItems) {
+ if (type == FieldType.EXACT || type == FieldType.FULL_TEXT || type == FieldType.PREFIX) {
+ rawFields.put(element.getKey(), inner.getAsString());
+ } else if (type == FieldType.INTEGER || type == FieldType.INTEGER_RANGE) {
+ rawFields.put(element.getKey(), inner.getAsInt());
+ } else if (type == FieldType.LONG) {
+ rawFields.put(element.getKey(), inner.getAsLong());
+ } else if (type == FieldType.TIMESTAMP) {
+ rawFields.put(element.getKey(), new Timestamp(inner.getAsLong()));
+ } else if (type == FieldType.STORED_ONLY) {
+ rawFields.put(element.getKey(), Base64.decodeBase64(inner.getAsString()));
+ } else {
+ throw FieldType.badFieldType(type);
+ }
+ }
+ }
+ return new FieldBundle(rawFields);
+ }
+
+ protected String toAction(String type, String id, String action) {
+ JsonObject properties = new JsonObject();
+ properties.addProperty("_id", id);
+ properties.addProperty("_index", indexName);
+ properties.addProperty("_type", type);
+
+ JsonObject jsonAction = new JsonObject();
+ jsonAction.add(action, properties);
+ return jsonAction.toString() + System.lineSeparator();
+ }
+
protected void addNamedElement(String name, JsonObject element, JsonArray array) {
JsonObject arrayElement = new JsonObject();
arrayElement.add(name, element);
@@ -269,4 +338,85 @@
}
return client.get().performRequest(request);
}
+
+ protected class ElasticQuerySource implements DataSource<V> {
+ private final QueryOptions opts;
+ private final String search;
+ private final String index;
+
+ ElasticQuerySource(Predicate<V> p, QueryOptions opts, String index, JsonArray sortArray)
+ throws QueryParseException {
+ this.opts = opts;
+ this.index = index;
+ QueryBuilder qb = queryBuilder.toQueryBuilder(p);
+ SearchSourceBuilder searchSource =
+ new SearchSourceBuilder(client.adapter())
+ .query(qb)
+ .from(opts.start())
+ .size(opts.limit())
+ .fields(Lists.newArrayList(opts.fields()));
+ search = getSearch(searchSource, sortArray);
+ }
+
+ @Override
+ public int getCardinality() {
+ return 10;
+ }
+
+ @Override
+ public ResultSet<V> read() throws OrmException {
+ return readImpl((doc) -> AbstractElasticIndex.this.fromDocument(doc, opts.fields()));
+ }
+
+ @Override
+ public ResultSet<FieldBundle> readRaw() throws OrmException {
+ return readImpl(AbstractElasticIndex.this::toFieldBundle);
+ }
+
+ private <T> ResultSet<T> readImpl(Function<JsonObject, T> mapper) throws OrmException {
+ try {
+ List<T> results = Collections.emptyList();
+ String uri = getURI(index, SEARCH);
+ Response response =
+ performRequest(HttpPost.METHOD_NAME, uri, search, Collections.emptyMap());
+ StatusLine statusLine = response.getStatusLine();
+ if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
+ String content = getContent(response);
+ JsonObject obj =
+ new JsonParser().parse(content).getAsJsonObject().getAsJsonObject("hits");
+ if (obj.get("hits") != null) {
+ JsonArray json = obj.getAsJsonArray("hits");
+ results = Lists.newArrayListWithCapacity(json.size());
+ for (int i = 0; i < json.size(); i++) {
+ T mapperResult = mapper.apply(json.get(i).getAsJsonObject());
+ if (mapperResult != null) {
+ results.add(mapperResult);
+ }
+ }
+ }
+ } else {
+ logger.atSevere().log(statusLine.getReasonPhrase());
+ }
+ final List<T> r = Collections.unmodifiableList(results);
+ return new ResultSet<T>() {
+ @Override
+ public Iterator<T> iterator() {
+ return r.iterator();
+ }
+
+ @Override
+ public List<T> toList() {
+ return r;
+ }
+
+ @Override
+ public void close() {
+ // Do nothing.
+ }
+ };
+ } catch (IOException e) {
+ throw new OrmException(e);
+ }
+ }
+ }
}
diff --git a/java/com/google/gerrit/elasticsearch/BUILD b/java/com/google/gerrit/elasticsearch/BUILD
new file mode 100644
index 0000000..8d23051
--- /dev/null
+++ b/java/com/google/gerrit/elasticsearch/BUILD
@@ -0,0 +1,31 @@
+java_library(
+ name = "elasticsearch",
+ srcs = glob(["**/*.java"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/common:annotations",
+ "//java/com/google/gerrit/extensions:api",
+ "//java/com/google/gerrit/index",
+ "//java/com/google/gerrit/index:query_exception",
+ "//java/com/google/gerrit/index/project",
+ "//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/reviewdb:server",
+ "//java/com/google/gerrit/server",
+ "//lib:gson",
+ "//lib:guava",
+ "//lib:gwtorm",
+ "//lib:protobuf",
+ "//lib/commons:codec",
+ "//lib/commons:lang",
+ "//lib/elasticsearch-rest-client",
+ "//lib/flogger:api",
+ "//lib/guice",
+ "//lib/guice:guice-assistedinject",
+ "//lib/httpcomponents:httpasyncclient",
+ "//lib/httpcomponents:httpclient",
+ "//lib/httpcomponents:httpcore",
+ "//lib/httpcomponents:httpcore-nio",
+ "//lib/jackson:jackson-core",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+ ],
+)
diff --git a/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java b/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
new file mode 100644
index 0000000..1b69b6d
--- /dev/null
+++ b/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
@@ -0,0 +1,130 @@
+// 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.elasticsearch;
+
+import static com.google.gerrit.server.index.account.AccountField.ID;
+
+import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
+import com.google.gerrit.elasticsearch.bulk.BulkRequest;
+import com.google.gerrit.elasticsearch.bulk.IndexRequest;
+import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.Schema;
+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.AccountCache;
+import com.google.gerrit.server.account.AccountState;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.index.IndexUtils;
+import com.google.gerrit.server.index.account.AccountField;
+import com.google.gerrit.server.index.account.AccountIndex;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.assistedinject.Assisted;
+import java.io.IOException;
+import java.util.Set;
+import org.apache.http.HttpStatus;
+import org.elasticsearch.client.Response;
+
+public class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, AccountState>
+ implements AccountIndex {
+ static class AccountMapping {
+ final MappingProperties accounts;
+
+ AccountMapping(Schema<AccountState> schema, ElasticQueryAdapter adapter) {
+ this.accounts = ElasticMapping.createMapping(schema, adapter);
+ }
+ }
+
+ private static final String ACCOUNTS = "accounts";
+
+ private final AccountMapping mapping;
+ private final Provider<AccountCache> accountCache;
+ private final Schema<AccountState> schema;
+
+ @Inject
+ ElasticAccountIndex(
+ ElasticConfiguration cfg,
+ SitePaths sitePaths,
+ Provider<AccountCache> accountCache,
+ ElasticRestClientProvider client,
+ @Assisted Schema<AccountState> schema) {
+ super(cfg, sitePaths, schema, client, ACCOUNTS);
+ this.accountCache = accountCache;
+ this.mapping = new AccountMapping(schema, client.adapter());
+ this.schema = schema;
+ }
+
+ @Override
+ public void replace(AccountState as) throws IOException {
+ BulkRequest bulk =
+ new IndexRequest(getId(as), indexName, type, client.adapter())
+ .add(new UpdateRequest<>(schema, as));
+
+ String uri = getURI(type, BULK);
+ Response response = postRequest(uri, bulk, getRefreshParam());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode != HttpStatus.SC_OK) {
+ throw new IOException(
+ String.format(
+ "Failed to replace account %s in index %s: %s",
+ as.getAccount().getId(), indexName, statusCode));
+ }
+ }
+
+ @Override
+ public DataSource<AccountState> getSource(Predicate<AccountState> p, QueryOptions opts)
+ throws QueryParseException {
+ JsonArray sortArray = getSortArray(AccountField.ID.getName());
+ return new ElasticQuerySource(
+ p, opts.filterFields(IndexUtils::accountFields), ACCOUNTS, sortArray);
+ }
+
+ @Override
+ protected String getDeleteActions(Account.Id a) {
+ return delete(type, a);
+ }
+
+ @Override
+ protected String getMappings() {
+ return getMappingsForSingleType(ACCOUNTS, mapping.accounts);
+ }
+
+ @Override
+ protected String getId(AccountState as) {
+ return as.getAccount().getId().toString();
+ }
+
+ @Override
+ protected AccountState fromDocument(JsonObject json, Set<String> fields) {
+ JsonElement source = json.get("_source");
+ if (source == null) {
+ source = json.getAsJsonObject().get("fields");
+ }
+
+ Account.Id id = new Account.Id(source.getAsJsonObject().get(ID.getName()).getAsInt());
+ // Use the AccountCache rather than depending on any stored fields in the document (of which
+ // there shouldn't be any). The most expensive part to compute anyway is the effective group
+ // IDs, and we don't have a good way to reindex when those change.
+ // If the account doesn't exist return an empty AccountState to represent the missing account
+ // to account the fact that the account exists in the index.
+ return accountCache.get().getEvenIfMissing(id);
+ }
+}
diff --git a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
new file mode 100644
index 0000000..1224c61
--- /dev/null
+++ b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
@@ -0,0 +1,434 @@
+// 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.elasticsearch;
+
+import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.APPROVAL_CODEC;
+import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.CHANGE_CODEC;
+import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.PATCH_SET_CODEC;
+import static com.google.gerrit.server.index.change.ChangeIndexRewriter.CLOSED_STATUSES;
+import static com.google.gerrit.server.index.change.ChangeIndexRewriter.OPEN_STATUSES;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.codec.binary.Base64.decodeBase64;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.Sets;
+import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
+import com.google.gerrit.elasticsearch.bulk.BulkRequest;
+import com.google.gerrit.elasticsearch.bulk.DeleteRequest;
+import com.google.gerrit.elasticsearch.bulk.IndexRequest;
+import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.Schema;
+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.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.ReviewerByEmailSet;
+import com.google.gerrit.server.ReviewerSet;
+import com.google.gerrit.server.StarredChangesUtil;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.index.IndexUtils;
+import com.google.gerrit.server.index.change.ChangeField;
+import com.google.gerrit.server.index.change.ChangeIndex;
+import com.google.gerrit.server.index.change.ChangeIndexRewriter;
+import com.google.gerrit.server.project.SubmitRuleOptions;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.assistedinject.Assisted;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.http.HttpStatus;
+import org.elasticsearch.client.Response;
+
+/** Secondary index implementation using Elasticsearch. */
+class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
+ implements ChangeIndex {
+ static class ChangeMapping {
+ final MappingProperties changes;
+ final MappingProperties openChanges;
+ final MappingProperties closedChanges;
+
+ ChangeMapping(Schema<ChangeData> schema, ElasticQueryAdapter adapter) {
+ MappingProperties mapping = ElasticMapping.createMapping(schema, adapter);
+ this.changes = mapping;
+ this.openChanges = mapping;
+ this.closedChanges = mapping;
+ }
+ }
+
+ private static final String CHANGES = "changes";
+ private static final String OPEN_CHANGES = "open_" + CHANGES;
+ private static final String CLOSED_CHANGES = "closed_" + CHANGES;
+
+ private final ChangeMapping mapping;
+ private final Provider<ReviewDb> db;
+ private final ChangeData.Factory changeDataFactory;
+ private final Schema<ChangeData> schema;
+
+ @Inject
+ ElasticChangeIndex(
+ ElasticConfiguration cfg,
+ Provider<ReviewDb> db,
+ ChangeData.Factory changeDataFactory,
+ SitePaths sitePaths,
+ ElasticRestClientProvider clientBuilder,
+ @Assisted Schema<ChangeData> schema) {
+ super(cfg, sitePaths, schema, clientBuilder, CHANGES);
+ this.db = db;
+ this.changeDataFactory = changeDataFactory;
+ this.schema = schema;
+ mapping = new ChangeMapping(schema, client.adapter());
+ }
+
+ @Override
+ public void replace(ChangeData cd) throws IOException {
+ String deleteIndex;
+ String insertIndex;
+
+ try {
+ if (cd.change().getStatus().isOpen()) {
+ insertIndex = OPEN_CHANGES;
+ deleteIndex = CLOSED_CHANGES;
+ } else {
+ insertIndex = CLOSED_CHANGES;
+ deleteIndex = OPEN_CHANGES;
+ }
+ } catch (OrmException e) {
+ throw new IOException(e);
+ }
+
+ ElasticQueryAdapter adapter = client.adapter();
+ BulkRequest bulk =
+ new IndexRequest(getId(cd), indexName, adapter.getType(insertIndex), adapter)
+ .add(new UpdateRequest<>(schema, cd));
+ if (!adapter.usePostV5Type()) {
+ bulk.add(new DeleteRequest(cd.getId().toString(), indexName, deleteIndex, adapter));
+ }
+
+ String uri = getURI(type, BULK);
+ Response response = postRequest(uri, bulk, getRefreshParam());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode != HttpStatus.SC_OK) {
+ throw new IOException(
+ String.format(
+ "Failed to replace change %s in index %s: %s", cd.getId(), indexName, statusCode));
+ }
+ }
+
+ @Override
+ public DataSource<ChangeData> getSource(Predicate<ChangeData> p, QueryOptions opts)
+ throws QueryParseException {
+ Set<Change.Status> statuses = ChangeIndexRewriter.getPossibleStatus(p);
+ List<String> indexes = Lists.newArrayListWithCapacity(2);
+ if (client.adapter().usePostV5Type()) {
+ if (!Sets.intersection(statuses, OPEN_STATUSES).isEmpty()
+ || !Sets.intersection(statuses, CLOSED_STATUSES).isEmpty()) {
+ indexes.add(ElasticQueryAdapter.POST_V5_TYPE);
+ }
+ } else {
+ if (!Sets.intersection(statuses, OPEN_STATUSES).isEmpty()) {
+ indexes.add(OPEN_CHANGES);
+ }
+ if (!Sets.intersection(statuses, CLOSED_STATUSES).isEmpty()) {
+ indexes.add(CLOSED_CHANGES);
+ }
+ }
+
+ QueryOptions filteredOpts = opts.filterFields(IndexUtils::changeFields);
+ return new ElasticQuerySource(p, filteredOpts, getURI(indexes), getSortArray());
+ }
+
+ private JsonArray getSortArray() {
+ JsonObject properties = new JsonObject();
+ properties.addProperty(ORDER, "desc");
+ client.adapter().setIgnoreUnmapped(properties);
+
+ JsonArray sortArray = new JsonArray();
+ addNamedElement(ChangeField.UPDATED.getName(), properties, sortArray);
+ addNamedElement(ChangeField.LEGACY_ID.getName(), properties, sortArray);
+ return sortArray;
+ }
+
+ private String getURI(List<String> types) {
+ return String.join(",", types);
+ }
+
+ @Override
+ protected String getDeleteActions(Id c) {
+ if (client.adapter().usePostV5Type()) {
+ return delete(ElasticQueryAdapter.POST_V5_TYPE, c);
+ }
+ return delete(OPEN_CHANGES, c) + delete(CLOSED_CHANGES, c);
+ }
+
+ @Override
+ protected String getMappings() {
+ if (client.adapter().usePostV5Type()) {
+ return getMappingsFor(ElasticQueryAdapter.POST_V5_TYPE, mapping.changes);
+ }
+ return gson.toJson(ImmutableMap.of(MAPPINGS, mapping));
+ }
+
+ @Override
+ protected String getId(ChangeData cd) {
+ return cd.getId().toString();
+ }
+
+ @Override
+ protected ChangeData fromDocument(JsonObject json, Set<String> fields) {
+ JsonElement sourceElement = json.get("_source");
+ if (sourceElement == null) {
+ sourceElement = json.getAsJsonObject().get("fields");
+ }
+ JsonObject source = sourceElement.getAsJsonObject();
+ JsonElement c = source.get(ChangeField.CHANGE.getName());
+
+ if (c == null) {
+ int id = source.get(ChangeField.LEGACY_ID.getName()).getAsInt();
+ // IndexUtils#changeFields ensures either CHANGE or PROJECT is always present.
+ String projectName = requireNonNull(source.get(ChangeField.PROJECT.getName()).getAsString());
+ return changeDataFactory.create(
+ db.get(), new Project.NameKey(projectName), new Change.Id(id));
+ }
+
+ ChangeData cd =
+ changeDataFactory.create(
+ db.get(), CHANGE_CODEC.decode(Base64.decodeBase64(c.getAsString())));
+
+ // Any decoding that is done here must also be done in {@link LuceneChangeIndex}.
+
+ // Patch sets.
+ cd.setPatchSets(decodeProtos(source, ChangeField.PATCH_SET.getName(), PATCH_SET_CODEC));
+
+ // Approvals.
+ if (source.get(ChangeField.APPROVAL.getName()) != null) {
+ cd.setCurrentApprovals(decodeProtos(source, ChangeField.APPROVAL.getName(), APPROVAL_CODEC));
+ } else if (fields.contains(ChangeField.APPROVAL.getName())) {
+ cd.setCurrentApprovals(Collections.emptyList());
+ }
+
+ // Added & Deleted.
+ JsonElement addedElement = source.get(ChangeField.ADDED.getName());
+ JsonElement deletedElement = source.get(ChangeField.DELETED.getName());
+ if (addedElement != null && deletedElement != null) {
+ // Changed lines.
+ int added = addedElement.getAsInt();
+ int deleted = deletedElement.getAsInt();
+ cd.setChangedLines(added, deleted);
+ }
+
+ // Star.
+ JsonElement starredElement = source.get(ChangeField.STAR.getName());
+ if (starredElement != null) {
+ ListMultimap<Account.Id, String> stars = MultimapBuilder.hashKeys().arrayListValues().build();
+ JsonArray starBy = starredElement.getAsJsonArray();
+ if (starBy.size() > 0) {
+ for (int i = 0; i < starBy.size(); i++) {
+ String[] indexableFields = starBy.get(i).getAsString().split(":");
+ Optional<Account.Id> id = Account.Id.tryParse(indexableFields[0]);
+ if (id.isPresent()) {
+ stars.put(id.get(), indexableFields[1]);
+ }
+ }
+ }
+ cd.setStars(stars);
+ }
+
+ // Mergeable.
+ JsonElement mergeableElement = source.get(ChangeField.MERGEABLE.getName());
+ if (mergeableElement != null) {
+ String mergeable = mergeableElement.getAsString();
+ if ("1".equals(mergeable)) {
+ cd.setMergeable(true);
+ } else if ("0".equals(mergeable)) {
+ cd.setMergeable(false);
+ }
+ }
+
+ // Reviewed-by.
+ if (source.get(ChangeField.REVIEWEDBY.getName()) != null) {
+ JsonArray reviewedBy = source.get(ChangeField.REVIEWEDBY.getName()).getAsJsonArray();
+ if (reviewedBy.size() > 0) {
+ Set<Account.Id> accounts = Sets.newHashSetWithExpectedSize(reviewedBy.size());
+ for (int i = 0; i < reviewedBy.size(); i++) {
+ int aId = reviewedBy.get(i).getAsInt();
+ if (reviewedBy.size() == 1 && aId == ChangeField.NOT_REVIEWED) {
+ break;
+ }
+ accounts.add(new Account.Id(aId));
+ }
+ cd.setReviewedBy(accounts);
+ }
+ } else if (fields.contains(ChangeField.REVIEWEDBY.getName())) {
+ cd.setReviewedBy(Collections.emptySet());
+ }
+
+ // Hashtag.
+ if (source.get(ChangeField.HASHTAG.getName()) != null) {
+ JsonArray hashtagArray = source.get(ChangeField.HASHTAG.getName()).getAsJsonArray();
+ if (hashtagArray.size() > 0) {
+ Set<String> hashtags = Sets.newHashSetWithExpectedSize(hashtagArray.size());
+ for (int i = 0; i < hashtagArray.size(); i++) {
+ hashtags.add(hashtagArray.get(i).getAsString());
+ }
+ cd.setHashtags(hashtags);
+ }
+ } else if (fields.contains(ChangeField.HASHTAG.getName())) {
+ cd.setHashtags(Collections.emptySet());
+ }
+
+ // Star.
+ if (source.get(ChangeField.STAR.getName()) != null) {
+ JsonArray starArray = source.get(ChangeField.STAR.getName()).getAsJsonArray();
+ if (starArray.size() > 0) {
+ ListMultimap<Account.Id, String> stars =
+ MultimapBuilder.hashKeys().arrayListValues().build();
+ for (int i = 0; i < starArray.size(); i++) {
+ StarredChangesUtil.StarField starField =
+ StarredChangesUtil.StarField.parse(starArray.get(i).getAsString());
+ stars.put(starField.accountId(), starField.label());
+ }
+ cd.setStars(stars);
+ }
+ } else if (fields.contains(ChangeField.STAR.getName())) {
+ cd.setStars(ImmutableListMultimap.of());
+ }
+
+ // Reviewer.
+ if (source.get(ChangeField.REVIEWER.getName()) != null) {
+ cd.setReviewers(
+ ChangeField.parseReviewerFieldValues(
+ cd.getId(),
+ FluentIterable.from(source.get(ChangeField.REVIEWER.getName()).getAsJsonArray())
+ .transform(JsonElement::getAsString)));
+ } else if (fields.contains(ChangeField.REVIEWER.getName())) {
+ cd.setReviewers(ReviewerSet.empty());
+ }
+
+ // Reviewer-by-email.
+ if (source.get(ChangeField.REVIEWER_BY_EMAIL.getName()) != null) {
+ cd.setReviewersByEmail(
+ ChangeField.parseReviewerByEmailFieldValues(
+ cd.getId(),
+ FluentIterable.from(
+ source.get(ChangeField.REVIEWER_BY_EMAIL.getName()).getAsJsonArray())
+ .transform(JsonElement::getAsString)));
+ } else if (fields.contains(ChangeField.REVIEWER_BY_EMAIL.getName())) {
+ cd.setReviewersByEmail(ReviewerByEmailSet.empty());
+ }
+
+ // Pending-reviewer.
+ if (source.get(ChangeField.PENDING_REVIEWER.getName()) != null) {
+ cd.setPendingReviewers(
+ ChangeField.parseReviewerFieldValues(
+ cd.getId(),
+ FluentIterable.from(
+ source.get(ChangeField.PENDING_REVIEWER.getName()).getAsJsonArray())
+ .transform(JsonElement::getAsString)));
+ } else if (fields.contains(ChangeField.PENDING_REVIEWER.getName())) {
+ cd.setPendingReviewers(ReviewerSet.empty());
+ }
+
+ // Pending-reviewer-by-email.
+ if (source.get(ChangeField.PENDING_REVIEWER_BY_EMAIL.getName()) != null) {
+ cd.setPendingReviewersByEmail(
+ ChangeField.parseReviewerByEmailFieldValues(
+ cd.getId(),
+ FluentIterable.from(
+ source.get(ChangeField.PENDING_REVIEWER_BY_EMAIL.getName()).getAsJsonArray())
+ .transform(JsonElement::getAsString)));
+ } else if (fields.contains(ChangeField.PENDING_REVIEWER_BY_EMAIL.getName())) {
+ cd.setPendingReviewersByEmail(ReviewerByEmailSet.empty());
+ }
+
+ // Stored-submit-record-strict.
+ decodeSubmitRecords(
+ source,
+ ChangeField.STORED_SUBMIT_RECORD_STRICT.getName(),
+ ChangeField.SUBMIT_RULE_OPTIONS_STRICT,
+ cd);
+
+ // Stored-submit-record-leniant.
+ decodeSubmitRecords(
+ source,
+ ChangeField.STORED_SUBMIT_RECORD_LENIENT.getName(),
+ ChangeField.SUBMIT_RULE_OPTIONS_LENIENT,
+ cd);
+
+ // Ref-state.
+ if (fields.contains(ChangeField.REF_STATE.getName())) {
+ cd.setRefStates(getByteArray(source, ChangeField.REF_STATE.getName()));
+ }
+
+ // Ref-state-pattern.
+ if (fields.contains(ChangeField.REF_STATE_PATTERN.getName())) {
+ cd.setRefStatePatterns(getByteArray(source, ChangeField.REF_STATE_PATTERN.getName()));
+ }
+
+ // Unresolved-comment-count.
+ decodeUnresolvedCommentCount(source, ChangeField.UNRESOLVED_COMMENT_COUNT.getName(), cd);
+
+ return cd;
+ }
+
+ private Iterable<byte[]> getByteArray(JsonObject source, String name) {
+ JsonElement element = source.get(name);
+ return element != null
+ ? Iterables.transform(element.getAsJsonArray(), e -> Base64.decodeBase64(e.getAsString()))
+ : Collections.emptyList();
+ }
+
+ private void decodeSubmitRecords(
+ JsonObject doc, String fieldName, SubmitRuleOptions opts, ChangeData out) {
+ JsonArray records = doc.getAsJsonArray(fieldName);
+ if (records == null) {
+ return;
+ }
+ ChangeField.parseSubmitRecords(
+ FluentIterable.from(records)
+ .transform(i -> new String(decodeBase64(i.toString()), UTF_8))
+ .toList(),
+ opts,
+ out);
+ }
+
+ private void decodeUnresolvedCommentCount(JsonObject doc, String fieldName, ChangeData out) {
+ JsonElement count = doc.get(fieldName);
+ if (count == null) {
+ return;
+ }
+ out.setUnresolvedCommentCount(count.getAsInt());
+ }
+}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java b/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
similarity index 93%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
rename to java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
index cd74567..6863238 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
@@ -17,6 +17,7 @@
import static com.google.common.base.MoreObjects.firstNonNull;
import com.google.common.base.Strings;
+import com.google.common.flogger.FluentLogger;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.ProvisionException;
@@ -28,12 +29,10 @@
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpHost;
import org.eclipse.jgit.lib.Config;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
@Singleton
class ElasticConfiguration {
- private static final Logger log = LoggerFactory.getLogger(ElasticConfiguration.class);
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static final String SECTION_ELASTICSEARCH = "elasticsearch";
static final String KEY_PASSWORD = "password";
@@ -92,7 +91,7 @@
uri.getHost(), port == -1 ? Integer.valueOf(DEFAULT_PORT) : port, uri.getScheme());
this.hosts.add(httpHost);
} catch (URISyntaxException | IllegalArgumentException e) {
- log.error("Invalid server URI {}: {}", server, e.getMessage());
+ logger.atSevere().log("Invalid server URI %s: %s", server, e.getMessage());
}
}
@@ -100,7 +99,7 @@
throw new ProvisionException("No valid Elasticsearch servers configured");
}
- log.info("Elasticsearch servers: {}", hosts);
+ logger.atInfo().log("Elasticsearch servers: %s", hosts);
}
Config getConfig() {
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticException.java b/java/com/google/gerrit/elasticsearch/ElasticException.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticException.java
rename to java/com/google/gerrit/elasticsearch/ElasticException.java
diff --git a/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
new file mode 100644
index 0000000..f694a05
--- /dev/null
+++ b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
@@ -0,0 +1,126 @@
+// Copyright (C) 2017 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.elasticsearch;
+
+import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
+import com.google.gerrit.elasticsearch.bulk.BulkRequest;
+import com.google.gerrit.elasticsearch.bulk.IndexRequest;
+import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.Schema;
+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.account.GroupCache;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.group.InternalGroup;
+import com.google.gerrit.server.index.IndexUtils;
+import com.google.gerrit.server.index.group.GroupField;
+import com.google.gerrit.server.index.group.GroupIndex;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.assistedinject.Assisted;
+import java.io.IOException;
+import java.util.Set;
+import org.apache.http.HttpStatus;
+import org.elasticsearch.client.Response;
+
+public class ElasticGroupIndex extends AbstractElasticIndex<AccountGroup.UUID, InternalGroup>
+ implements GroupIndex {
+ static class GroupMapping {
+ final MappingProperties groups;
+
+ GroupMapping(Schema<InternalGroup> schema, ElasticQueryAdapter adapter) {
+ this.groups = ElasticMapping.createMapping(schema, adapter);
+ }
+ }
+
+ private static final String GROUPS = "groups";
+
+ private final GroupMapping mapping;
+ private final Provider<GroupCache> groupCache;
+ private final Schema<InternalGroup> schema;
+
+ @Inject
+ ElasticGroupIndex(
+ ElasticConfiguration cfg,
+ SitePaths sitePaths,
+ Provider<GroupCache> groupCache,
+ ElasticRestClientProvider client,
+ @Assisted Schema<InternalGroup> schema) {
+ super(cfg, sitePaths, schema, client, GROUPS);
+ this.groupCache = groupCache;
+ this.mapping = new GroupMapping(schema, client.adapter());
+ this.schema = schema;
+ }
+
+ @Override
+ public void replace(InternalGroup group) throws IOException {
+ BulkRequest bulk =
+ new IndexRequest(getId(group), indexName, type, client.adapter())
+ .add(new UpdateRequest<>(schema, group));
+
+ String uri = getURI(type, BULK);
+ Response response = postRequest(uri, bulk, getRefreshParam());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode != HttpStatus.SC_OK) {
+ throw new IOException(
+ String.format(
+ "Failed to replace group %s in index %s: %s",
+ group.getGroupUUID().get(), indexName, statusCode));
+ }
+ }
+
+ @Override
+ public DataSource<InternalGroup> getSource(Predicate<InternalGroup> p, QueryOptions opts)
+ throws QueryParseException {
+ JsonArray sortArray = getSortArray(GroupField.UUID.getName());
+ return new ElasticQuerySource(p, opts.filterFields(IndexUtils::groupFields), GROUPS, sortArray);
+ }
+
+ @Override
+ protected String getDeleteActions(AccountGroup.UUID g) {
+ return delete(type, g);
+ }
+
+ @Override
+ protected String getMappings() {
+ return getMappingsForSingleType(GROUPS, mapping.groups);
+ }
+
+ @Override
+ protected String getId(InternalGroup group) {
+ return group.getGroupUUID().get();
+ }
+
+ @Override
+ protected InternalGroup fromDocument(JsonObject json, Set<String> fields) {
+ JsonElement source = json.get("_source");
+ if (source == null) {
+ source = json.getAsJsonObject().get("fields");
+ }
+
+ AccountGroup.UUID uuid =
+ new AccountGroup.UUID(
+ source.getAsJsonObject().get(GroupField.UUID.getName()).getAsString());
+ // Use the GroupCache rather than depending on any stored fields in the
+ // document (of which there shouldn't be any).
+ return groupCache.get().get(uuid).orElse(null);
+ }
+}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexModule.java b/java/com/google/gerrit/elasticsearch/ElasticIndexModule.java
similarity index 78%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexModule.java
rename to java/com/google/gerrit/elasticsearch/ElasticIndexModule.java
index 6bc51ce..15d6126 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexModule.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticIndexModule.java
@@ -14,6 +14,7 @@
package com.google.gerrit.elasticsearch;
+import com.google.gerrit.index.project.ProjectIndex;
import com.google.gerrit.server.index.AbstractIndexModule;
import com.google.gerrit.server.index.VersionManager;
import com.google.gerrit.server.index.account.AccountIndex;
@@ -22,18 +23,17 @@
import java.util.Map;
public class ElasticIndexModule extends AbstractIndexModule {
-
public static ElasticIndexModule singleVersionWithExplicitVersions(
- Map<String, Integer> versions, int threads) {
- return new ElasticIndexModule(versions, threads);
+ Map<String, Integer> versions, int threads, boolean slave) {
+ return new ElasticIndexModule(versions, threads, slave);
}
- public static ElasticIndexModule latestVersion() {
- return new ElasticIndexModule(null, 0);
+ public static ElasticIndexModule latestVersion(boolean slave) {
+ return new ElasticIndexModule(null, 0, slave);
}
- private ElasticIndexModule(Map<String, Integer> singleVersions, int threads) {
- super(singleVersions, threads);
+ private ElasticIndexModule(Map<String, Integer> singleVersions, int threads, boolean slave) {
+ super(singleVersions, threads, slave);
}
@Override
@@ -58,6 +58,11 @@
}
@Override
+ protected Class<? extends ProjectIndex> getProjectIndex() {
+ return ElasticProjectIndex.class;
+ }
+
+ @Override
protected Class<? extends VersionManager> getVersionManager() {
return ElasticIndexVersionManager.class;
}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java b/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
similarity index 91%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
rename to java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
index 249e93c..a777f47 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
@@ -16,6 +16,7 @@
import static java.util.stream.Collectors.toList;
+import com.google.common.flogger.FluentLogger;
import com.google.gson.JsonParser;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -25,12 +26,10 @@
import org.apache.http.StatusLine;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
@Singleton
class ElasticIndexVersionDiscovery {
- private static final Logger log = LoggerFactory.getLogger(ElasticIndexVersionDiscovery.class);
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final ElasticRestClientProvider client;
@@ -50,7 +49,7 @@
String.format(
"Failed to discover index versions for %s: %d: %s",
name, statusLine.getStatusCode(), statusLine.getReasonPhrase());
- log.error(message);
+ logger.atSevere().log(message);
throw new IOException(message);
}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexVersionManager.java b/java/com/google/gerrit/elasticsearch/ElasticIndexVersionManager.java
similarity index 79%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexVersionManager.java
rename to java/com/google/gerrit/elasticsearch/ElasticIndexVersionManager.java
index cff1911..8011efa 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticIndexVersionManager.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticIndexVersionManager.java
@@ -14,11 +14,14 @@
package com.google.gerrit.elasticsearch;
+import com.google.common.base.Strings;
+import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.Schema;
+import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.index.GerritIndexStatus;
import com.google.gerrit.server.index.OnlineUpgradeListener;
@@ -29,26 +32,25 @@
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.eclipse.jgit.lib.Config;
@Singleton
public class ElasticIndexVersionManager extends VersionManager {
- private static final Logger log = LoggerFactory.getLogger(ElasticIndexVersionManager.class);
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final String prefix;
private final ElasticIndexVersionDiscovery versionDiscovery;
@Inject
ElasticIndexVersionManager(
- ElasticConfiguration cfg,
+ @GerritServerConfig Config cfg,
SitePaths sitePaths,
DynamicSet<OnlineUpgradeListener> listeners,
Collection<IndexDefinition<?, ?, ?>> defs,
ElasticIndexVersionDiscovery versionDiscovery) {
- super(sitePaths, listeners, defs, VersionManager.getOnlineUpgrade(cfg.getConfig()));
+ super(sitePaths, listeners, defs, VersionManager.getOnlineUpgrade(cfg));
this.versionDiscovery = versionDiscovery;
- prefix = cfg.prefix;
+ prefix = Strings.nullToEmpty(cfg.getString("elasticsearch", null, "prefix"));
}
@Override
@@ -57,17 +59,17 @@
TreeMap<Integer, Version<V>> versions = new TreeMap<>();
try {
List<String> discovered = versionDiscovery.discover(prefix, def.getName());
- log.debug("Discovered versions for {}: {}", def.getName(), discovered);
+ logger.atFine().log("Discovered versions for %s: %s", def.getName(), discovered);
for (String version : discovered) {
Integer v = Ints.tryParse(version);
if (v == null || version.length() != 4) {
- log.warn("Unrecognized version in index {}: {}", def.getName(), version);
+ logger.atWarning().log("Unrecognized version in index %s: %s", def.getName(), version);
continue;
}
versions.put(v, new Version<>(null, v, true, cfg.getReady(def.getName(), v)));
}
} catch (IOException e) {
- log.error("Error scanning index: " + def.getName(), e);
+ logger.atSevere().withCause(e).log("Error scanning index: %s", def.getName());
}
for (Schema<V> schema : def.getSchemas().values()) {
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticMapping.java b/java/com/google/gerrit/elasticsearch/ElasticMapping.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticMapping.java
rename to java/com/google/gerrit/elasticsearch/ElasticMapping.java
diff --git a/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java b/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
new file mode 100644
index 0000000..8510559
--- /dev/null
+++ b/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
@@ -0,0 +1,124 @@
+// Copyright (C) 2017 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.elasticsearch;
+
+import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
+import com.google.gerrit.elasticsearch.bulk.BulkRequest;
+import com.google.gerrit.elasticsearch.bulk.IndexRequest;
+import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.Schema;
+import com.google.gerrit.index.project.ProjectData;
+import com.google.gerrit.index.project.ProjectField;
+import com.google.gerrit.index.project.ProjectIndex;
+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.Project;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.index.IndexUtils;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.assistedinject.Assisted;
+import java.io.IOException;
+import java.util.Set;
+import org.apache.http.HttpStatus;
+import org.elasticsearch.client.Response;
+
+public class ElasticProjectIndex extends AbstractElasticIndex<Project.NameKey, ProjectData>
+ implements ProjectIndex {
+ static class ProjectMapping {
+ MappingProperties projects;
+
+ ProjectMapping(Schema<ProjectData> schema, ElasticQueryAdapter adapter) {
+ this.projects = ElasticMapping.createMapping(schema, adapter);
+ }
+ }
+
+ static final String PROJECTS = "projects";
+
+ private final ProjectMapping mapping;
+ private final Provider<ProjectCache> projectCache;
+ private final Schema<ProjectData> schema;
+
+ @Inject
+ ElasticProjectIndex(
+ ElasticConfiguration cfg,
+ SitePaths sitePaths,
+ Provider<ProjectCache> projectCache,
+ ElasticRestClientProvider client,
+ @Assisted Schema<ProjectData> schema) {
+ super(cfg, sitePaths, schema, client, PROJECTS);
+ this.projectCache = projectCache;
+ this.schema = schema;
+ this.mapping = new ProjectMapping(schema, client.adapter());
+ }
+
+ @Override
+ public void replace(ProjectData projectState) throws IOException {
+ BulkRequest bulk =
+ new IndexRequest(projectState.getProject().getName(), indexName, type, client.adapter())
+ .add(new UpdateRequest<>(schema, projectState));
+
+ String uri = getURI(type, BULK);
+ Response response = postRequest(uri, bulk, getRefreshParam());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode != HttpStatus.SC_OK) {
+ throw new IOException(
+ String.format(
+ "Failed to replace project %s in index %s: %s",
+ projectState.getProject().getName(), indexName, statusCode));
+ }
+ }
+
+ @Override
+ public DataSource<ProjectData> getSource(Predicate<ProjectData> p, QueryOptions opts)
+ throws QueryParseException {
+ JsonArray sortArray = getSortArray(ProjectField.NAME.getName());
+ return new ElasticQuerySource(p, opts.filterFields(IndexUtils::projectFields), type, sortArray);
+ }
+
+ @Override
+ protected String getDeleteActions(Project.NameKey nameKey) {
+ return delete(type, nameKey);
+ }
+
+ @Override
+ protected String getMappings() {
+ return getMappingsForSingleType(PROJECTS, mapping.projects);
+ }
+
+ @Override
+ protected String getId(ProjectData projectState) {
+ return projectState.getProject().getName();
+ }
+
+ @Override
+ protected ProjectData fromDocument(JsonObject json, Set<String> fields) {
+ JsonElement source = json.get("_source");
+ if (source == null) {
+ source = json.getAsJsonObject().get("fields");
+ }
+
+ Project.NameKey nameKey =
+ new Project.NameKey(
+ source.getAsJsonObject().get(ProjectField.NAME.getName()).getAsString());
+ return projectCache.get().get(nameKey).toProjectData();
+ }
+}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java b/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
similarity index 94%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
rename to java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
index 0c28dd1..40c1bbb 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
@@ -28,6 +28,7 @@
private final String exactFieldType;
private final String stringFieldType;
private final String indexProperty;
+ private final String rawFieldsKey;
private final String versionDiscoveryUrl;
ElasticQueryAdapter(ElasticVersion version) {
@@ -40,6 +41,7 @@
this.exactFieldType = "keyword";
this.stringFieldType = "text";
this.indexProperty = "true";
+ this.rawFieldsKey = "_source";
}
void setIgnoreUnmapped(JsonObject properties) {
@@ -74,6 +76,10 @@
return indexProperty;
}
+ String rawFieldsKey() {
+ return rawFieldsKey;
+ }
+
boolean usePostV5Type() {
return usePostV5Type;
}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java b/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java b/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
similarity index 93%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
rename to java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
index 9c1cf02..e9839b7 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
@@ -14,6 +14,7 @@
package com.google.gerrit.elasticsearch;
+import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gson.JsonParser;
@@ -32,12 +33,10 @@
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
@Singleton
class ElasticRestClientProvider implements Provider<RestClient>, LifecycleListener {
- private static final Logger log = LoggerFactory.getLogger(ElasticRestClientProvider.class);
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final ElasticConfiguration cfg;
@@ -65,7 +64,7 @@
if (client == null) {
client = build();
ElasticVersion version = getVersion();
- log.info("Elasticsearch integration version {}", version);
+ logger.atInfo().log("Elasticsearch integration version %s", version);
adapter = new ElasticQueryAdapter(version);
}
}
@@ -120,7 +119,7 @@
.getAsJsonObject()
.get("number")
.getAsString();
- log.info("Connected to Elasticsearch version {}", version);
+ logger.atInfo().log("Connected to Elasticsearch version %s", version);
return ElasticVersion.forVersion(version);
} catch (IOException e) {
throw new FailedToGetVersion(e);
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticSetting.java b/java/com/google/gerrit/elasticsearch/ElasticSetting.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticSetting.java
rename to java/com/google/gerrit/elasticsearch/ElasticSetting.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticVersion.java b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticVersion.java
rename to java/com/google/gerrit/elasticsearch/ElasticVersion.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/BoolQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/ExistsQueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/ExistsQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/ExistsQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/ExistsQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/MatchAllQueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/MatchAllQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/MatchAllQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/MatchAllQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/MatchQueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/MatchQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/MatchQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/MatchQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/QueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/QueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/QueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/QueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/QueryBuilders.java b/java/com/google/gerrit/elasticsearch/builders/QueryBuilders.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/QueryBuilders.java
rename to java/com/google/gerrit/elasticsearch/builders/QueryBuilders.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/QuerySourceBuilder.java b/java/com/google/gerrit/elasticsearch/builders/QuerySourceBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/QuerySourceBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/QuerySourceBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/RangeQueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/RangeQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/RangeQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/RangeQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/RegexpQueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/RegexpQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/RegexpQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/RegexpQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/SearchSourceBuilder.java b/java/com/google/gerrit/elasticsearch/builders/SearchSourceBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/SearchSourceBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/SearchSourceBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/TermQueryBuilder.java b/java/com/google/gerrit/elasticsearch/builders/TermQueryBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/TermQueryBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/TermQueryBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/XContentBuilder.java b/java/com/google/gerrit/elasticsearch/builders/XContentBuilder.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/builders/XContentBuilder.java
rename to java/com/google/gerrit/elasticsearch/builders/XContentBuilder.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/ActionRequest.java b/java/com/google/gerrit/elasticsearch/bulk/ActionRequest.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/ActionRequest.java
rename to java/com/google/gerrit/elasticsearch/bulk/ActionRequest.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/BulkRequest.java b/java/com/google/gerrit/elasticsearch/bulk/BulkRequest.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/BulkRequest.java
rename to java/com/google/gerrit/elasticsearch/bulk/BulkRequest.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/DeleteRequest.java b/java/com/google/gerrit/elasticsearch/bulk/DeleteRequest.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/DeleteRequest.java
rename to java/com/google/gerrit/elasticsearch/bulk/DeleteRequest.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/IndexRequest.java b/java/com/google/gerrit/elasticsearch/bulk/IndexRequest.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/IndexRequest.java
rename to java/com/google/gerrit/elasticsearch/bulk/IndexRequest.java
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java b/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
similarity index 100%
rename from gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
rename to java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/index/elasticsearch/ElasticIndexModuleOnInit.java b/java/com/google/gerrit/pgm/init/index/elasticsearch/ElasticIndexModuleOnInit.java
similarity index 100%
rename from gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/index/elasticsearch/ElasticIndexModuleOnInit.java
rename to java/com/google/gerrit/pgm/init/index/elasticsearch/ElasticIndexModuleOnInit.java
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
similarity index 96%
rename from gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
rename to javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
index 3d59ad3..bb7cff7 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
+++ b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
@@ -18,7 +18,7 @@
import static com.google.gerrit.elasticsearch.ElasticTestUtils.getConfig;
import com.google.gerrit.elasticsearch.ElasticVersion;
-import com.google.gerrit.testutil.ConfigSuite;
+import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
similarity index 96%
rename from gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
rename to javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
index cf8503d..4e88955 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
@@ -18,7 +18,7 @@
import static com.google.gerrit.elasticsearch.ElasticTestUtils.getConfig;
import com.google.gerrit.elasticsearch.ElasticVersion;
-import com.google.gerrit.testutil.ConfigSuite;
+import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
diff --git a/javatests/com/google/gerrit/elasticsearch/BUILD b/javatests/com/google/gerrit/elasticsearch/BUILD
new file mode 100644
index 0000000..4806acc
--- /dev/null
+++ b/javatests/com/google/gerrit/elasticsearch/BUILD
@@ -0,0 +1,98 @@
+load("//tools/bzl:junit.bzl", "junit_tests")
+
+java_library(
+ name = "elasticsearch_test_utils",
+ testonly = True,
+ srcs = [
+ "ElasticContainer.java",
+ "ElasticTestUtils.java",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/elasticsearch",
+ "//java/com/google/gerrit/index",
+ "//java/com/google/gerrit/server",
+ "//lib:guava",
+ "//lib:junit",
+ "//lib/guice",
+ "//lib/httpcomponents:httpcore",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+ "//lib/testcontainers",
+ "//lib/testcontainers:testcontainers-elasticsearch",
+ ],
+)
+
+ELASTICSEARCH_DEPS = [
+ ":elasticsearch_test_utils",
+ "//java/com/google/gerrit/elasticsearch",
+ "//java/com/google/gerrit/testing:gerrit-test-util",
+ "//lib/guice",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+]
+
+QUERY_TESTS_DEP = "//javatests/com/google/gerrit/server/query/%s:abstract_query_tests"
+
+TYPES = [
+ "account",
+ "change",
+ "group",
+ "project",
+]
+
+SUFFIX = "sTest.java"
+
+ELASTICSEARCH_TESTS_V5 = {i: "ElasticV5Query" + i.capitalize() + SUFFIX for i in TYPES}
+
+ELASTICSEARCH_TESTS_V6 = {i: "ElasticV6Query" + i.capitalize() + SUFFIX for i in TYPES}
+
+ELASTICSEARCH_TESTS_V7 = {i: "ElasticV7Query" + i.capitalize() + SUFFIX for i in TYPES}
+
+ELASTICSEARCH_TAGS = [
+ "docker",
+ "elastic",
+ "exclusive",
+]
+
+[junit_tests(
+ name = "elasticsearch_query_%ss_test_V5" % name,
+ size = "large",
+ srcs = [src],
+ tags = ELASTICSEARCH_TAGS,
+ deps = ELASTICSEARCH_DEPS + [QUERY_TESTS_DEP % name],
+) for name, src in ELASTICSEARCH_TESTS_V5.items()]
+
+[junit_tests(
+ name = "elasticsearch_query_%ss_test_V6" % name,
+ size = "large",
+ srcs = [src],
+ tags = ELASTICSEARCH_TAGS + ["flaky"],
+ deps = ELASTICSEARCH_DEPS + [QUERY_TESTS_DEP % name],
+) for name, src in ELASTICSEARCH_TESTS_V6.items()]
+
+[junit_tests(
+ name = "elasticsearch_query_%ss_test_V7" % name,
+ size = "large",
+ srcs = [src],
+ tags = ELASTICSEARCH_TAGS + ["flaky"],
+ deps = ELASTICSEARCH_DEPS + [QUERY_TESTS_DEP % name] + [
+ "//lib/httpcomponents:httpasyncclient",
+ "//lib/httpcomponents:httpclient",
+ ],
+) for name, src in ELASTICSEARCH_TESTS_V7.items()]
+
+junit_tests(
+ name = "elasticsearch_tests",
+ size = "small",
+ srcs = glob(
+ ["*Test.java"],
+ exclude = ["Elastic*Query*" + SUFFIX],
+ ),
+ tags = ["elastic"],
+ deps = [
+ "//java/com/google/gerrit/elasticsearch",
+ "//lib:guava",
+ "//lib/guice",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+ "//lib/truth",
+ ],
+)
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java
similarity index 100%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticConfigurationTest.java
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticContainer.java b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
similarity index 97%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticContainer.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
index b68e866..8583d2d 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticContainer.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
@@ -15,7 +15,7 @@
package com.google.gerrit.elasticsearch;
import org.apache.http.HttpHost;
-import org.junit.internal.AssumptionViolatedException;
+import org.junit.AssumptionViolatedException;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
/* Helper class for running ES integration tests in docker container */
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticTestUtils.java b/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
similarity index 100%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticTestUtils.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
index 01a523b..c8ce54a 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.account.AbstractQueryAccountsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,11 @@
import org.junit.BeforeClass;
public class ElasticV5QueryAccountsTest extends AbstractQueryAccountsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
index d60b7ec..cfdfa98 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.change.AbstractQueryChangesTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,11 @@
import org.junit.BeforeClass;
public class ElasticV5QueryChangesTest extends AbstractQueryChangesTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
index e8d9a78..832a7bd 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.group.AbstractQueryGroupsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,11 @@
import org.junit.BeforeClass;
public class ElasticV5QueryGroupsTest extends AbstractQueryGroupsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
similarity index 82%
copy from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
copy to javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
index d60b7ec..29d3fa4 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
@@ -15,15 +15,22 @@
package com.google.gerrit.elasticsearch;
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
-import com.google.gerrit.server.query.change.AbstractQueryChangesTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.server.query.project.AbstractQueryProjectsTest;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
import org.junit.AfterClass;
import org.junit.BeforeClass;
-public class ElasticV5QueryChangesTest extends AbstractQueryChangesTest {
+public class ElasticV5QueryProjectsTest extends AbstractQueryProjectsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
index c4a787f..8833907 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.account.AbstractQueryAccountsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,11 @@
import org.junit.BeforeClass;
public class ElasticV6QueryAccountsTest extends AbstractQueryAccountsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
index 536ba74..8ba753c 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.change.AbstractQueryChangesTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,10 @@
import org.junit.BeforeClass;
public class ElasticV6QueryChangesTest extends AbstractQueryChangesTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
index 22186f5..cecb085 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.group.AbstractQueryGroupsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,11 @@
import org.junit.BeforeClass;
public class ElasticV6QueryGroupsTest extends AbstractQueryGroupsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryProjectsTest.java
similarity index 81%
copy from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
copy to javatests/com/google/gerrit/elasticsearch/ElasticV6QueryProjectsTest.java
index 22186f5..47e9b10 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryProjectsTest.java
@@ -15,15 +15,22 @@
package com.google.gerrit.elasticsearch;
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
-import com.google.gerrit.server.query.group.AbstractQueryGroupsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.server.query.project.AbstractQueryProjectsTest;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
import org.junit.AfterClass;
import org.junit.BeforeClass;
-public class ElasticV6QueryGroupsTest extends AbstractQueryGroupsTest {
+public class ElasticV6QueryProjectsTest extends AbstractQueryProjectsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
@@ -34,7 +41,7 @@
return;
}
- container = ElasticContainer.createAndStart(ElasticVersion.V6_5);
+ container = ElasticContainer.createAndStart(ElasticVersion.V6_2);
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
}
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
index 8634709..bddbbc9 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.account.AbstractQueryAccountsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,11 @@
import org.junit.BeforeClass;
public class ElasticV7QueryAccountsTest extends AbstractQueryAccountsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
similarity index 91%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
index f46364e..5dcf159 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.change.AbstractQueryChangesTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.http.client.methods.HttpPost;
@@ -29,6 +31,10 @@
import org.junit.BeforeClass;
public class ElasticV7QueryChangesTest extends AbstractQueryChangesTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
similarity index 88%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
index 33f6666..54be7b9 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
@@ -16,7 +16,9 @@
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
import com.google.gerrit.server.query.group.AbstractQueryGroupsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
@@ -24,6 +26,11 @@
import org.junit.BeforeClass;
public class ElasticV7QueryGroupsTest extends AbstractQueryGroupsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
similarity index 82%
copy from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
copy to javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
index 33f6666..e8b4a2c 100644
--- a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
@@ -15,15 +15,22 @@
package com.google.gerrit.elasticsearch;
import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo;
-import com.google.gerrit.server.query.group.AbstractQueryGroupsTest;
-import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.server.query.project.AbstractQueryProjectsTest;
+import com.google.gerrit.testing.ConfigSuite;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gerrit.testing.IndexConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
import org.junit.AfterClass;
import org.junit.BeforeClass;
-public class ElasticV7QueryGroupsTest extends AbstractQueryGroupsTest {
+public class ElasticV7QueryProjectsTest extends AbstractQueryProjectsTest {
+ @ConfigSuite.Default
+ public static Config defaultConfig() {
+ return IndexConfig.createForElasticsearch();
+ }
+
private static ElasticNodeInfo nodeInfo;
private static ElasticContainer container;
diff --git a/gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticVersionTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
similarity index 100%
rename from gerrit-elasticsearch/src/test/java/com/google/gerrit/elasticsearch/ElasticVersionTest.java
rename to javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java