diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2021-07-27 16:10:33 -0500 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-08-04 20:08:14 +0000 |
commit | bc4d1696a5998adcadb03c64e21aff4a467a1ab1 (patch) | |
tree | 7dd07d23f17e805db73dd60a961b05d210fdf53c /server/sonar-webserver-core/src | |
parent | c63120be2e7c090ca42d120c756e703e7cc9eaa1 (diff) | |
download | sonarqube-bc4d1696a5998adcadb03c64e21aff4a467a1ab1.tar.gz sonarqube-bc4d1696a5998adcadb03c64e21aff4a467a1ab1.zip |
SONAR-15237 Improve startup performance of the web process
Diffstat (limited to 'server/sonar-webserver-core/src')
8 files changed, 117 insertions, 415 deletions
diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/CachingRuleFinder.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/CachingRuleFinder.java deleted file mode 100644 index f4fe7a0ce87..00000000000 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/CachingRuleFinder.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.rule; - -import com.google.common.collect.ImmutableListMultimap; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Ordering; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.RuleStatus; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.rules.RuleQuery; -import org.sonar.core.util.stream.MoreCollectors; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.rule.RuleDefinitionDto; -import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleParamDto; -import org.sonar.markdown.Markdown; - -import static com.google.common.collect.Lists.newArrayList; -import static org.sonar.core.util.stream.MoreCollectors.toSet; -import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; - -/** - * A {@link RuleFinder} implementation that retrieves all rule definitions and their parameter when instantiated, cache - * them in memory and provide implementation of {@link RuleFinder}'s method which only read from this data in memory. - */ -public class CachingRuleFinder implements ServerRuleFinder { - - private static final Ordering<Map.Entry<RuleDefinitionDto, Rule>> FIND_BY_QUERY_ORDER = Ordering.natural().reverse().onResultOf(entry -> entry.getKey().getUpdatedAt()); - - private final Map<RuleKey, RuleDefinitionDto> ruleDtosByKey; - private final Map<RuleDefinitionDto, Rule> rulesByRuleDefinition; - private final Map<RuleKey, Rule> rulesByKey; - - public CachingRuleFinder(DbClient dbClient) { - try (DbSession dbSession = dbClient.openSession(false)) { - List<RuleDefinitionDto> dtos = dbClient.ruleDao().selectAllDefinitions(dbSession); - this.ruleDtosByKey = dtos.stream().collect(Collectors.toMap(RuleDefinitionDto::getKey, d -> d)); - this.rulesByRuleDefinition = buildRulesByRuleDefinitionDto(dbClient, dbSession, dtos); - this.rulesByKey = this.rulesByRuleDefinition.entrySet().stream() - .collect(uniqueIndex(entry -> entry.getKey().getKey(), Map.Entry::getValue)); - } - } - - private static Map<RuleDefinitionDto, Rule> buildRulesByRuleDefinitionDto(DbClient dbClient, DbSession dbSession, List<RuleDefinitionDto> dtos) { - Set<RuleKey> ruleKeys = dtos.stream().map(RuleDefinitionDto::getKey).collect(toSet(dtos.size())); - ListMultimap<String, RuleParamDto> ruleParamsByRuleUuid = retrieveRuleParameters(dbClient, dbSession, ruleKeys); - Map<RuleDefinitionDto, Rule> rulesByDefinition = new HashMap<>(dtos.size()); - for (RuleDefinitionDto definition : dtos) { - rulesByDefinition.put(definition, toRule(definition, ruleParamsByRuleUuid.get(definition.getUuid()))); - } - return ImmutableMap.copyOf(rulesByDefinition); - } - - private static ImmutableListMultimap<String, RuleParamDto> retrieveRuleParameters(DbClient dbClient, DbSession dbSession, Set<RuleKey> ruleKeys) { - if (ruleKeys.isEmpty()) { - return ImmutableListMultimap.of(); - } - return dbClient.ruleDao().selectRuleParamsByRuleKeys(dbSession, ruleKeys) - .stream() - .collect(MoreCollectors.index(RuleParamDto::getRuleUuid)); - } - - @Override - @CheckForNull - public Rule findByKey(@Nullable String repositoryKey, @Nullable String key) { - if (repositoryKey == null || key == null) { - return null; - } - return findByKey(RuleKey.of(repositoryKey, key)); - } - - @Override - @CheckForNull - public Rule findByKey(RuleKey key) { - return rulesByKey.get(key); - } - - @Override - @CheckForNull - public Rule find(@Nullable RuleQuery query) { - if (query == null) { - return null; - } - - return rulesByRuleDefinition.entrySet().stream() - .filter(entry -> matchQuery(entry.getKey(), query)) - .sorted(FIND_BY_QUERY_ORDER) - .map(Map.Entry::getValue) - .findFirst() - .orElse(null); - } - - @Override - public Collection<Rule> findAll(@Nullable RuleQuery query) { - if (query == null) { - return Collections.emptyList(); - } - return rulesByRuleDefinition.entrySet().stream() - .filter(entry -> matchQuery(entry.getKey(), query)) - .sorted(FIND_BY_QUERY_ORDER) - .map(Map.Entry::getValue) - .collect(MoreCollectors.toList()); - } - - private static boolean matchQuery(RuleDefinitionDto ruleDefinition, RuleQuery ruleQuery) { - if (RuleStatus.REMOVED.equals(ruleDefinition.getStatus())) { - return false; - } - String repositoryKey = ruleQuery.getRepositoryKey(); - if (ruleQuery.getRepositoryKey() != null && !repositoryKey.equals(ruleDefinition.getRepositoryKey())) { - return false; - } - String key = ruleQuery.getKey(); - if (key != null && !key.equals(ruleDefinition.getRuleKey())) { - return false; - } - String configKey = ruleQuery.getConfigKey(); - return configKey == null || configKey.equals(ruleDefinition.getConfigKey()); - } - - private static Rule toRule(RuleDefinitionDto ruleDefinition, List<RuleParamDto> params) { - String severity = ruleDefinition.getSeverityString(); - String description = ruleDefinition.getDescription(); - RuleDto.Format descriptionFormat = ruleDefinition.getDescriptionFormat(); - - Rule apiRule = new Rule(); - apiRule - .setName(ruleDefinition.getName()) - .setLanguage(ruleDefinition.getLanguage()) - .setKey(ruleDefinition.getRuleKey()) - .setConfigKey(ruleDefinition.getConfigKey()) - .setIsTemplate(ruleDefinition.isTemplate()) - .setCreatedAt(new Date(ruleDefinition.getCreatedAt())) - .setUpdatedAt(new Date(ruleDefinition.getUpdatedAt())) - .setRepositoryKey(ruleDefinition.getRepositoryKey()) - .setSeverity(severity != null ? RulePriority.valueOf(severity) : null) - .setStatus(ruleDefinition.getStatus().name()) - .setSystemTags(ruleDefinition.getSystemTags().toArray(new String[ruleDefinition.getSystemTags().size()])) - .setTags(new String[0]); - if (description != null && descriptionFormat != null) { - if (RuleDto.Format.HTML.equals(descriptionFormat)) { - apiRule.setDescription(description); - } else { - apiRule.setDescription(Markdown.convertToHtml(description)); - } - } - - List<org.sonar.api.rules.RuleParam> apiParams = newArrayList(); - for (RuleParamDto param : params) { - apiParams.add(new org.sonar.api.rules.RuleParam(apiRule, param.getName(), param.getDescription(), param.getType()) - .setDefaultValue(param.getDefaultValue())); - } - apiRule.setParams(apiParams); - - return apiRule; - } - - @Override - public Optional<RuleDefinitionDto> findDtoByKey(RuleKey key) { - return Optional.ofNullable(this.ruleDtosByKey.get(key)); - } -} diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/RegisterRules.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/RegisterRules.java index be384165d5f..85ca920382e 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/RegisterRules.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/RegisterRules.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -35,7 +36,6 @@ import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nullable; -import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.picocontainer.Startable; import org.sonar.api.resources.Languages; @@ -72,7 +72,9 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Sets.difference; import static com.google.common.collect.Sets.intersection; import static java.lang.String.format; +import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; +import static java.util.Collections.unmodifiableMap; import static org.sonar.core.util.stream.MoreCollectors.toList; import static org.sonar.core.util.stream.MoreCollectors.toSet; import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; @@ -113,7 +115,7 @@ public class RegisterRules implements Startable { @Override public void start() { Profiler profiler = Profiler.create(LOG).startInfo("Register rules"); - try (DbSession dbSession = dbClient.openSession(false)) { + try (DbSession dbSession = dbClient.openSession(true)) { RulesDefinition.Context ruleDefinitionContext = defLoader.load(); List<RulesDefinition.Repository> repositories = ruleDefinitionContext.repositories(); RegisterRulesContext registerRulesContext = createRegisterRulesContext(dbSession); @@ -122,9 +124,7 @@ public class RegisterRules implements Startable { for (RulesDefinition.ExtendedRepository repoDef : repositories) { if (languages.get(repoDef.language()) != null) { - for (RulesDefinition.Rule ruleDef : repoDef.rules()) { - registerRule(registerRulesContext, ruleDef, dbSession); - } + registerRules(registerRulesContext, repoDef.rules(), dbSession); dbSession.commit(); } } @@ -153,7 +153,13 @@ public class RegisterRules implements Startable { Map<RuleKey, RuleDefinitionDto> allRules = dbClient.ruleDao().selectAllDefinitions(dbSession).stream() .collect(uniqueIndex(RuleDefinitionDto::getKey)); Map<String, Set<SingleDeprecatedRuleKey>> existingDeprecatedKeysById = loadDeprecatedRuleKeys(dbSession); - return new RegisterRulesContext(allRules, existingDeprecatedKeysById); + Map<String, List<RuleParamDto>> ruleParamsByRuleUuid = loadAllRuleParameters(dbSession); + return new RegisterRulesContext(allRules, existingDeprecatedKeysById, ruleParamsByRuleUuid); + } + + private Map<String, List<RuleParamDto>> loadAllRuleParameters(DbSession dbSession) { + return dbClient.ruleDao().selectAllRuleParams(dbSession).stream() + .collect(Collectors.groupingBy(RuleParamDto::getRuleUuid)); } private Map<String, Set<SingleDeprecatedRuleKey>> loadDeprecatedRuleKeys(DbSession dbSession) { @@ -167,6 +173,7 @@ public class RegisterRules implements Startable { private final Map<RuleKey, RuleDefinitionDto> dbRules; private final Set<RuleDefinitionDto> known; private final Map<String, Set<SingleDeprecatedRuleKey>> dbDeprecatedKeysByUuid; + private final Map<String, List<RuleParamDto>> ruleParamsByRuleUuid; private final Map<RuleKey, RuleDefinitionDto> dbRulesByDbDeprecatedKey; // mutable data private final Set<RuleDefinitionDto> created = new HashSet<>(); @@ -175,10 +182,12 @@ public class RegisterRules implements Startable { private final Set<RuleDefinitionDto> unchanged = new HashSet<>(); private final Set<RuleDefinitionDto> removed = new HashSet<>(); - private RegisterRulesContext(Map<RuleKey, RuleDefinitionDto> dbRules, Map<String, Set<SingleDeprecatedRuleKey>> dbDeprecatedKeysByUuid) { + private RegisterRulesContext(Map<RuleKey, RuleDefinitionDto> dbRules, Map<String, Set<SingleDeprecatedRuleKey>> dbDeprecatedKeysByUuid, + Map<String, List<RuleParamDto>> ruleParamsByRuleUuid) { this.dbRules = ImmutableMap.copyOf(dbRules); this.known = ImmutableSet.copyOf(dbRules.values()); this.dbDeprecatedKeysByUuid = dbDeprecatedKeysByUuid; + this.ruleParamsByRuleUuid = ruleParamsByRuleUuid; this.dbRulesByDbDeprecatedKey = buildDbRulesByDbDeprecatedKey(dbDeprecatedKeysByUuid, dbRules); } @@ -187,19 +196,19 @@ public class RegisterRules implements Startable { Map<String, RuleDefinitionDto> dbRulesByRuleUuid = dbRules.values().stream() .collect(uniqueIndex(RuleDefinitionDto::getUuid)); - ImmutableMap.Builder<RuleKey, RuleDefinitionDto> builder = ImmutableMap.builder(); + Map<RuleKey, RuleDefinitionDto> rulesByKey = new LinkedHashMap<>(); for (Map.Entry<String, Set<SingleDeprecatedRuleKey>> entry : dbDeprecatedKeysByUuid.entrySet()) { String ruleUuid = entry.getKey(); RuleDefinitionDto rule = dbRulesByRuleUuid.get(ruleUuid); if (rule == null) { LOG.warn("Could not retrieve rule with uuid %s referenced by a deprecated rule key. " + - "The following deprecated rule keys seem to be referencing a non-existing rule", + "The following deprecated rule keys seem to be referencing a non-existing rule", ruleUuid, entry.getValue()); } else { - entry.getValue().forEach(d -> builder.put(d.getOldRuleKeyAsRuleKey(), rule)); + entry.getValue().forEach(d -> rulesByKey.put(d.getOldRuleKeyAsRuleKey(), rule)); } } - return builder.build(); + return unmodifiableMap(rulesByKey); } private boolean hasDbRules() { @@ -219,7 +228,7 @@ public class RegisterRules implements Startable { return res; } - private ImmutableMap<RuleKey, SingleDeprecatedRuleKey> getDbDeprecatedKeysByOldRuleKey() { + private Map<RuleKey, SingleDeprecatedRuleKey> getDbDeprecatedKeysByOldRuleKey() { return dbDeprecatedKeysByUuid.values().stream() .flatMap(Collection::stream) .collect(uniqueIndex(SingleDeprecatedRuleKey::getOldRuleKeyAsRuleKey)); @@ -229,6 +238,10 @@ public class RegisterRules implements Startable { return dbDeprecatedKeysByUuid.getOrDefault(rule.getUuid(), emptySet()); } + private List<RuleParamDto> getRuleParametersFor(String ruleUuid) { + return ruleParamsByRuleUuid.getOrDefault(ruleUuid, emptyList()); + } + private Stream<RuleDefinitionDto> getRemaining() { Set<RuleDefinitionDto> res = new HashSet<>(dbRules.values()); res.removeAll(unchanged); @@ -298,8 +311,7 @@ public class RegisterRules implements Startable { } private void persistRepositories(DbSession dbSession, List<RulesDefinition.Repository> repositories) { - List<RuleRepositoryDto> dtos = repositories - .stream() + List<RuleRepositoryDto> dtos = repositories.stream() .map(r -> new RuleRepositoryDto(r.key(), r.language(), r.name())) .collect(toList(repositories.size())); List<String> keys = dtos.stream().map(RuleRepositoryDto::getKey).collect(toList(repositories.size())); @@ -313,46 +325,53 @@ public class RegisterRules implements Startable { // nothing } - private void registerRule(RegisterRulesContext context, RulesDefinition.Rule ruleDef, DbSession session) { - RuleKey ruleKey = RuleKey.of(ruleDef.repository().key(), ruleDef.key()); + private void registerRules(RegisterRulesContext context, List<RulesDefinition.Rule> ruleDefs, DbSession session) { + Map<RulesDefinition.Rule, RuleDefinitionDto> dtos = new LinkedHashMap<>(ruleDefs.size()); - RuleDefinitionDto ruleDefinitionDto = context.getDbRuleFor(ruleDef) - .orElseGet(() -> { - RuleDefinitionDto newRule = createRuleDto(ruleDef, session); - context.created(newRule); - return newRule; - }); + for (RulesDefinition.Rule ruleDef : ruleDefs) { + RuleKey ruleKey = RuleKey.of(ruleDef.repository().key(), ruleDef.key()); - // we must detect renaming __before__ we modify the DTO - if (!ruleDefinitionDto.getKey().equals(ruleKey)) { - context.renamed(ruleDefinitionDto); - ruleDefinitionDto.setRuleKey(ruleKey); - } + RuleDefinitionDto ruleDefinitionDto = context.getDbRuleFor(ruleDef) + .orElseGet(() -> { + RuleDefinitionDto newRule = createRuleDto(ruleDef, session); + context.created(newRule); + return newRule; + }); + dtos.put(ruleDef, ruleDefinitionDto); + + // we must detect renaming __before__ we modify the DTO + if (!ruleDefinitionDto.getKey().equals(ruleKey)) { + context.renamed(ruleDefinitionDto); + ruleDefinitionDto.setRuleKey(ruleKey); + } - if (mergeRule(ruleDef, ruleDefinitionDto)) { - context.updated(ruleDefinitionDto); - } + if (mergeRule(ruleDef, ruleDefinitionDto)) { + context.updated(ruleDefinitionDto); + } - if (mergeDebtDefinitions(ruleDef, ruleDefinitionDto)) { - context.updated(ruleDefinitionDto); - } + if (mergeDebtDefinitions(ruleDef, ruleDefinitionDto)) { + context.updated(ruleDefinitionDto); + } - if (mergeTags(ruleDef, ruleDefinitionDto)) { - context.updated(ruleDefinitionDto); - } + if (mergeTags(ruleDef, ruleDefinitionDto)) { + context.updated(ruleDefinitionDto); + } - if (mergeSecurityStandards(ruleDef, ruleDefinitionDto)) { - context.updated(ruleDefinitionDto); - } + if (mergeSecurityStandards(ruleDef, ruleDefinitionDto)) { + context.updated(ruleDefinitionDto); + } - if (context.isUpdated(ruleDefinitionDto) || context.isRenamed(ruleDefinitionDto)) { - update(session, ruleDefinitionDto); - } else if (!context.isCreated(ruleDefinitionDto)) { - context.unchanged(ruleDefinitionDto); + if (context.isUpdated(ruleDefinitionDto) || context.isRenamed(ruleDefinitionDto)) { + update(session, ruleDefinitionDto); + } else if (!context.isCreated(ruleDefinitionDto)) { + context.unchanged(ruleDefinitionDto); + } } - mergeParams(ruleDef, ruleDefinitionDto, session); - updateDeprecatedKeys(context, ruleDef, ruleDefinitionDto, session); + for (Map.Entry<RulesDefinition.Rule, RuleDefinitionDto> e : dtos.entrySet()) { + mergeParams(context, e.getKey(), e.getValue(), session); + updateDeprecatedKeys(context, e.getKey(), e.getValue(), session); + } } private RuleDefinitionDto createRuleDto(RulesDefinition.Rule ruleDef, DbSession session) { @@ -409,23 +428,23 @@ public class RegisterRules implements Startable { private static boolean mergeRule(RulesDefinition.Rule def, RuleDefinitionDto dto) { boolean changed = false; - if (!StringUtils.equals(dto.getName(), def.name())) { + if (!Objects.equals(dto.getName(), def.name())) { dto.setName(def.name()); changed = true; } if (mergeDescription(def, dto)) { changed = true; } - if (!StringUtils.equals(dto.getPluginKey(), def.pluginKey())) { + if (!Objects.equals(dto.getPluginKey(), def.pluginKey())) { dto.setPluginKey(def.pluginKey()); changed = true; } - if (!StringUtils.equals(dto.getConfigKey(), def.internalKey())) { + if (!Objects.equals(dto.getConfigKey(), def.internalKey())) { dto.setConfigKey(def.internalKey()); changed = true; } String severity = def.severity(); - if (!ObjectUtils.equals(dto.getSeverityString(), severity)) { + if (!Objects.equals(dto.getSeverityString(), severity)) { dto.setSeverity(severity); changed = true; } @@ -438,16 +457,16 @@ public class RegisterRules implements Startable { dto.setStatus(def.status()); changed = true; } - if (!StringUtils.equals(dto.getScope().name(), def.scope().name())) { + if (!Objects.equals(dto.getScope().name(), def.scope().name())) { dto.setScope(toDtoScope(def.scope())); changed = true; } - if (!StringUtils.equals(dto.getLanguage(), def.repository().language())) { + if (!Objects.equals(dto.getLanguage(), def.repository().language())) { dto.setLanguage(def.repository().language()); changed = true; } RuleType type = RuleType.valueOf(def.type().name()); - if (!ObjectUtils.equals(dto.getType(), type.getDbConstant())) { + if (!Objects.equals(dto.getType(), type.getDbConstant())) { dto.setType(type); changed = true; } @@ -460,11 +479,11 @@ public class RegisterRules implements Startable { private static boolean mergeDescription(RulesDefinition.Rule def, RuleDefinitionDto dto) { boolean changed = false; - if (def.htmlDescription() != null && !StringUtils.equals(dto.getDescription(), def.htmlDescription())) { + if (def.htmlDescription() != null && !Objects.equals(dto.getDescription(), def.htmlDescription())) { dto.setDescription(def.htmlDescription()); dto.setDescriptionFormat(Format.HTML); changed = true; - } else if (def.markdownDescription() != null && !StringUtils.equals(dto.getDescription(), def.markdownDescription())) { + } else if (def.markdownDescription() != null && !Objects.equals(dto.getDescription(), def.markdownDescription())) { dto.setDescription(def.markdownDescription()); dto.setDescriptionFormat(Format.MARKDOWN); changed = true; @@ -490,27 +509,27 @@ public class RegisterRules implements Startable { @Nullable String remediationCoefficient, @Nullable String remediationOffset, @Nullable String effortToFixDescription) { boolean changed = false; - if (!StringUtils.equals(dto.getDefRemediationFunction(), remediationFunction)) { + if (!Objects.equals(dto.getDefRemediationFunction(), remediationFunction)) { dto.setDefRemediationFunction(remediationFunction); changed = true; } - if (!StringUtils.equals(dto.getDefRemediationGapMultiplier(), remediationCoefficient)) { + if (!Objects.equals(dto.getDefRemediationGapMultiplier(), remediationCoefficient)) { dto.setDefRemediationGapMultiplier(remediationCoefficient); changed = true; } - if (!StringUtils.equals(dto.getDefRemediationBaseEffort(), remediationOffset)) { + if (!Objects.equals(dto.getDefRemediationBaseEffort(), remediationOffset)) { dto.setDefRemediationBaseEffort(remediationOffset); changed = true; } - if (!StringUtils.equals(dto.getGapDescription(), effortToFixDescription)) { + if (!Objects.equals(dto.getGapDescription(), effortToFixDescription)) { dto.setGapDescription(effortToFixDescription); changed = true; } return changed; } - private void mergeParams(RulesDefinition.Rule ruleDef, RuleDefinitionDto rule, DbSession session) { - List<RuleParamDto> paramDtos = dbClient.ruleDao().selectRuleParamsByRuleKey(session, rule.getKey()); + private void mergeParams(RegisterRulesContext context, RulesDefinition.Rule ruleDef, RuleDefinitionDto rule, DbSession session) { + List<RuleParamDto> paramDtos = context.getRuleParametersFor(rule.getUuid()); Map<String, RuleParamDto> existingParamsByName = new HashMap<>(); Profiler profiler = Profiler.create(Loggers.get(getClass())); @@ -556,23 +575,22 @@ public class RegisterRules implements Startable { private static boolean mergeParam(RuleParamDto paramDto, RulesDefinition.Param paramDef) { boolean changed = false; - if (!StringUtils.equals(paramDto.getType(), paramDef.type().toString())) { + if (!Objects.equals(paramDto.getType(), paramDef.type().toString())) { paramDto.setType(paramDef.type().toString()); changed = true; } - if (!StringUtils.equals(paramDto.getDefaultValue(), paramDef.defaultValue())) { + if (!Objects.equals(paramDto.getDefaultValue(), paramDef.defaultValue())) { paramDto.setDefaultValue(paramDef.defaultValue()); changed = true; } - if (!StringUtils.equals(paramDto.getDescription(), paramDef.description())) { + if (!Objects.equals(paramDto.getDescription(), paramDef.description())) { paramDto.setDescription(paramDef.description()); changed = true; } return changed; } - private void updateDeprecatedKeys(RegisterRulesContext context, RulesDefinition.Rule ruleDef, RuleDefinitionDto rule, - DbSession dbSession) { + private void updateDeprecatedKeys(RegisterRulesContext context, RulesDefinition.Rule ruleDef, RuleDefinitionDto rule, DbSession dbSession) { Set<SingleDeprecatedRuleKey> deprecatedRuleKeysFromDefinition = SingleDeprecatedRuleKey.from(ruleDef); Set<SingleDeprecatedRuleKey> deprecatedRuleKeysFromDB = context.getDBDeprecatedKeysFor(rule); @@ -604,9 +622,9 @@ public class RegisterRules implements Startable { changed = true; } else if (dto.getSystemTags().size() != ruleDef.tags().size() || !dto.getSystemTags().containsAll(ruleDef.tags())) { - dto.setSystemTags(ruleDef.tags()); - changed = true; - } + dto.setSystemTags(ruleDef.tags()); + changed = true; + } return changed; } @@ -618,9 +636,9 @@ public class RegisterRules implements Startable { changed = true; } else if (dto.getSecurityStandards().size() != ruleDef.securityStandards().size() || !dto.getSecurityStandards().containsAll(ruleDef.securityStandards())) { - dto.setSecurityStandards(ruleDef.securityStandards()); - changed = true; - } + dto.setSecurityStandards(ruleDef.securityStandards()); + changed = true; + } return changed; } @@ -669,31 +687,31 @@ public class RegisterRules implements Startable { private static boolean updateCustomRuleFromTemplateRule(RuleDefinitionDto customRule, RuleDefinitionDto templateRule) { boolean changed = false; - if (!StringUtils.equals(customRule.getLanguage(), templateRule.getLanguage())) { + if (!Objects.equals(customRule.getLanguage(), templateRule.getLanguage())) { customRule.setLanguage(templateRule.getLanguage()); changed = true; } - if (!StringUtils.equals(customRule.getConfigKey(), templateRule.getConfigKey())) { + if (!Objects.equals(customRule.getConfigKey(), templateRule.getConfigKey())) { customRule.setConfigKey(templateRule.getConfigKey()); changed = true; } - if (!StringUtils.equals(customRule.getPluginKey(), templateRule.getPluginKey())) { + if (!Objects.equals(customRule.getPluginKey(), templateRule.getPluginKey())) { customRule.setPluginKey(templateRule.getPluginKey()); changed = true; } - if (!StringUtils.equals(customRule.getDefRemediationFunction(), templateRule.getDefRemediationFunction())) { + if (!Objects.equals(customRule.getDefRemediationFunction(), templateRule.getDefRemediationFunction())) { customRule.setDefRemediationFunction(templateRule.getDefRemediationFunction()); changed = true; } - if (!StringUtils.equals(customRule.getDefRemediationGapMultiplier(), templateRule.getDefRemediationGapMultiplier())) { + if (!Objects.equals(customRule.getDefRemediationGapMultiplier(), templateRule.getDefRemediationGapMultiplier())) { customRule.setDefRemediationGapMultiplier(templateRule.getDefRemediationGapMultiplier()); changed = true; } - if (!StringUtils.equals(customRule.getDefRemediationBaseEffort(), templateRule.getDefRemediationBaseEffort())) { + if (!Objects.equals(customRule.getDefRemediationBaseEffort(), templateRule.getDefRemediationBaseEffort())) { customRule.setDefRemediationBaseEffort(templateRule.getDefRemediationBaseEffort()); changed = true; } - if (!StringUtils.equals(customRule.getGapDescription(), templateRule.getGapDescription())) { + if (!Objects.equals(customRule.getGapDescription(), templateRule.getGapDescription())) { customRule.setGapDescription(templateRule.getGapDescription()); changed = true; } @@ -701,11 +719,11 @@ public class RegisterRules implements Startable { customRule.setStatus(templateRule.getStatus()); changed = true; } - if (!StringUtils.equals(customRule.getSeverityString(), templateRule.getSeverityString())) { + if (!Objects.equals(customRule.getSeverityString(), templateRule.getSeverityString())) { customRule.setSeverity(templateRule.getSeverityString()); changed = true; } - if (!StringUtils.equals(customRule.getRepositoryKey(), templateRule.getRepositoryKey())) { + if (!Objects.equals(customRule.getRepositoryKey(), templateRule.getRepositoryKey())) { customRule.setRepositoryKey(templateRule.getRepositoryKey()); changed = true; } @@ -771,7 +789,7 @@ public class RegisterRules implements Startable { lazyToString(() -> intersection.stream().map(RuleKey::toString).collect(Collectors.joining(",")))); // Find incorrect usage of deprecated keys - ImmutableMap<RuleKey, SingleDeprecatedRuleKey> dbDeprecatedRuleKeysByOldRuleKey = registerRulesContext.getDbDeprecatedKeysByOldRuleKey(); + Map<RuleKey, SingleDeprecatedRuleKey> dbDeprecatedRuleKeysByOldRuleKey = registerRulesContext.getDbDeprecatedKeysByOldRuleKey(); Set<String> incorrectRuleKeyMessage = definedRules.stream() .flatMap(r -> filterInvalidDeprecatedRuleKeys(dbDeprecatedRuleKeysByOldRuleKey, r)) diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/WebServerRuleFinder.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/WebServerRuleFinder.java deleted file mode 100644 index 3b4b759cbda..00000000000 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/WebServerRuleFinder.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.rule; - -/** - * {@link ServerRuleFinder} implementation that supports caching used by the Web Server. - * <p> - * Caching is enabled right after loading of rules is done (see {@link RegisterRules}) and disabled - * once all startup tasks are done (see {@link org.sonar.server.platform.platformlevel.PlatformLevelStartup}). - * </p> - */ -public interface WebServerRuleFinder extends ServerRuleFinder { - /** - * Enable caching. - */ - void startCaching(); - - /** - * Disable caching. - */ - void stopCaching(); -} diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/WebServerRuleFinderImpl.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/WebServerRuleFinderImpl.java deleted file mode 100644 index deeba3402bb..00000000000 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/WebServerRuleFinderImpl.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.rule; - -import com.google.common.annotations.VisibleForTesting; -import java.util.Collection; -import java.util.Optional; -import javax.annotation.CheckForNull; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleQuery; -import org.sonar.db.DbClient; -import org.sonar.db.rule.RuleDefinitionDto; - -public class WebServerRuleFinderImpl implements WebServerRuleFinder { - private final DbClient dbClient; - private final ServerRuleFinder defaultFinder; - @VisibleForTesting - ServerRuleFinder delegate; - - public WebServerRuleFinderImpl(DbClient dbClient) { - this.dbClient = dbClient; - this.defaultFinder = new DefaultRuleFinder(dbClient); - this.delegate = this.defaultFinder; - } - - @Override - public void startCaching() { - this.delegate = new CachingRuleFinder(dbClient); - } - - @Override - public void stopCaching() { - this.delegate = this.defaultFinder; - } - - @Override - @CheckForNull - public Rule findByKey(String repositoryKey, String key) { - return delegate.findByKey(repositoryKey, key); - } - - @Override - @CheckForNull - public Rule findByKey(RuleKey key) { - return delegate.findByKey(key); - } - - @Override - @CheckForNull - public Rule find(RuleQuery query) { - return delegate.find(query); - } - - @Override - public Collection<Rule> findAll(RuleQuery query) { - return delegate.findAll(query); - } - - @Override - public Optional<RuleDefinitionDto> findDtoByKey(RuleKey key) { - return delegate.findDtoByKey(key); - } -} diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java index 6757058ef21..1760041827b 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/RegisterMetrics.java @@ -19,9 +19,6 @@ */ package org.sonar.server.startup; -import static com.google.common.collect.FluentIterable.concat; -import static com.google.common.collect.Lists.newArrayList; - import com.google.common.annotations.VisibleForTesting; import java.util.HashMap; import java.util.List; @@ -39,6 +36,9 @@ import org.sonar.db.DbSession; import org.sonar.db.metric.MetricDto; import org.sonar.server.metric.MetricToDto; +import static com.google.common.collect.FluentIterable.concat; +import static com.google.common.collect.Lists.newArrayList; + public class RegisterMetrics implements Startable { private static final Logger LOG = Loggers.get(RegisterMetrics.class); @@ -72,7 +72,7 @@ public class RegisterMetrics implements Startable { void register(Iterable<Metric> metrics) { Profiler profiler = Profiler.create(LOG).startInfo("Register metrics"); - try (DbSession session = dbClient.openSession(false)) { + try (DbSession session = dbClient.openSession(true)) { save(session, metrics); sanitizeQualityGates(session); session.commit(); diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/CachingRuleFinderTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/CachingRuleFinderTest.java index 7d2219b826b..afb59647971 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/CachingRuleFinderTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/CachingRuleFinderTest.java @@ -95,6 +95,7 @@ public class CachingRuleFinderTest { verify(dbClient).openSession(anyBoolean()); verify(ruleDao).selectAllDefinitions(dbSession); + verify(ruleDao).selectAllRuleParams(dbSession); verifyNoMoreInteractions(ruleDao); } @@ -110,7 +111,7 @@ public class CachingRuleFinderTest { new CachingRuleFinder(dbClient); - verify(ruleDao).selectRuleParamsByRuleKeys(dbSession, ImmutableSet.copyOf(ruleKeys)); + verify(ruleDao).selectAllRuleParams(dbSession); } @Test diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/RegisterRulesTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/RegisterRulesTest.java index 07b785376a7..4c7423de81b 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/RegisterRulesTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/RegisterRulesTest.java @@ -102,7 +102,7 @@ public class RegisterRulesTest { private static final RuleKey RULE_KEY3 = RuleKey.of("fake", "rule3"); private static final RuleKey HOTSPOT_RULE_KEY = RuleKey.of("fake", "hotspot"); - private TestSystem2 system = new TestSystem2().setNow(DATE1.getTime()); + private final TestSystem2 system = new TestSystem2().setNow(DATE1.getTime()); @org.junit.Rule public ExpectedException expectedException = ExpectedException.none(); @@ -113,14 +113,16 @@ public class RegisterRulesTest { @org.junit.Rule public LogTester logTester = new LogTester(); - private QProfileRules qProfileRules = mock(QProfileRules.class); - private WebServerRuleFinder webServerRuleFinder = mock(WebServerRuleFinder.class); - private DbClient dbClient = db.getDbClient(); + private final QProfileRules qProfileRules = mock(QProfileRules.class); + private final WebServerRuleFinder webServerRuleFinder = mock(WebServerRuleFinder.class); + private final DbClient dbClient = db.getDbClient(); + private final MetadataIndex metadataIndex = mock(MetadataIndex.class); + private final UuidFactory uuidFactory = UuidFactoryFast.getInstance(); + private RuleIndexer ruleIndexer; private ActiveRuleIndexer activeRuleIndexer; private RuleIndex ruleIndex; - private MetadataIndex metadataIndex = mock(MetadataIndex.class); - private UuidFactory uuidFactory = UuidFactoryFast.getInstance(); + @Before public void before() { @@ -996,7 +998,7 @@ public class RegisterRulesTest { } @SafeVarargs - private final void createRule(RulesDefinition.Context context, String language, String repositoryKey, String ruleKey, Consumer<NewRule>... consumers) { + private void createRule(RulesDefinition.Context context, String language, String repositoryKey, String ruleKey, Consumer<NewRule>... consumers) { NewRepository repo = context.createRepository(repositoryKey, language); NewRule newRule = repo.createRule(ruleKey) .setName(ruleKey) diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java index 69682a5d27e..aebccfc0a3f 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java @@ -45,8 +45,9 @@ public class RegisterMetricsTest { @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); - private UuidFactory uuidFactory = new SequenceUuidFactory(); - private DbClient dbClient = dbTester.getDbClient(); + private final UuidFactory uuidFactory = new SequenceUuidFactory(); + private final DbClient dbClient = dbTester.getDbClient(); + private final RegisterMetrics register = new RegisterMetrics(dbClient, uuidFactory); /** * Insert new metrics, including custom metrics @@ -65,7 +66,6 @@ public class RegisterMetricsTest { .setUserManaged(true) .create(); - RegisterMetrics register = new RegisterMetrics(dbClient, uuidFactory); register.register(asList(m1, custom)); Map<String, MetricDto> metricsByKey = selectAllMetrics(); @@ -91,7 +91,6 @@ public class RegisterMetricsTest { .setDirection(1) .setHidden(false)); - RegisterMetrics register = new RegisterMetrics(dbClient, uuidFactory); Metric m1 = new Metric.Builder("m1", "New name", Metric.ValueType.FLOAT) .setDescription("new description") .setDirection(-1) @@ -115,7 +114,6 @@ public class RegisterMetricsTest { IntStream.range(0, count) .forEach(t -> dbTester.measures().insertMetric(m -> m.setEnabled(random.nextBoolean()))); - RegisterMetrics register = new RegisterMetrics(dbClient, uuidFactory); register.register(Collections.emptyList()); assertThat(selectAllMetrics().values().stream()) @@ -128,7 +126,6 @@ public class RegisterMetricsTest { MetricDto enabledMetric = dbTester.measures().insertMetric(t -> t.setEnabled(true)); MetricDto disabledMetric = dbTester.measures().insertMetric(t -> t.setEnabled(false)); - RegisterMetrics register = new RegisterMetrics(dbClient, uuidFactory); register.register(asList(builderOf(enabledMetric).create(), builderOf(disabledMetric).create())); assertThat(selectAllMetrics().values()) @@ -138,7 +135,6 @@ public class RegisterMetricsTest { @Test public void insert_core_metrics() { - RegisterMetrics register = new RegisterMetrics(dbClient, uuidFactory); register.start(); assertThat(dbTester.countRowsOfTable("metrics")).isEqualTo(CoreMetrics.getMetrics().size()); |