Line data Source code
1 : // Copyright (C) 2010 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.query.change; 16 : 17 : import static com.google.common.base.Preconditions.checkState; 18 : import static com.google.gerrit.server.query.change.ChangeQueryBuilder.FIELD_LIMIT; 19 : 20 : import com.google.common.collect.ImmutableListMultimap; 21 : import com.google.gerrit.entities.Change; 22 : import com.google.gerrit.extensions.common.PluginDefinedInfo; 23 : import com.google.gerrit.extensions.registration.DynamicSet; 24 : import com.google.gerrit.extensions.registration.Extension; 25 : import com.google.gerrit.index.IndexConfig; 26 : import com.google.gerrit.index.QueryOptions; 27 : import com.google.gerrit.index.query.IndexPredicate; 28 : import com.google.gerrit.index.query.Predicate; 29 : import com.google.gerrit.index.query.QueryProcessor; 30 : import com.google.gerrit.metrics.MetricMaker; 31 : import com.google.gerrit.server.CurrentUser; 32 : import com.google.gerrit.server.DynamicOptions; 33 : import com.google.gerrit.server.DynamicOptions.DynamicBean; 34 : import com.google.gerrit.server.account.AccountLimits; 35 : import com.google.gerrit.server.change.ChangePluginDefinedInfoFactory; 36 : import com.google.gerrit.server.change.PluginDefinedAttributesFactories; 37 : import com.google.gerrit.server.change.PluginDefinedInfosFactory; 38 : import com.google.gerrit.server.index.change.ChangeIndexCollection; 39 : import com.google.gerrit.server.index.change.ChangeIndexRewriter; 40 : import com.google.gerrit.server.index.change.ChangeSchemaDefinitions; 41 : import com.google.gerrit.server.index.change.IndexedChangeQuery; 42 : import com.google.gerrit.server.notedb.Sequences; 43 : import com.google.inject.Inject; 44 : import com.google.inject.Provider; 45 : import java.util.ArrayList; 46 : import java.util.Collection; 47 : import java.util.HashMap; 48 : import java.util.List; 49 : import java.util.Map; 50 : import java.util.Set; 51 : 52 : /** 53 : * Query processor for the change index. 54 : * 55 : * <p>Instances are one-time-use. Other singleton classes should inject a Provider rather than 56 : * holding on to a single instance. 57 : */ 58 : public class ChangeQueryProcessor extends QueryProcessor<ChangeData> 59 : implements DynamicOptions.BeanReceiver, DynamicOptions.BeanProvider, PluginDefinedInfosFactory { 60 : private final Provider<CurrentUser> userProvider; 61 : private final ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory; 62 111 : private final Map<String, DynamicBean> dynamicBeans = new HashMap<>(); 63 111 : private final List<Extension<ChangePluginDefinedInfoFactory>> 64 : changePluginDefinedInfoFactoriesByPlugin = new ArrayList<>(); 65 : private final Sequences sequences; 66 : private final IndexConfig indexConfig; 67 : 68 : static { 69 : // It is assumed that basic rewrites do not touch visibleto predicates. 70 111 : checkState( 71 111 : !ChangeIsVisibleToPredicate.class.isAssignableFrom(IndexPredicate.class), 72 : "ChangeQueryProcessor assumes visibleto is not used by the index rewriter."); 73 111 : } 74 : 75 : @Inject 76 : ChangeQueryProcessor( 77 : Provider<CurrentUser> userProvider, 78 : AccountLimits.Factory limitsFactory, 79 : MetricMaker metricMaker, 80 : IndexConfig indexConfig, 81 : ChangeIndexCollection indexes, 82 : ChangeIndexRewriter rewriter, 83 : Sequences sequences, 84 : ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory, 85 : DynamicSet<ChangePluginDefinedInfoFactory> changePluginDefinedInfoFactories) { 86 111 : super( 87 : metricMaker, 88 : ChangeSchemaDefinitions.INSTANCE, 89 : indexConfig, 90 : indexes, 91 : rewriter, 92 : FIELD_LIMIT, 93 111 : () -> limitsFactory.create(userProvider.get()).getQueryLimit()); 94 111 : this.userProvider = userProvider; 95 111 : this.changeIsVisibleToPredicateFactory = changeIsVisibleToPredicateFactory; 96 111 : this.sequences = sequences; 97 111 : this.indexConfig = indexConfig; 98 : 99 111 : changePluginDefinedInfoFactories 100 111 : .entries() 101 111 : .forEach(e -> changePluginDefinedInfoFactoriesByPlugin.add(e)); 102 111 : } 103 : 104 : @Override 105 : public ChangeQueryProcessor enforceVisibility(boolean enforce) { 106 111 : super.enforceVisibility(enforce); 107 111 : return this; 108 : } 109 : 110 : @Override 111 : protected QueryOptions createOptions( 112 : IndexConfig indexConfig, 113 : int start, 114 : int pageSize, 115 : int pageSizeMultiplier, 116 : int limit, 117 : Set<String> requestedFields) { 118 111 : return IndexedChangeQuery.createOptions( 119 : indexConfig, start, pageSize, pageSizeMultiplier, limit, requestedFields); 120 : } 121 : 122 : @Override 123 : public void setDynamicBean(String plugin, DynamicBean dynamicBean) { 124 4 : dynamicBeans.put(plugin, dynamicBean); 125 4 : } 126 : 127 : @Override 128 : public DynamicBean getDynamicBean(String plugin) { 129 3 : return dynamicBeans.get(plugin); 130 : } 131 : 132 : public PluginDefinedInfosFactory getInfosFactory() { 133 26 : return this::createPluginDefinedInfos; 134 : } 135 : 136 : @Override 137 : public ImmutableListMultimap<Change.Id, PluginDefinedInfo> createPluginDefinedInfos( 138 : Collection<ChangeData> cds) { 139 28 : return PluginDefinedAttributesFactories.createAll( 140 28 : cds, this, changePluginDefinedInfoFactoriesByPlugin.stream()); 141 : } 142 : 143 : @Override 144 : protected Predicate<ChangeData> enforceVisibility(Predicate<ChangeData> pred) { 145 103 : return new AndChangeSource( 146 103 : pred, changeIsVisibleToPredicateFactory.forUser(userProvider.get()), start, indexConfig); 147 : } 148 : 149 : @Override 150 : protected String formatForLogging(ChangeData changeData) { 151 11 : return changeData.getId().toString(); 152 : } 153 : 154 : @Override 155 : protected int getIndexSize() { 156 0 : return sequences.lastChangeId(); 157 : } 158 : 159 : @Override 160 : protected int getBatchSize() { 161 0 : return sequences.changeBatchSize(); 162 : } 163 : 164 : @Override 165 : protected int getInitialPageSize(int limit) { 166 111 : return Math.min(getUserQueryLimit().getAsInt(), limit); 167 : } 168 : }