Merge "BuckUtils: Support missing buck.properties"
diff --git a/Documentation/cmd-set-reviewers.txt b/Documentation/cmd-set-reviewers.txt
index 79f7651..d5b4908 100644
--- a/Documentation/cmd-set-reviewers.txt
+++ b/Documentation/cmd-set-reviewers.txt
@@ -10,17 +10,16 @@
[--add <REVIEWER> ... | -a <REVIEWER> ...]
[--remove <REVIEWER> ... | -r <REVIEWER> ...]
[--]
- {COMMIT | CHANGE-ID}...
+ {CHANGE-ID}...
--
== DESCRIPTION
Adds or removes reviewers to the specified change, sending email
notifications when changes are made.
-Changes should be specified as complete or abbreviated Change-Ids
-such as 'Iac6b2ac2'. They may also be specified by numeric change
-identifiers, such as '8242' or by complete or abbreviated commit
-SHA-1s.
+Changes can be specified in the
+link:rest-api-changes.html#change-id[same format] supported by the REST
+API.
== OPTIONS
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index c9bea0a..8c488e4 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1404,7 +1404,8 @@
httpd and sshd threads as some request processing code paths may
need multiple connections.
+
-Default is 8.
+Default is <<sshd.threads, sshd.threads>>
+ + <<httpd.maxThreads, httpd.maxThreads>> + 2.
+
This setting only applies if
<<database.connectionPool,database.connectionPool>> is true.
@@ -1422,7 +1423,7 @@
Maximum number of connections to keep idle in the pool. If there
are more idle connections, connections will be closed instead of
being returned back to the pool.
-Default is 4.
+Default is min(<<database.poolLimit, database.poolLimit>>, 16).
+
This setting only applies if
<<database.connectionPool,database.connectionPool>> is true.
@@ -3142,6 +3143,8 @@
+
A size of 0 bytes disables rules, same as rules.enable = false.
+
+Common unit suffixes of 'k', 'm', or 'g' are supported.
++
Default is 128 KiB.
[[rules.maxPrologDatabaseSize]]rules.maxPrologDatabaseSize::
@@ -3429,7 +3432,7 @@
If additional requests are received while all threads are busy they
are queued and serviced in a first-come-first-served order.
+
-By default, 1.5x the number of CPUs available to the JVM.
+By default, 2x the number of CPUs available to the JVM.
[[sshd.batchThreads]]sshd.batchThreads::
+
diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index 5c3b629..c05c8f0 100644
--- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -131,7 +131,6 @@
private static final String APPROVAL_FIELD = ChangeField.APPROVAL.getName();
private static final String CHANGE_FIELD = ChangeField.CHANGE.getName();
private static final String DELETED_FIELD = ChangeField.DELETED.getName();
- private static final String ID_FIELD = ChangeField.LEGACY_ID2.getName();
private static final String MERGEABLE_FIELD = ChangeField.MERGEABLE.getName();
private static final String PATCH_SET_FIELD = ChangeField.PATCH_SET.getName();
private static final String REVIEWEDBY_FIELD =
@@ -139,10 +138,6 @@
private static final String UPDATED_SORT_FIELD =
sortFieldName(ChangeField.UPDATED);
- private static final ImmutableSet<String> FIELDS = ImmutableSet.of(
- ADDED_FIELD, APPROVAL_FIELD, CHANGE_FIELD, DELETED_FIELD, ID_FIELD,
- MERGEABLE_FIELD, PATCH_SET_FIELD, REVIEWEDBY_FIELD);
-
private static final Map<String, String> CUSTOM_CHAR_MAPPING = ImmutableMap.of(
"_", " ", ".", " ");
@@ -438,10 +433,12 @@
List<ChangeData> result =
Lists.newArrayListWithCapacity(docs.scoreDocs.length);
+ Set<String> fields = fields(opts);
+ String idFieldName = idFieldName();
for (int i = opts.start(); i < docs.scoreDocs.length; i++) {
ScoreDoc sd = docs.scoreDocs[i];
- Document doc = searchers[sd.shardIndex].doc(sd.doc, FIELDS);
- result.add(toChangeData(doc));
+ Document doc = searchers[sd.shardIndex].doc(sd.doc, fields);
+ result.add(toChangeData(doc, fields, idFieldName));
}
final List<ChangeData> r = Collections.unmodifiableList(result);
@@ -477,19 +474,62 @@
}
}
- private ChangeData toChangeData(Document doc) {
+ @SuppressWarnings("deprecation")
+ private Set<String> fields(QueryOptions opts) {
+ if (schemaHasRequestedField(ChangeField.LEGACY_ID2, opts.fields())
+ || schemaHasRequestedField(ChangeField.CHANGE, opts.fields())
+ || schemaHasRequestedField(ChangeField.LEGACY_ID, opts.fields())) {
+ return opts.fields();
+ }
+ // Request the numeric ID field even if the caller did not request it,
+ // otherwise we can't actually construct a ChangeData.
+ return Sets.union(opts.fields(), ImmutableSet.of(idFieldName()));
+ }
+
+ private boolean schemaHasRequestedField(FieldDef<ChangeData, ?> field,
+ Set<String> requested) {
+ return schema.hasField(field) && requested.contains(field.getName());
+ }
+
+ @SuppressWarnings("deprecation")
+ private String idFieldName() {
+ return schema.getField(ChangeField.LEGACY_ID2, ChangeField.LEGACY_ID).get()
+ .getName();
+ }
+
+ private ChangeData toChangeData(Document doc, Set<String> fields,
+ String idFieldName) {
+ ChangeData cd;
+ // Either change or the ID field was guaranteed to be included in the call
+ // to fields() above.
BytesRef cb = doc.getBinaryValue(CHANGE_FIELD);
- if (cb == null) {
- int id = doc.getField(ID_FIELD).numericValue().intValue();
- return changeDataFactory.create(db.get(), new Change.Id(id));
+ if (cb != null) {
+ cd = changeDataFactory.create(db.get(),
+ ChangeProtoField.CODEC.decode(cb.bytes, cb.offset, cb.length));
+ } else {
+ int id = doc.getField(idFieldName).numericValue().intValue();
+ cd = changeDataFactory.create(db.get(), new Change.Id(id));
}
- // Change proto.
- Change change = ChangeProtoField.CODEC.decode(
- cb.bytes, cb.offset, cb.length);
- ChangeData cd = changeDataFactory.create(db.get(), change);
+ if (fields.contains(PATCH_SET_FIELD)) {
+ decodePatchSets(doc, cd);
+ }
+ if (fields.contains(APPROVAL_FIELD)) {
+ decodeApprovals(doc, cd);
+ }
+ if (fields.contains(ADDED_FIELD) && fields.contains(DELETED_FIELD)) {
+ decodeChangedLines(doc, cd);
+ }
+ if (fields.contains(MERGEABLE_FIELD)) {
+ decodeMergeable(doc, cd);
+ }
+ if (fields.contains(REVIEWEDBY_FIELD)) {
+ decodeReviewedBy(doc, cd);
+ }
+ return cd;
+ }
- // Patch sets.
+ private void decodePatchSets(Document doc, ChangeData cd) {
List<PatchSet> patchSets =
decodeProtos(doc, PATCH_SET_FIELD, PatchSetProtoField.CODEC);
if (!patchSets.isEmpty()) {
@@ -497,12 +537,14 @@
// this cannot be valid since a change needs at least one patch set.
cd.setPatchSets(patchSets);
}
+ }
- // Approvals.
+ private void decodeApprovals(Document doc, ChangeData cd) {
cd.setCurrentApprovals(
decodeProtos(doc, APPROVAL_FIELD, PatchSetApprovalProtoField.CODEC));
+ }
- // Changed lines.
+ private void decodeChangedLines(Document doc, ChangeData cd) {
IndexableField added = doc.getField(ADDED_FIELD);
IndexableField deleted = doc.getField(DELETED_FIELD);
if (added != null && deleted != null) {
@@ -510,16 +552,18 @@
added.numericValue().intValue(),
deleted.numericValue().intValue());
}
+ }
- // Mergeable.
+ private void decodeMergeable(Document doc, ChangeData cd) {
String mergeable = doc.get(MERGEABLE_FIELD);
if ("1".equals(mergeable)) {
cd.setMergeable(true);
} else if ("0".equals(mergeable)) {
cd.setMergeable(false);
}
+ }
- // Reviewed-by.
+ private void decodeReviewedBy(Document doc, ChangeData cd) {
IndexableField[] reviewedBy = doc.getFields(REVIEWEDBY_FIELD);
if (reviewedBy.length > 0) {
Set<Account.Id> accounts =
@@ -533,8 +577,6 @@
}
cd.setReviewedBy(accounts);
}
-
- return cd;
}
private static <T> List<T> decodeProtos(Document doc, String fieldName,
diff --git a/gerrit-openid/BUCK b/gerrit-openid/BUCK
index 78abce8..0a6363b 100644
--- a/gerrit-openid/BUCK
+++ b/gerrit-openid/BUCK
@@ -3,6 +3,9 @@
srcs = glob(['src/main/java/**/*.java']),
resources = glob(['src/main/resources/**/*']),
deps = [
+ '//lib/openid:consumer',
+ ],
+ provided_deps = [
'//gerrit-common:annotations',
'//gerrit-common:server',
'//gerrit-extension-api:api',
@@ -12,13 +15,12 @@
'//gerrit-server:server',
'//lib:guava',
'//lib:gwtorm',
+ '//lib:servlet-api-3_1',
'//lib/commons:codec',
'//lib/guice:guice',
'//lib/guice:guice-servlet',
'//lib/jgit:jgit',
'//lib/log:api',
- '//lib/openid:consumer',
],
- provided_deps = ['//lib:servlet-api-3_1'],
visibility = ['PUBLIC'],
)
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
index 0684650..adfea594 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -23,6 +23,7 @@
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
@@ -127,11 +128,14 @@
private boolean reverseProxy;
@Inject
- JettyServer(@GerritServerConfig final Config cfg, final SitePaths site,
- final JettyEnv env, final HttpLogFactory httpLogFactory) {
+ JettyServer(@GerritServerConfig Config cfg,
+ ThreadSettingsConfig threadSettingsConfig,
+ SitePaths site,
+ JettyEnv env,
+ HttpLogFactory httpLogFactory) {
this.site = site;
- httpd = new Server(threadPool(cfg));
+ httpd = new Server(threadPool(cfg, threadSettingsConfig));
httpd.setConnectors(listen(httpd, cfg));
Handler app = makeContext(env, cfg);
@@ -315,8 +319,8 @@
return site.resolve(path);
}
- private ThreadPool threadPool(Config cfg) {
- int maxThreads = cfg.getInt("httpd", null, "maxthreads", 25);
+ private ThreadPool threadPool(Config cfg, ThreadSettingsConfig threadSettingsConfig) {
+ int maxThreads = threadSettingsConfig.getHttpdMaxThreads();
int minThreads = cfg.getInt("httpd", null, "minthreads", 5);
int maxQueued = cfg.getInt("httpd", null, "maxqueued", 200);
int idleTimeout = (int)MILLISECONDS.convert(60, SECONDS);
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
index 7f6313d..6443e21 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
@@ -18,6 +18,7 @@
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gerrit.server.schema.DataSourceProvider;
import com.google.gerrit.server.schema.DataSourceType;
import com.google.inject.Inject;
@@ -39,9 +40,10 @@
SiteLibraryBasedDataSourceProvider(SitePaths site,
@GerritServerConfig Config cfg,
MetricMaker metrics,
+ ThreadSettingsConfig tsc,
DataSourceProvider.Context ctx,
DataSourceType dst) {
- super(cfg, metrics, ctx, dst);
+ super(cfg, metrics, tsc, ctx, dst);
libdir = site.lib_dir;
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java
index 44361aa..8db3125 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java
@@ -15,6 +15,7 @@
package com.google.gerrit.pgm.util;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gerrit.server.schema.DataSourceProvider;
import com.google.gerrit.server.schema.DataSourceType;
import com.google.inject.Injector;
@@ -34,14 +35,15 @@
return limitThreads(
dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class)),
dbInjector.getInstance(DataSourceType.class),
+ dbInjector.getInstance(ThreadSettingsConfig.class),
threads);
}
- private static int limitThreads(Config cfg, DataSourceType dst, int threads) {
+ private static int limitThreads(Config cfg, DataSourceType dst,
+ ThreadSettingsConfig threadSettingsConfig, int threads) {
boolean usePool = cfg.getBoolean("database", "connectionpool",
dst.usePool());
- int poolLimit = cfg.getInt("database", "poollimit",
- DataSourceProvider.DEFAULT_POOL_LIMIT);
+ int poolLimit = threadSettingsConfig.getDatabasePoolLimit();
if (usePool && threads > poolLimit) {
log.warn("Limiting program to " + poolLimit
+ " threads due to database.poolLimit");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
index 6c80d26..0cbe540 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
@@ -14,15 +14,13 @@
package com.google.gerrit.server;
-import static com.google.gerrit.server.query.change.ChangeData.asChanges;
-
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Ordering;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -43,6 +41,7 @@
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.RefControl;
+import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.util.IdGenerator;
import com.google.gwtorm.server.OrmConcurrencyException;
@@ -73,6 +72,7 @@
import java.io.IOException;
import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -180,6 +180,7 @@
private final Provider<IdentifiedUser> user;
private final Provider<ReviewDb> db;
private final Provider<InternalChangeQuery> queryProvider;
+ private final ChangeControl.GenericFactory changeControlFactory;
private final RevertedSender.Factory revertedSenderFactory;
private final ChangeInserter.Factory changeInserterFactory;
private final GitRepositoryManager gitManager;
@@ -193,6 +194,7 @@
ChangeUtil(Provider<IdentifiedUser> user,
Provider<ReviewDb> db,
Provider<InternalChangeQuery> queryProvider,
+ ChangeControl.GenericFactory changeControlFactory,
RevertedSender.Factory revertedSenderFactory,
ChangeInserter.Factory changeInserterFactory,
GitRepositoryManager gitManager,
@@ -204,6 +206,7 @@
this.user = user;
this.db = db;
this.queryProvider = queryProvider;
+ this.changeControlFactory = changeControlFactory;
this.revertedSenderFactory = revertedSenderFactory;
this.changeInserterFactory = changeInserterFactory;
this.gitManager = gitManager;
@@ -425,34 +428,51 @@
*
* @param id change identifier, either a numeric ID, a Change-Id, or
* project~branch~id triplet.
- * @return all matching changes, even if they are not visible to the current
- * user.
+ * @param user user to wrap in controls.
+ * @return possibly-empty list of controls for all matching changes,
+ * corresponding to the given user; may or may not be visible.
+ * @throws OrmException if an error occurred querying the database.
*/
- public List<Change> findChanges(String id)
- throws OrmException, ResourceNotFoundException {
+ public List<ChangeControl> findChanges(String id, CurrentUser user)
+ throws OrmException {
// Try legacy id
if (id.matches("^[1-9][0-9]*$")) {
- Change c = db.get().changes().get(Change.Id.parse(id));
- if (c != null) {
- return ImmutableList.of(c);
+ try {
+ return ImmutableList.of(
+ changeControlFactory.controlFor(Change.Id.parse(id), user));
+ } catch (NoSuchChangeException e) {
+ return Collections.emptyList();
}
- return Collections.emptyList();
}
+ // Use the index to search for changes, but don't return any stored fields,
+ // to force rereading in case the index is stale.
+ InternalChangeQuery query = queryProvider.get()
+ .setRequestedFields(ImmutableSet.<String> of());
+
// Try isolated changeId
if (!id.contains("~")) {
- return asChanges(queryProvider.get().byKeyPrefix(id));
+ return asChangeControls(query.byKeyPrefix(id));
}
// Try change triplet
Optional<ChangeTriplet> triplet = ChangeTriplet.parse(id);
if (triplet.isPresent()) {
- return asChanges(queryProvider.get().byBranchKey(
+ return asChangeControls(query.byBranchKey(
triplet.get().branch(),
triplet.get().id()));
}
- throw new ResourceNotFoundException(id);
+ return Collections.emptyList();
+ }
+
+ private List<ChangeControl> asChangeControls(List<ChangeData> cds)
+ throws OrmException {
+ List<ChangeControl> ctls = new ArrayList<>(cds.size());
+ for (ChangeData cd : cds) {
+ ctls.add(cd.changeControl(user.get()));
+ }
+ return ctls;
}
private static void deleteOnlyDraftPatchSetPreserveRef(ReviewDb db,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java
index a3c0d37..76ab25a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java
@@ -72,7 +72,7 @@
user.asyncStarredChanges();
ChangeResource change = changes.parse(TopLevelResource.INSTANCE, id);
- if (user.getStarredChanges().contains(change.getChange().getId())) {
+ if (user.getStarredChanges().contains(change.getId())) {
return new AccountResource.StarredChange(user, change);
}
throw new ResourceNotFoundException(id);
@@ -141,7 +141,7 @@
dbProvider.get().starredChanges().insert(Collections.singleton(
new StarredChange(new StarredChange.Key(
rsrc.getUser().getAccountId(),
- change.getChange().getId()))));
+ change.getId()))));
} catch (OrmDuplicateKeyException e) {
return Response.none();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
index b55642c..b7617a2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
@@ -132,7 +132,7 @@
@Override
public String id() {
- return Integer.toString(change.getChange().getId().get());
+ return Integer.toString(change.getId().get());
}
@Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
index cb3729b..2d06e93 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
@@ -177,7 +177,7 @@
if (edit.isPresent()) {
throw new ResourceConflictException(String.format(
"edit already exists for the change %s",
- resource.getChange().getChangeId()));
+ resource.getId()));
}
edit = createEdit();
if (!Strings.isNullOrEmpty(path)) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java
index 03d189f..934a408 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java
@@ -49,6 +49,10 @@
return control;
}
+ public Change.Id getId() {
+ return getControl().getId();
+ }
+
public Change getChange() {
return getControl().getChange();
}
@@ -90,7 +94,7 @@
public String getETag() {
CurrentUser user = control.getUser();
Hasher h = Hashing.md5().newHasher()
- .putBoolean(user.getStarredChanges().contains(getChange().getId()));
+ .putBoolean(user.getStarredChanges().contains(getId()));
prepareETag(h, user);
return h.hash().toString();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java
index 1648a5d..c671534 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangesCollection.java
@@ -24,11 +24,11 @@
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.project.ChangeControl;
-import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.QueryChanges;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -42,8 +42,8 @@
public class ChangesCollection implements
RestCollection<TopLevelResource, ChangeResource>,
AcceptsPost<TopLevelResource> {
+ private final Provider<ReviewDb> db;
private final Provider<CurrentUser> user;
- private final ChangeControl.GenericFactory changeControlFactory;
private final Provider<QueryChanges> queryFactory;
private final DynamicMap<RestView<ChangeResource>> views;
private final ChangeUtil changeUtil;
@@ -52,15 +52,15 @@
@Inject
ChangesCollection(
+ Provider<ReviewDb> db,
Provider<CurrentUser> user,
- ChangeControl.GenericFactory changeControlFactory,
Provider<QueryChanges> queryFactory,
DynamicMap<RestView<ChangeResource>> views,
ChangeUtil changeUtil,
CreateChange createChange,
ChangeIndexer changeIndexer) {
+ this.db = db;
this.user = user;
- this.changeControlFactory = changeControlFactory;
this.queryFactory = queryFactory;
this.views = views;
this.changeUtil = changeUtil;
@@ -81,8 +81,8 @@
@Override
public ChangeResource parse(TopLevelResource root, IdString id)
throws ResourceNotFoundException, OrmException {
- List<Change> changes = changeUtil.findChanges(id.encoded());
- if (changes.isEmpty()) {
+ List<ChangeControl> ctls = changeUtil.findChanges(id.encoded(), user.get());
+ if (ctls.isEmpty()) {
Integer changeId = Ints.tryParse(id.get());
if (changeId != null) {
try {
@@ -92,17 +92,15 @@
}
}
}
- if (changes.size() != 1) {
+ if (ctls.size() != 1) {
throw new ResourceNotFoundException(id);
}
- ChangeControl control;
- try {
- control = changeControlFactory.validateFor(changes.get(0), user.get());
- } catch (NoSuchChangeException e) {
+ ChangeControl ctl = ctls.get(0);
+ if (!ctl.isVisible(db.get())) {
throw new ResourceNotFoundException(id);
}
- return new ChangeResource(control);
+ return new ChangeResource(ctl);
}
public ChangeResource parse(Change.Id id)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
index 3768738..576ae76 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
@@ -44,6 +44,7 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.UpdateException;
import com.google.gerrit.server.git.validators.CommitValidators;
+import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.project.ProjectsCollection;
@@ -154,19 +155,19 @@
ObjectId parentCommit;
List<String> groups;
if (input.baseChange != null) {
- List<Change> changes = changeUtil.findChanges(input.baseChange);
- if (changes.size() != 1) {
+ List<ChangeControl> ctls = changeUtil.findChanges(
+ input.baseChange, rsrc.getControl().getUser());
+ if (ctls.size() != 1) {
throw new InvalidChangeOperationException(
"Base change not found: " + input.baseChange);
}
- Change change = Iterables.getOnlyElement(changes);
- if (!rsrc.getControl().controlFor(change).isVisible(db.get())) {
+ ChangeControl ctl = Iterables.getOnlyElement(ctls);
+ if (!ctl.isVisible(db.get())) {
throw new InvalidChangeOperationException(
"Base change not found: " + input.baseChange);
}
- PatchSet ps = db.get().patchSets().get(
- new PatchSet.Id(change.getId(),
- change.currentPatchSetId().get()));
+ PatchSet ps =
+ db.get().patchSets().get(ctl.getChange().currentPatchSetId());
parentCommit = ObjectId.fromString(ps.getRevision().get());
groups = ps.getGroups();
} else {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java
index b276aae..2a99202 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java
@@ -85,8 +85,7 @@
public UiAction.Description getDescription(ChangeResource rsrc) {
try {
return new UiAction.Description()
- .setTitle(String.format("Delete draft change %d",
- rsrc.getChange().getChangeId()))
+ .setTitle("Delete draft change " + rsrc.getId())
.setVisible(allowDrafts
&& rsrc.getChange().getStatus() == Status.DRAFT
&& rsrc.getControl().canDeleteDraft(dbProvider.get()));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
index 6c37252..3a70e09 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
@@ -75,7 +75,7 @@
throws AuthException, ResourceNotFoundException, OrmException,
IOException {
ChangeControl control = rsrc.getControl();
- Change.Id changeId = rsrc.getChange().getId();
+ Change.Id changeId = rsrc.getId();
ReviewDb db = dbProvider.get();
ChangeUpdate update = updateFactory.create(rsrc.getControl());
@@ -103,13 +103,13 @@
if (del.isEmpty()) {
throw new ResourceNotFoundException();
}
- ChangeUtil.bumpRowVersionNotLastUpdatedOn(rsrc.getChange().getId(), db);
+ ChangeUtil.bumpRowVersionNotLastUpdatedOn(rsrc.getId(), db);
db.patchSetApprovals().delete(del);
update.removeReviewer(rsrc.getUser().getAccountId());
if (msg.length() > 0) {
ChangeMessage changeMessage =
- new ChangeMessage(new ChangeMessage.Key(rsrc.getChange().getId(),
+ new ChangeMessage(new ChangeMessage.Key(rsrc.getId(),
ChangeUtil.messageUUID(db)),
control.getUser().getAccountId(),
TimeUtil.nowTs(), rsrc.getChange().currentPatchSetId());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
index 9a658a9..9a72b07 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
@@ -237,8 +237,7 @@
if (message != null) {
changeMessage = new ChangeMessage(
- new ChangeMessage.Key(
- ctl.getChange().getId(), ChangeUtil.messageUUID(db)),
+ new ChangeMessage.Key(ctl.getId(), ChangeUtil.messageUUID(db)),
ctx.getUser().getAccountId(), ctx.getWhen(), patchSet.getId());
changeMessage.setMessage(message);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java
index a3fc2e1..6d7720d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java
@@ -52,7 +52,7 @@
req.getChange().getProject(), req.getControl().getUser(),
TimeUtil.nowTs())) {
SetHashtagsOp op = hashtagsFactory.create(input);
- bu.addOp(req.getChange().getId(), op);
+ bu.addOp(req.getId(), op);
bu.execute();
return Response.<ImmutableSortedSet<String>> ok(op.getUpdatedHashtags());
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
index 3ab84ab..1766ed2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
@@ -230,9 +230,9 @@
ReviewDb db = dbProvider.get();
ChangeUpdate update = updateFactory.create(rsrc.getControl());
List<PatchSetApproval> added;
- db.changes().beginTransaction(rsrc.getChange().getId());
+ db.changes().beginTransaction(rsrc.getId());
try {
- ChangeUtil.bumpRowVersionNotLastUpdatedOn(rsrc.getChange().getId(), db);
+ ChangeUtil.bumpRowVersionNotLastUpdatedOn(rsrc.getId(), db);
added = approvalsUtil.addReviewers(db, rsrc.getNotes(), update,
rsrc.getControl().getLabelTypes(), rsrc.getChange(),
reviewers.keySet());
@@ -243,7 +243,7 @@
update.commit();
CheckedFuture<?, IOException> indexFuture =
- indexer.indexAsync(rsrc.getChange().getId());
+ indexer.indexAsync(rsrc.getId());
result.reviewers = Lists.newArrayListWithCapacity(added.size());
for (PatchSetApproval psa : added) {
// New reviewers have value 0, don't bother normalizing.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
index ae12497..df629bb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
@@ -77,7 +77,7 @@
Op op = new Op(ctl, input != null ? input : new Input());
try (BatchUpdate u = batchUpdateFactory.create(dbProvider.get(),
req.getChange().getProject(), ctl.getUser(), TimeUtil.nowTs())) {
- u.addOp(req.getChange().getId(), op);
+ u.addOp(req.getId(), op);
u.execute();
}
return Strings.isNullOrEmpty(op.newTopicName)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
index ce2e81d..421fced 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
@@ -87,7 +87,7 @@
Op op = new Op(input);
try (BatchUpdate u = batchUpdateFactory.create(dbProvider.get(),
req.getChange().getProject(), ctl.getUser(), TimeUtil.nowTs())) {
- u.addOp(req.getChange().getId(), op).execute();
+ u.addOp(req.getId(), op).execute();
}
return json.create(ChangeJson.NO_OPTIONS).format(op.change);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revisions.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revisions.java
index bb5775b..734ebb6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revisions.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revisions.java
@@ -129,7 +129,7 @@
// Chance of collision rises; look at all patch sets on the change.
List<RevisionResource> out = Lists.newArrayList();
for (PatchSet ps : dbProvider.get().patchSets()
- .byChange(change.getChange().getId())) {
+ .byChange(change.getId())) {
if (ps.getRevision() != null && ps.getRevision().get().startsWith(id)) {
out.add(new RevisionResource(change, ps));
}
@@ -141,7 +141,7 @@
private List<RevisionResource> byLegacyPatchSetId(ChangeResource change,
String id) throws OrmException {
PatchSet ps = dbProvider.get().patchSets().get(new PatchSet.Id(
- change.getChange().getId(),
+ change.getId(),
Integer.parseInt(id)));
if (ps != null) {
return Collections.singletonList(new RevisionResource(change, ps));
@@ -161,8 +161,7 @@
throws AuthException, IOException {
Optional<ChangeEdit> edit = editUtil.byChange(change.getChange());
if (edit.isPresent()) {
- PatchSet ps = new PatchSet(new PatchSet.Id(
- change.getChange().getId(), 0));
+ PatchSet ps = new PatchSet(new PatchSet.Id(change.getId(), 0));
ps.setRevision(edit.get().getRevision());
if (revid == null || edit.get().getRevision().equals(revid)) {
return Collections.singletonList(
@@ -174,7 +173,7 @@
private static List<RevisionResource> toResources(final ChangeResource change,
Iterable<PatchSet> patchSets) {
- final Change.Id changeId = change.getChange().getId();
+ final Change.Id changeId = change.getId();
return FluentIterable.from(patchSets)
.filter(new Predicate<PatchSet>() {
@Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ThreadSettingsConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ThreadSettingsConfig.java
new file mode 100644
index 0000000..c62583e
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ThreadSettingsConfig.java
@@ -0,0 +1,55 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.config;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.lib.Config;
+
+@Singleton
+public class ThreadSettingsConfig {
+ private final int sshdThreads;
+ private final int httpdMaxThreads;
+ private final int sshdBatchThreads;
+ private final int databasePoolLimit;
+
+ @Inject
+ ThreadSettingsConfig(@GerritServerConfig Config cfg) {
+ int cores = Runtime.getRuntime().availableProcessors();
+ sshdThreads = cfg.getInt("sshd", "threads", 2 * cores);
+ httpdMaxThreads = cfg.getInt("httpd", "maxThreads", 25);
+ int defaultDatabasePoolLimit = sshdThreads + httpdMaxThreads + 2;
+ databasePoolLimit =
+ cfg.getInt("database", "poolLimit", defaultDatabasePoolLimit);
+ sshdBatchThreads = cores == 1 ? 1 : 2;
+ }
+
+ public int getDatabasePoolLimit() {
+ return databasePoolLimit;
+ }
+
+ public int getHttpdMaxThreads() {
+ return httpdMaxThreads;
+ }
+
+ public int getSshdThreads() {
+ return sshdThreads;
+ }
+
+ public int getSshdBatchTreads() {
+ return sshdBatchThreads;
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/LabelNormalizer.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/LabelNormalizer.java
index 0dc7aa9..097ab6e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/LabelNormalizer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/LabelNormalizer.java
@@ -116,7 +116,7 @@
LabelTypes labelTypes = ctl.getLabelTypes();
for (PatchSetApproval psa : approvals) {
Change.Id changeId = psa.getKey().getParentKey().getParentKey();
- checkArgument(changeId.equals(ctl.getChange().getId()),
+ checkArgument(changeId.equals(ctl.getId()),
"Approval %s does not match change %s",
psa.getKey(), ctl.getChange().getKey());
if (psa.isSubmit()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexedChangeQuery.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexedChangeQuery.java
index 683f8cf..28fa9f8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexedChangeQuery.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexedChangeQuery.java
@@ -50,7 +50,7 @@
int backendLimit = opts.config().maxLimit();
int limit = Ints.saturatedCast((long) opts.limit() + opts.start());
limit = Math.min(limit, backendLimit);
- return QueryOptions.create(opts.config(), 0, limit);
+ return QueryOptions.create(opts.config(), 0, limit, opts.fields());
}
private final ChangeIndex index;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/Schema.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/Schema.java
index df70292..a605461 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/Schema.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/Schema.java
@@ -61,6 +61,8 @@
}
private final ImmutableMap<String, FieldDef<T, ?>> fields;
+ private final ImmutableMap<String, FieldDef<T, ?>> storedFields;
+
private int version;
protected Schema(Iterable<FieldDef<T, ?>> fields) {
@@ -71,10 +73,15 @@
public Schema(int version, Iterable<FieldDef<T, ?>> fields) {
this.version = version;
ImmutableMap.Builder<String, FieldDef<T, ?>> b = ImmutableMap.builder();
+ ImmutableMap.Builder<String, FieldDef<T, ?>> sb = ImmutableMap.builder();
for (FieldDef<T, ?> f : fields) {
b.put(f.getName(), f);
+ if (f.isStored()) {
+ sb.put(f.getName(), f);
+ }
}
this.fields = b.build();
+ this.storedFields = sb.build();
}
public final int getVersion() {
@@ -95,6 +102,14 @@
}
/**
+ * @return all fields in this schema where {@link FieldDef#isStored()} is
+ * true.
+ */
+ public final ImmutableMap<String, FieldDef<T, ?>> getStoredFields() {
+ return storedFields;
+ }
+
+ /**
* Look up fields in this schema.
*
* @param first the preferred field to look up.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
index fb41027..22c8da4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
@@ -86,8 +86,7 @@
}
public void setPatchSetId(PatchSet.Id psId) {
- checkArgument(psId == null
- || psId.getParentKey().equals(getChange().getId()));
+ checkArgument(psId == null || psId.getParentKey().equals(ctl.getId()));
this.psId = psId;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
index bd8f797..acd2852 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
@@ -98,7 +98,7 @@
IdentifiedUser user = ctl.getUser().asIdentifiedUser();
this.accountId = user.getAccountId();
this.changeNotes = getChangeNotes().load();
- this.draftNotes = draftNotesFactory.create(ctl.getChange().getId(),
+ this.draftNotes = draftNotesFactory.create(ctl.getId(),
user.getAccountId());
this.upsertComments = Lists.newArrayList();
@@ -273,7 +273,7 @@
@Override
protected String getRefName() {
- return RefNames.refsDraftComments(accountId, getChange().getId());
+ return RefNames.refsDraftComments(accountId, ctl.getId());
}
@Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index 1d8e507..08632dd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -387,7 +387,7 @@
@Override
protected String getRefName() {
- return ChangeNoteUtil.changeRefName(getChange().getId());
+ return ChangeNoteUtil.changeRefName(ctl.getId());
}
@Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
index 8a50114..606ca78d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
@@ -90,7 +90,7 @@
throws NoSuchChangeException, OrmException {
ChangeControl c = controlFor(change, user);
if (!c.isVisible(db.get())) {
- throw new NoSuchChangeException(c.getChange().getId());
+ throw new NoSuchChangeException(c.getId());
}
return c;
}
@@ -153,6 +153,10 @@
return getProjectControl().getProject();
}
+ public Change.Id getId() {
+ return notes.getChangeId();
+ }
+
public Change getChange() {
return notes.getChange();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
index c06029b..a3fb523 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -416,7 +416,7 @@
this.patchListCache = patchListCache;
this.notesMigration = notesMigration;
this.mergeabilityCache = mergeabilityCache;
- legacyId = c.getChange().getId();
+ legacyId = c.getId();
change = c.getChange();
changeControl = c;
notes = c.getNotes();
@@ -544,6 +544,23 @@
return changeControl;
}
+ public ChangeControl changeControl(CurrentUser user) throws OrmException {
+ if (changeControl != null) {
+ throw new IllegalStateException(
+ "user already specified: " + changeControl.getUser());
+ }
+ try {
+ if (change != null) {
+ changeControl = changeControlFactory.controlFor(change, user);
+ } else {
+ changeControl = changeControlFactory.controlFor(legacyId, user);
+ }
+ } catch (NoSuchChangeException e) {
+ throw new OrmException(e);
+ }
+ return changeControl;
+ }
+
void cacheVisibleTo(ChangeControl ctl) {
visibleTo = ctl.getUser();
changeControl = ctl;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java
index a2ccc3a..2dde972 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java
@@ -106,6 +106,11 @@
return this;
}
+ public InternalChangeQuery setRequestedFields(Set<String> fields) {
+ qp.setRequestedFields(fields);
+ return this;
+ }
+
public List<ChangeData> byKey(Change.Key key) throws OrmException {
return byKeyPrefix(key.get());
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryOptions.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryOptions.java
index 1964fa5..a70f892 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryOptions.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryOptions.java
@@ -17,29 +17,36 @@
import static com.google.common.base.Preconditions.checkArgument;
import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
import com.google.gerrit.server.index.IndexConfig;
+import java.util.Set;
+
@AutoValue
public abstract class QueryOptions {
- public static QueryOptions create(IndexConfig config, int start, int limit) {
+ public static QueryOptions create(IndexConfig config, int start, int limit,
+ Set<String> fields) {
checkArgument(start >= 0, "start must be nonnegative: %s", start);
checkArgument(limit > 0, "limit must be positive: %s", limit);
- return new AutoValue_QueryOptions(config, start, limit);
+ return new AutoValue_QueryOptions(config, start, limit,
+ ImmutableSet.copyOf(fields));
}
public static QueryOptions oneResult() {
- return create(IndexConfig.createDefault(), 0, 1);
+ return create(IndexConfig.createDefault(), 0, 1,
+ ImmutableSet.<String> of());
}
public abstract IndexConfig config();
public abstract int start();
public abstract int limit();
+ public abstract ImmutableSet<String> fields();
public QueryOptions withLimit(int newLimit) {
- return create(config(), start(), newLimit);
+ return create(config(), start(), newLimit, fields());
}
public QueryOptions withStart(int newStart) {
- return create(config(), newStart, limit());
+ return create(config(), newStart, limit(), fields());
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
index c3c70b3..1a6ae02 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
@@ -18,6 +18,7 @@
import static com.google.gerrit.server.query.change.ChangeStatusPredicate.open;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Ordering;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.metrics.Description;
@@ -25,6 +26,8 @@
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.index.ChangeIndex;
+import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.index.IndexRewriter;
@@ -39,11 +42,13 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
public class QueryProcessor {
private final Provider<ReviewDb> db;
private final Provider<CurrentUser> userProvider;
private final ChangeControl.GenericFactory changeControlFactory;
+ private final IndexCollection indexes;
private final IndexRewriter rewriter;
private final IndexConfig indexConfig;
private final Metrics metrics;
@@ -51,17 +56,20 @@
private int limitFromCaller;
private int start;
private boolean enforceVisibility = true;
+ private Set<String> requestedFields;
@Inject
QueryProcessor(Provider<ReviewDb> db,
Provider<CurrentUser> userProvider,
ChangeControl.GenericFactory changeControlFactory,
+ IndexCollection indexes,
IndexRewriter rewriter,
IndexConfig indexConfig,
Metrics metrics) {
this.db = db;
this.userProvider = userProvider;
this.changeControlFactory = changeControlFactory;
+ this.indexes = indexes;
this.rewriter = rewriter;
this.indexConfig = indexConfig;
this.metrics = metrics;
@@ -82,6 +90,11 @@
return this;
}
+ public QueryProcessor setRequestedFields(Set<String> fields) {
+ requestedFields = fields;
+ return this;
+ }
+
/**
* Query for changes that match a structured query.
*
@@ -150,7 +163,8 @@
"Cannot go beyond page " + indexConfig.maxPages() + "of results");
}
- QueryOptions opts = QueryOptions.create(indexConfig, start, limit + 1);
+ QueryOptions opts = QueryOptions.create(
+ indexConfig, start, limit + 1, getRequestedFields());
Predicate<ChangeData> s = rewriter.rewrite(q, opts);
if (!(s instanceof ChangeDataSource)) {
q = Predicate.and(open(), q);
@@ -184,6 +198,16 @@
return out;
}
+ private Set<String> getRequestedFields() {
+ if (requestedFields != null) {
+ return requestedFields;
+ }
+ ChangeIndex index = indexes.getSearchIndex();
+ return index != null
+ ? index.getSchema().getStoredFields().keySet()
+ : ImmutableSet.<String> of();
+ }
+
boolean isDisabled() {
return getPermittedLimit() <= 0;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
index e0482f9..0c3bf67 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
@@ -27,6 +27,7 @@
import com.google.gerrit.server.config.ConfigSection;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gwtorm.jdbc.SimpleDataSource;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -47,21 +48,22 @@
@Singleton
public class DataSourceProvider implements Provider<DataSource>,
LifecycleListener {
- public static final int DEFAULT_POOL_LIMIT = 8;
-
private final Config cfg;
private final MetricMaker metrics;
private final Context ctx;
private final DataSourceType dst;
+ private final ThreadSettingsConfig threadSettingsConfig;
private DataSource ds;
@Inject
protected DataSourceProvider(@GerritServerConfig Config cfg,
MetricMaker metrics,
+ ThreadSettingsConfig threadSettingsConfig,
Context ctx,
DataSourceType dst) {
this.cfg = cfg;
this.metrics = metrics;
+ this.threadSettingsConfig = threadSettingsConfig;
this.ctx = ctx;
this.dst = dst;
}
@@ -127,9 +129,11 @@
if (password != null && !password.isEmpty()) {
ds.setPassword(password);
}
- ds.setMaxActive(cfg.getInt("database", "poollimit", DEFAULT_POOL_LIMIT));
+ int poolLimit = threadSettingsConfig.getDatabasePoolLimit();
+ ds.setMaxActive(poolLimit);
ds.setMinIdle(cfg.getInt("database", "poolminidle", 4));
- ds.setMaxIdle(cfg.getInt("database", "poolmaxidle", 4));
+ ds.setMaxIdle(
+ cfg.getInt("database", "poolmaxidle", Math.min(poolLimit, 16)));
ds.setMaxWait(ConfigUtil.getTimeUnit(cfg, "database", null,
"poolmaxwait", MILLISECONDS.convert(30, SECONDS), MILLISECONDS));
ds.setInitialSize(ds.getMinIdle());
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg b/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
index 6988459..5370156 100644
--- a/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
@@ -63,6 +63,10 @@
AWK=/usr/xpg4/bin/awk
fi
+ # Get core.commentChar from git config or use default symbol
+ commentChar=`git config --get core.commentChar`
+ commentChar=${commentChar:-#}
+
# How this works:
# - parse the commit message as (textLine+ blankLine*)*
# - assume textLine+ to be a footer until proven otherwise
@@ -81,8 +85,8 @@
blankLines = 0
}
- # Skip lines starting with "#" without any spaces before it.
- /^#/ { next }
+ # Skip lines starting with commentChar without any spaces before it.
+ /^'"$commentChar"'/ { next }
# Skip the line starting with the diff command and everything after it,
# up to the end of the file, assuming it is only patch data.
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriterTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriterTest.java
index 7b1185e..f44d172 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriterTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriterTest.java
@@ -25,6 +25,7 @@
import static com.google.gerrit.server.query.Predicate.or;
import static org.junit.Assert.assertEquals;
+import com.google.common.collect.ImmutableSet;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.query.AndPredicate;
import com.google.gerrit.server.query.Predicate;
@@ -285,7 +286,8 @@
}
private static QueryOptions options(int start, int limit) {
- return QueryOptions.create(CONFIG, start, limit);
+ return QueryOptions.create(CONFIG, start, limit,
+ ImmutableSet.<String> of());
}
private Set<Change.Status> status(String query) throws QueryParseException {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index dd2667f..49e1796 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -56,6 +56,7 @@
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.validators.CommitValidators;
+import com.google.gerrit.server.index.ChangeField;
import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.ChangeControl;
@@ -1263,6 +1264,30 @@
cd.messages();
}
+ @Test
+ public void prepopulateOnlyRequestedFields() throws Exception {
+ assume().that(notesMigration.enabled()).isFalse();
+ TestRepository<Repo> repo = createProject("repo");
+ Change change = insert(newChange(repo, null, null, null, null));
+
+ db = new DisabledReviewDb();
+ requestContext.setContext(newRequestContext(userId));
+ // Use QueryProcessor directly instead of API so we get ChangeDatas back.
+ List<ChangeData> cds = queryProcessor
+ .setRequestedFields(ImmutableSet.of(
+ ChangeField.PATCH_SET.getName(),
+ ChangeField.CHANGE.getName()))
+ .queryChanges(queryBuilder.parse(change.getId().toString()))
+ .changes();
+ assertThat(cds).hasSize(1);
+
+ ChangeData cd = cds.get(0);
+ cd.change();
+ cd.patchSets();
+
+ exception.expect(DisabledReviewDb.Disabled.class);
+ cd.currentApprovals();
+ }
protected ChangeInserter newChange(
TestRepository<Repo> repo,
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/LuceneQueryChangesV14Test.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/LuceneQueryChangesV14Test.java
index 7e7899b..53a9805 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/LuceneQueryChangesV14Test.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/LuceneQueryChangesV14Test.java
@@ -78,6 +78,13 @@
// Ignore.
}
+ @Override
+ @Ignore
+ @Test
+ public void prepopulateOnlyRequestedFields() throws Exception {
+ // Ignore.
+ }
+
@Test
public void isReviewed() throws Exception {
clockStepMs = MILLISECONDS.convert(2, MINUTES);
diff --git a/gerrit-server/src/test/java/com/google/gerrit/testutil/TestChanges.java b/gerrit-server/src/test/java/com/google/gerrit/testutil/TestChanges.java
index aa7b38b..f35dbea 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/testutil/TestChanges.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/testutil/TestChanges.java
@@ -108,6 +108,7 @@
ChangeNotes notes = new ChangeNotes(repoManager, migration, allUsers, c)
.load();
expect(ctl.getNotes()).andStubReturn(notes);
+ expect(ctl.getId()).andStubReturn(c.getId());
EasyMock.replay(ctl);
return ctl;
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java
index f78aba4..88e1142 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java
@@ -15,6 +15,7 @@
package com.google.gerrit.sshd;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gerrit.server.git.QueueProvider;
import com.google.gerrit.server.git.WorkQueue;
import com.google.inject.Inject;
@@ -31,11 +32,13 @@
private final WorkQueue.Executor batchExecutor;
@Inject
- public CommandExecutorQueueProvider(@GerritServerConfig final Config config,
- final WorkQueue queues) {
- final int cores = Runtime.getRuntime().availableProcessors();
- poolSize = config.getInt("sshd", "threads", 3 * cores / 2);
- batchThreads = config.getInt("sshd", "batchThreads", cores == 1 ? 1 : 2);
+ public CommandExecutorQueueProvider(
+ @GerritServerConfig Config config,
+ ThreadSettingsConfig threadsSettingsConfig,
+ WorkQueue queues) {
+ poolSize = threadsSettingsConfig.getSshdThreads();
+ batchThreads = config.getInt("sshd", "batchThreads",
+ threadsSettingsConfig.getSshdBatchTreads());
if (batchThreads > poolSize) {
poolSize += batchThreads;
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
index e9043f7..db32b3f 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
@@ -18,9 +18,8 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ChangesCollection;
@@ -28,14 +27,10 @@
import com.google.gerrit.server.change.PostReviewers;
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.project.ChangeControl;
-import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectControl;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -47,7 +42,9 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
@CommandMetaData(name = "set-reviewers", description = "Add or remove reviewers on a change")
@@ -69,7 +66,7 @@
@Argument(index = 0, required = true, multiValued = true, metaVar = "COMMIT", usage = "changes to modify")
void addChange(String token) {
try {
- changes.addAll(parseChangeId(token));
+ addChangeImpl(token);
} catch (UnloggedFailure e) {
throw new IllegalArgumentException(e.getMessage(), e);
} catch (OrmException e) {
@@ -81,9 +78,6 @@
private ReviewDb db;
@Inject
- private Provider<InternalChangeQuery> queryProvider;
-
- @Inject
private ReviewerResource.Factory reviewerFactory;
@Inject
@@ -96,24 +90,25 @@
private Provider<CurrentUser> userProvider;
@Inject
- private ChangeControl.GenericFactory changeControlFactory;
-
- @Inject
private ChangesCollection changesCollection;
+ @Inject
+ private ChangeUtil changeUtil;
+
private Set<Account.Id> toRemove = new HashSet<>();
- private Set<Change.Id> changes = new HashSet<>();
+
+ private Map<Change.Id, ChangeResource> changes = new LinkedHashMap<>();
@Override
protected void run() throws UnloggedFailure {
boolean ok = true;
- for (Change.Id changeId : changes) {
+ for (ChangeResource rsrc : changes.values()) {
try {
- ok &= modifyOne(changeId);
+ ok &= modifyOne(rsrc);
} catch (Exception err) {
ok = false;
- log.error("Error updating reviewers on change " + changeId, err);
- writeError("fatal", "internal error while updating " + changeId);
+ log.error("Error updating reviewers on change " + rsrc.getId(), err);
+ writeError("fatal", "internal error while updating " + rsrc.getId());
}
}
@@ -122,8 +117,7 @@
}
}
- private boolean modifyOne(Change.Id changeId) throws Exception {
- ChangeResource changeRsrc = changesCollection.parse(changeId);
+ private boolean modifyOne(ChangeResource changeRsrc) throws Exception {
boolean ok = true;
// Remove reviewers
@@ -168,92 +162,28 @@
return ok;
}
- private Set<Change.Id> parseChangeId(String idstr)
- throws UnloggedFailure, OrmException {
- Set<Change.Id> matched = new HashSet<>(4);
- boolean isCommit = idstr.matches("^([0-9a-fA-F]{4," + RevId.LEN + "})$");
-
- // By newer style changeKey?
- //
- boolean changeKeyParses = idstr.matches("^I[0-9a-f]*$");
- if (changeKeyParses) {
- for (ChangeData cd : queryProvider.get().byKeyPrefix(idstr)) {
- matchChange(matched, cd.change());
+ private void addChangeImpl(String id) throws UnloggedFailure, OrmException {
+ List<ChangeControl> matched =
+ changeUtil.findChanges(id, userProvider.get());
+ List<ChangeControl> toAdd = new ArrayList<>(changes.size());
+ for (ChangeControl ctl : matched) {
+ Change c = ctl.getChange();
+ if (!changes.containsKey(c.getId()) && inProject(c)
+ && ctl.isVisible(db)) {
+ toAdd.add(ctl);
}
}
-
- // By commit?
- //
- if (isCommit) {
- RevId id = new RevId(idstr);
- ResultSet<PatchSet> patches;
- if (id.isComplete()) {
- patches = db.patchSets().byRevision(id);
- } else {
- patches = db.patchSets().byRevisionRange(id, id.max());
- }
-
- for (PatchSet ps : patches) {
- matchChange(matched, ps.getId().getParentKey());
- }
- }
-
- // By older style changeId?
- //
- boolean changeIdParses = false;
- if (idstr.matches("^[1-9][0-9]*$")) {
- Change.Id id;
- try {
- id = Change.Id.parse(idstr);
- changeIdParses = true;
- } catch (IllegalArgumentException e) {
- id = null;
- changeIdParses = false;
- }
-
- if (changeIdParses) {
- matchChange(matched, id);
- }
- }
-
- if (!changeKeyParses && !isCommit && !changeIdParses) {
- throw error("\"" + idstr + "\" is not a valid change");
- }
-
- switch (matched.size()) {
+ switch (toAdd.size()) {
case 0:
- throw error("\"" + idstr + "\" no such change");
+ throw error("\"" + id + "\" no such change");
case 1:
- return matched;
+ ChangeControl ctl = toAdd.get(0);
+ changes.put(ctl.getId(), changesCollection.parse(ctl));
+ break;
default:
- throw error("\"" + idstr + "\" matches multiple changes");
- }
- }
-
- private void matchChange(Set<Change.Id> matched, Change.Id changeId) {
- if (changeId != null && !matched.contains(changeId)) {
- try {
- matchChange(matched, db.changes().get(changeId));
- } catch (OrmException e) {
- log.warn("Error reading change " + changeId, e);
- }
- }
- }
-
- private void matchChange(Set<Change.Id> matched, Change change) {
- try {
- if (change != null
- && inProject(change)
- && changeControlFactory.controlFor(change,
- userProvider.get()).isVisible(db)) {
- matched.add(change.getId());
- }
- } catch (NoSuchChangeException e) {
- // Ignore this change.
- } catch (OrmException e) {
- log.warn("Error reading change " + change.getId(), e);
+ throw error("\"" + id + "\" matches multiple changes");
}
}