import org.elasticsearch.action.admin.cluster.state.ClusterStateRequestBuilder;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequestBuilder;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
+import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequestBuilder;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
import org.elasticsearch.action.admin.indices.flush.FlushRequestBuilder;
import org.elasticsearch.search.aggregations.metrics.max.Max;
import org.picocontainer.Startable;
import org.sonar.core.profiling.Profiling;
-import org.sonar.server.es.request.ProxyBulkRequestBuilder;
-import org.sonar.server.es.request.ProxyClusterHealthRequestBuilder;
-import org.sonar.server.es.request.ProxyClusterStateRequestBuilder;
-import org.sonar.server.es.request.ProxyClusterStatsRequestBuilder;
-import org.sonar.server.es.request.ProxyCountRequestBuilder;
-import org.sonar.server.es.request.ProxyCreateIndexRequestBuilder;
-import org.sonar.server.es.request.ProxyDeleteByQueryRequestBuilder;
-import org.sonar.server.es.request.ProxyDeleteRequestBuilder;
-import org.sonar.server.es.request.ProxyFlushRequestBuilder;
-import org.sonar.server.es.request.ProxyGetRequestBuilder;
-import org.sonar.server.es.request.ProxyIndexRequestBuilder;
-import org.sonar.server.es.request.ProxyIndicesExistsRequestBuilder;
-import org.sonar.server.es.request.ProxyIndicesStatsRequestBuilder;
-import org.sonar.server.es.request.ProxyMultiGetRequestBuilder;
-import org.sonar.server.es.request.ProxyNodesStatsRequestBuilder;
-import org.sonar.server.es.request.ProxyPutMappingRequestBuilder;
-import org.sonar.server.es.request.ProxyRefreshRequestBuilder;
-import org.sonar.server.es.request.ProxySearchRequestBuilder;
-import org.sonar.server.es.request.ProxySearchScrollRequestBuilder;
+import org.sonar.server.es.request.*;
import org.sonar.server.search.ClusterHealth;
import org.sonar.server.search.SearchClient;
return new ProxyDeleteRequestBuilder(profiling, client, index).setType(type).setId(id);
}
-
public DeleteByQueryRequestBuilder prepareDeleteByQuery(String... indices) {
return new ProxyDeleteByQueryRequestBuilder(client, profiling).setIndices(indices);
}
.setWaitForMerge(true);
}
+ public ClearIndicesCacheRequestBuilder prepareClearCache(String... indices) {
+ return new ProxyClearCacheRequestBuilder(client, profiling).setIndices(indices);
+ }
public long getLastUpdatedAt(String indexName, String typeName) {
SearchRequestBuilder request = prepareSearch(indexName)
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.es.request;
+
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.action.ListenableActionFuture;
+import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequestBuilder;
+import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.unit.TimeValue;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.StopWatch;
+
+public class ProxyClearCacheRequestBuilder extends ClearIndicesCacheRequestBuilder {
+
+ private final Profiling profiling;
+
+ public ProxyClearCacheRequestBuilder(Client client, Profiling profiling) {
+ super(client.admin().indices());
+ this.profiling = profiling;
+ }
+
+ @Override
+ public ClearIndicesCacheResponse get() {
+ StopWatch fullProfile = profiling.start("clear cache", Profiling.Level.FULL);
+ try {
+ return super.execute().actionGet();
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format("Fail to execute %s", toString()), e);
+ } finally {
+ if (profiling.isProfilingEnabled(Profiling.Level.FULL)) {
+ fullProfile.stop("%s", toString());
+ }
+ }
+ }
+
+ @Override
+ public ClearIndicesCacheResponse get(TimeValue timeout) {
+ throw new IllegalStateException("Not yet implemented");
+ }
+
+ @Override
+ public ClearIndicesCacheResponse get(String timeout) {
+ throw new IllegalStateException("Not yet implemented");
+ }
+
+ @Override
+ public ListenableActionFuture<ClearIndicesCacheResponse> execute() {
+ throw new UnsupportedOperationException("execute() should not be called as it's used for asynchronous");
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder message = new StringBuilder();
+ message.append("ES clear cache request");
+ if (request.indices().length > 0) {
+ message.append(String.format(" on indices '%s'", StringUtils.join(request.indices(), ",")));
+ }
+ String[] fields = request.fields();
+ if (fields != null && fields.length > 0) {
+ message.append(String.format(" on fields '%s'", StringUtils.join(fields, ",")));
+ }
+ String[] filterKeys = request.filterKeys();
+ if (filterKeys != null && filterKeys.length > 0) {
+ message.append(String.format(" on filterKeys '%s'", StringUtils.join(filterKeys, ",")));
+ }
+ if (request.filterCache()) {
+ message.append(" with filter cache");
+ }
+ if (request.fieldDataCache()) {
+ message.append(" with field data cache");
+ }
+ if (request.idCache()) {
+ message.append(" with id cache");
+ }
+ return message.toString();
+ }
+}
*/
package org.sonar.server.issue.index;
+import com.google.common.collect.Maps;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.IssueComment;
import org.sonar.api.rule.RuleKey;
super(fields);
}
+ public IssueDoc() {
+ super(Maps.<String, Object>newHashMap());
+ }
+
@Override
public String key() {
return getField(IssueIndexDefinition.FIELD_ISSUE_KEY);
.lookupType(ViewIndexDefinition.TYPE_VIEW)
.lookupId(viewUuid)
.lookupPath(ViewIndexDefinition.FIELD_PROJECTS))
- .cacheKey(cacheKey(viewUuid));
+ .cacheKey(viewsLookupCacheKey(viewUuid));
}
return viewsFilter;
}
- public static String cacheKey(String viewUuid) {
+ public static String viewsLookupCacheKey(String viewUuid) {
return IssueIndexDefinition.TYPE_ISSUE + viewUuid + ViewIndexDefinition.TYPE_VIEW;
}
package org.sonar.server.platform;
import org.apache.commons.dbutils.DbUtils;
-import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
import org.sonar.core.persistence.DatabaseVersion;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.es.EsClient;
import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.SearchClient;
import org.sonar.server.source.index.SourceLineIndexDefinition;
+import org.sonar.server.view.index.ViewIndexDefinition;
import java.sql.Connection;
import java.sql.SQLException;
private static final String[] RESOURCE_RELATED_TABLES = {
"group_roles", "user_roles", "properties"
};
- private final SearchClient searchClient;
+ private final EsClient esClient;
private final MyBatis myBatis;
- public BackendCleanup(SearchClient searchClient, MyBatis myBatis) {
- this.searchClient = searchClient;
+ public BackendCleanup(EsClient esClient, MyBatis myBatis) {
+ this.esClient = esClient;
this.myBatis = myBatis;
}
public void clearIndexes() {
LoggerFactory.getLogger(getClass()).info("Truncate Elasticsearch indices");
try {
- searchClient.admin().indices()
- .clearCache(new ClearIndicesCacheRequest())
+ esClient.prepareClearCache()
.get();
- searchClient.prepareDeleteByQuery(searchClient.prepareState().get()
+ esClient.prepareDeleteByQuery(esClient.prepareState().get()
.getState().getMetaData().concreteAllIndices())
.setQuery(QueryBuilders.matchAllQuery())
.get();
- searchClient.prepareRefresh(searchClient.prepareState().get()
+ esClient.prepareRefresh(esClient.prepareState().get()
.getState().getMetaData().concreteAllIndices())
.setForce(true)
.get();
- searchClient.prepareFlush(searchClient.prepareState().get()
+ esClient.prepareFlush(esClient.prepareState().get()
.getState().getMetaData().concreteAllIndices())
.get();
} catch (Exception e) {
// Clear inspection indexes
clearIndex(IssueIndexDefinition.INDEX);
clearIndex(SourceLineIndexDefinition.INDEX);
+ clearIndex(ViewIndexDefinition.INDEX);
} finally {
dbSession.close();
* Completely remove a index with all types
*/
public void clearIndex(String indexName) {
- searchClient.prepareDeleteByQuery(searchClient.prepareState().get()
+ esClient.prepareDeleteByQuery(esClient.prepareState().get()
.getState().getMetaData().concreteIndices(new String[] {indexName}))
.setQuery(QueryBuilders.matchAllQuery())
.get();
* Remove only the type of an index
*/
public void clearIndexType(IndexDefinition indexDefinition) {
- searchClient.prepareDeleteByQuery(searchClient.prepareState().get()
+ esClient.prepareDeleteByQuery(esClient.prepareState().get()
.getState().getMetaData().concreteIndices(new String[] {indexDefinition.getIndexName()})).setTypes(indexDefinition.getIndexType())
.setQuery(QueryBuilders.matchAllQuery())
.get();
public static final String MANUAL_REPOSITORY = "manual";
- RuleDoc(Map<String, Object> fields) {
+ public RuleDoc(Map<String, Object> fields) {
super(fields);
}
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
+
}
package org.sonar.server.source.index;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
import org.sonar.server.search.BaseDoc;
import org.sonar.server.search.BaseNormalizer;
import org.sonar.server.search.IndexUtils;
import java.util.Collection;
import java.util.Date;
-import java.util.HashMap;
import java.util.Map;
public class SourceLineDoc extends BaseDoc {
// For testing purpose
public SourceLineDoc() {
- this(new HashMap<String, Object>());
+ this(Maps.<String, Object>newHashMap());
}
public String projectUuid() {
*/
package org.sonar.server.user.index;
+import com.google.common.collect.Maps;
import org.sonar.api.user.User;
import org.sonar.server.search.BaseDoc;
super(fields);
}
+ public UserDoc() {
+ this(Maps.<String, Object>newHashMap());
+ }
+
@Override
public String login() {
return getField(UserIndexDefinition.FIELD_LOGIN);
return getField(UserIndexDefinition.FIELD_UPDATED_AT);
}
- public void setLogin(@Nullable String s) {
+ public UserDoc setLogin(@Nullable String s) {
setField(UserIndexDefinition.FIELD_LOGIN, s);
+ return this;
}
- public void setName(@Nullable String s) {
+ public UserDoc setName(@Nullable String s) {
setField(UserIndexDefinition.FIELD_NAME, s);
+ return this;
}
- public void setEmail(@Nullable String s) {
+ public UserDoc setEmail(@Nullable String s) {
setField(UserIndexDefinition.FIELD_EMAIL, s);
+ return this;
}
- public void setActive(boolean b) {
+ public UserDoc setActive(boolean b) {
setField(UserIndexDefinition.FIELD_ACTIVE, b);
+ return this;
}
- public void setScmAccounts(@Nullable List<String> s) {
+ public UserDoc setScmAccounts(@Nullable List<String> s) {
setField(UserIndexDefinition.FIELD_SCM_ACCOUNTS, s);
+ return this;
}
- public void setCreatedAt(long l) {
+ public UserDoc setCreatedAt(long l) {
setField(UserIndexDefinition.FIELD_CREATED_AT, l);
+ return this;
}
- public void setUpdatedAt(long l) {
+ public UserDoc setUpdatedAt(long l) {
setField(UserIndexDefinition.FIELD_UPDATED_AT, l);
+ return this;
}
}
import org.sonar.server.es.BaseIndexer;
import org.sonar.server.es.BulkIndexer;
import org.sonar.server.es.EsClient;
+import org.sonar.server.issue.index.IssueIndex;
import java.util.List;
import java.util.Map;
/**
* Index all views if the index is empty.
- * Only used on startup .
+ * Only used on startup.
+ *
+ * The views lookup cache will not be cleared
*/
@Override
protected long doIndex(long lastUpdatedAt) {
- // Index only if index is empty
long count = esClient.prepareCount(ViewIndexDefinition.INDEX).setTypes(ViewIndexDefinition.TYPE_VIEW).get().getCount();
if (count == 0) {
DbSession dbSession = dbClient.openSession(false);
for (UuidWithProjectUuidDto uuidWithProjectUuidDto : dbClient.componentDao().selectAllViewsAndSubViews(dbSession)) {
viewAndProjectViewUuidMap.put(uuidWithProjectUuidDto.getUuid(), uuidWithProjectUuidDto.getProjectUuid());
}
- index(dbSession, viewAndProjectViewUuidMap);
+ index(dbSession, viewAndProjectViewUuidMap, false);
} finally {
dbSession.close();
}
/**
* Index a root view : it will load projects on each sub views and index it.
* Used by the compute engine to reindex a root view.
+ *
+ * The views lookup cache will be cleared
*/
public void index(String rootViewUuid) {
DbSession dbSession = dbClient.openSession(false);
for (ComponentDto viewOrSubView : dbClient.componentDao().selectModulesTree(dbSession, rootViewUuid)) {
viewAndProjectViewUuidMap.put(viewOrSubView.uuid(), viewOrSubView.projectUuid());
}
- index(dbSession, viewAndProjectViewUuidMap);
+ index(dbSession, viewAndProjectViewUuidMap, true);
} finally {
dbSession.close();
}
}
/**
- * Index a single document
+ * Index a single document.
+ *
+ * The views lookup cache will be cleared
*/
public void index(ViewDoc viewDoc) {
final BulkIndexer bulk = new BulkIndexer(esClient, ViewIndexDefinition.INDEX);
bulk.start();
- bulk.add(newUpsertRequest(viewDoc));
+ doIndex(bulk, viewDoc, true);
bulk.stop();
}
- private void index(DbSession dbSession, Map<String, String> viewAndProjectViewUuidMap) {
+ private void index(DbSession dbSession, Map<String, String> viewAndProjectViewUuidMap, boolean needClearCache) {
final BulkIndexer bulk = new BulkIndexer(esClient, ViewIndexDefinition.INDEX);
bulk.start();
for (Map.Entry<String, String> entry : viewAndProjectViewUuidMap.entrySet()) {
- doIndex(dbSession, bulk, entry.getKey(), entry.getValue());
+ String viewUuid = entry.getKey();
+ List<String> projects = dbClient.componentDao().selectProjectsFromView(dbSession, viewUuid, entry.getValue());
+ doIndex(bulk, new ViewDoc()
+ .setUuid(viewUuid)
+ .setProjects(projects), needClearCache);
}
bulk.stop();
}
- private void doIndex(DbSession dbSession, BulkIndexer bulk, String uuid, String projectUuid) {
- List<String> projects = dbClient.componentDao().selectProjectsFromView(dbSession, uuid, projectUuid);
- bulk.add(newUpsertRequest(new ViewDoc()
- .setUuid(uuid)
- .setProjects(projects)));
+ private void doIndex(BulkIndexer bulk, ViewDoc viewDoc, boolean needClearCache) {
+ bulk.add(newUpsertRequest(viewDoc));
+ if (needClearCache) {
+ clearLookupCache(viewDoc.uuid());
+ }
}
private UpdateRequest newUpsertRequest(ViewDoc doc) {
.upsert(doc.getFields());
}
+ private void clearLookupCache(String viewUuid) {
+ try {
+ esClient.prepareClearCache()
+ .setFilterCache(true)
+ .setFilterKeys(IssueIndex.viewsLookupCacheKey(viewUuid))
+ .get();
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format("Unable to clear lookup cache of view '%s'", viewUuid), e);
+ }
+ }
+
}
.setQualifier(Qualifiers.VIEW);
}
- public static ComponentDto newTechnicalProject(ComponentDto project, ComponentDto view) {
- return newTechnicalProject(Uuids.create(), project, view);
- }
-
- public static ComponentDto newTechnicalProject(String uuid, ComponentDto project, ComponentDto view) {
+ public static ComponentDto newProjectCopy(String uuid, ComponentDto project, ComponentDto view) {
Preconditions.checkNotNull(project.getId(), "The project need to be persisted before creating this technical project.");
return newChildComponent(uuid, view)
.setUuid(uuid)
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.computation.step;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.IssueQuery;
-import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.db.IssueDao;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.permission.InternalPermissionService;
-import org.sonar.server.permission.PermissionChange;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.user.MockUserSession;
-import org.sonar.server.view.index.ViewIndexer;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * It's still not possible to only used EsTester as IssueIndex does not support it yet.
- */
-public class IndexViewsStepMediumTest {
-
- ComputationContext context;
-
- DbSession dbSession;
-
- ViewIndexer indexer;
-
- IndexViewsStep step;
-
- @ClassRule
- public static ServerTester tester = new ServerTester().addComponents(IndexViewsStep.class);
-
- IssueIndex index;
-
- @Before
- public void setUp() throws Exception {
- tester.clearIndexes();
- context = mock(ComputationContext.class);
- dbSession = tester.get(DbClient.class).openSession(false);
- index = tester.get(IssueIndex.class);
- step = tester.get(IndexViewsStep.class);
- }
-
- @After
- public void after() {
- dbSession.close();
- }
-
- @Test
- public void clear_cache_of_issue_on_view_filter() throws Exception {
- String viewUuid = "ABCD";
- when(context.getProject()).thenReturn(ComponentTesting.newProjectDto(viewUuid).setQualifier(Qualifiers.VIEW));
-
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(dbSession, rule);
- ComponentDto project1 = addProjectWithIssue(rule);
-
- ComponentDto view = ComponentTesting.newView("ABCD");
- ComponentDto techProject1 = ComponentTesting.newTechnicalProject("CDEF", project1, view);
- tester.get(ComponentDao.class).insert(dbSession, view, techProject1);
- dbSession.commit();
- tester.get(ViewIndexer.class).index(viewUuid);
-
- // Execute issue query on view -> 1 issue on view (and filter on view will be set in cache)
- assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(1);
-
- // Add a project to the view
- ComponentDto project2 = addProjectWithIssue(rule);
- ComponentDto techProject2 = ComponentTesting.newTechnicalProject("EFGH", project2, view);
- tester.get(ComponentDao.class).insert(dbSession, techProject2);
- dbSession.commit();
-
- // Execute issue query on view -> Still 1 issue on view, issue on project2 is not yet visible
- assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(1);
-
- step.execute(context);
-
- // Execute issue query on view -> issue of project2 are well taken into account
- assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(2);
- }
-
- private ComponentDto addProjectWithIssue(RuleDto rule) {
- ComponentDto project = ComponentTesting.newProjectDto();
- ComponentDto file = ComponentTesting.newFileDto(project);
- tester.get(ComponentDao.class).insert(dbSession, project, file);
-
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- tester.get(IssueDao.class).insert(dbSession, issue);
- dbSession.commit();
-
- setDefaultProjectPermission(project);
- tester.get(IssueIndexer.class).indexAll();
-
- return project;
- }
-
- private void setDefaultProjectPermission(ComponentDto project) {
- // project can be seen by anyone and by code viewer
- MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
- tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
- MockUserSession.set();
- }
-}
when(context.getProject()).thenReturn(ComponentTesting.newProjectDto("DBCA").setQualifier(Qualifiers.VIEW));
esTester.putDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW,
- new ViewDoc().setUuid("ABCD").getFields(),
- new ViewDoc().setUuid("BCDE").getFields(),
+ new ViewDoc().setUuid("ABCD"),
+ new ViewDoc().setUuid("BCDE"),
// Should be removed as it no more exists in db
- new ViewDoc().setUuid("CDEF").getFields());
+ new ViewDoc().setUuid("CDEF"));
ComponentDto view = ComponentTesting.newProjectDto("ABCD").setQualifier(Qualifiers.VIEW);
ComponentDto subView = ComponentTesting.newModuleDto("BCDE", view).setQualifier(Qualifiers.SUBVIEW);
List<String> viewUuids = esTester.getDocumentFields(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW, ViewIndexDefinition.FIELD_UUID);
assertThat(viewUuids).containsOnly("ABCD", "BCDE");
}
+
+ @Test
+ public void nothing_to_do_when_not_analysing_view() throws Exception {
+ when(context.getProject()).thenReturn(ComponentTesting.newProjectDto("DBCA"));
+
+ esTester.putDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW,
+ new ViewDoc().setUuid("ABCD"),
+ // This vies does not exists in db...
+ new ViewDoc().setUuid("BCDE"));
+
+ dbClient.componentDao().insert(session, ComponentTesting.newProjectDto("ABCD").setQualifier(Qualifiers.VIEW));
+ session.commit();
+
+ step.execute(context);
+
+ // ... But it should not be removed as the project of the context is not a view
+ assertThat(esTester.countDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW)).isEqualTo(2);
+ }
+
}
import java.io.FileInputStream;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
bulk.get();
}
- public void putDocuments(String index, String type, Map<String, Object>... docs) throws Exception {
+ public void putDocuments(String index, String type, BaseDoc... docs) throws Exception {
BulkRequestBuilder bulk = client.prepareBulk().setRefresh(true);
- for (Map<String, Object> doc : docs) {
- bulk.add(new IndexRequest(index, type).source(doc));
+ for (BaseDoc doc : docs) {
+ bulk.add(new IndexRequest(index, type).source(doc.getFields()));
}
bulk.get();
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.es.request;
+
+import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequestBuilder;
+import org.elasticsearch.common.unit.TimeValue;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.search.SearchClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+public class ProxyClearCacheRequestBuilderTest {
+
+ @Rule
+ public EsTester esTester = new EsTester();
+
+ @Test
+ public void clear_cache() {
+ ClearIndicesCacheRequestBuilder requestBuilder = esTester.client().prepareClearCache();
+ requestBuilder.get();
+ }
+
+ @Test
+ public void to_string() {
+ assertThat(esTester.client().prepareClearCache().toString()).isEqualTo("ES clear cache request");
+ assertThat(esTester.client().prepareClearCache("rules").toString()).isEqualTo("ES clear cache request on indices 'rules'");
+ assertThat(esTester.client().prepareClearCache().setFields("key").toString()).isEqualTo("ES clear cache request on fields 'key'");
+ assertThat(esTester.client().prepareClearCache().setFilterKeys("rule1").toString()).isEqualTo("ES clear cache request on filterKeys 'rule1'");
+ assertThat(esTester.client().prepareClearCache().setFilterCache(true).toString()).isEqualTo("ES clear cache request with filter cache");
+ assertThat(esTester.client().prepareClearCache().setFieldDataCache(true).toString()).isEqualTo("ES clear cache request with field data cache");
+ assertThat(esTester.client().prepareClearCache().setIdCache(true).toString()).isEqualTo("ES clear cache request with id cache");
+ }
+
+ @Test
+ public void with_profiling_basic() {
+ Profiling profiling = new Profiling(new Settings().setProperty(Profiling.CONFIG_PROFILING_LEVEL, Profiling.Level.BASIC.name()));
+ SearchClient searchClient = new SearchClient(new Settings(), profiling);
+
+ ClearIndicesCacheRequestBuilder requestBuilder = esTester.client().prepareClearCache();
+ requestBuilder.get();
+
+ // TODO assert profiling
+ searchClient.stop();
+ }
+
+ @Test
+ public void get_with_string_timeout_is_not_yet_implemented() throws Exception {
+ try {
+ esTester.client().prepareClearCache().get("1");
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+ }
+ }
+
+ @Test
+ public void get_with_time_value_timeout_is_not_yet_implemented() throws Exception {
+ try {
+ esTester.client().prepareClearCache().get(TimeValue.timeValueMinutes(1));
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not yet implemented");
+ }
+ }
+
+ @Test
+ public void execute_should_throw_an_unsupported_operation_exception() throws Exception {
+ try {
+ esTester.client().prepareClearCache().execute();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(UnsupportedOperationException.class).hasMessage("execute() should not be called as it's used for asynchronous");
+ }
+ }
+
+}
package org.sonar.server.platform;
-import org.junit.After;
+import com.google.common.collect.ImmutableMap;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.component.SnapshotDto;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.SnapshotTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
+import org.junit.experimental.categories.Category;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.es.EsTester;
import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.db.IssueDao;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.permission.InternalPermissionService;
-import org.sonar.server.permission.PermissionChange;
+import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.rule.index.RuleIndex;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.user.MockUserSession;
-
+import org.sonar.server.rule.index.RuleDoc;
+import org.sonar.server.rule.index.RuleNormalizer;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.source.index.SourceLineDoc;
+import org.sonar.server.source.index.SourceLineIndexDefinition;
+import org.sonar.server.view.index.ViewDoc;
+import org.sonar.server.view.index.ViewIndexDefinition;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
+@Category(DbTests.class)
public class BackendCleanupMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static EsTester esTester = new EsTester();
- DbClient db;
- DbSession session;
- RuleDto rule;
- ComponentDto project;
- ComponentDto file;
- IssueDto issue;
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
BackendCleanup backendCleanup;
@Before
public void setUp() throws Exception {
- tester.clearDbAndIndexes();
- db = tester.get(DbClient.class);
- session = db.openSession(false);
- backendCleanup = tester.get(BackendCleanup.class);
-
- rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(session, rule);
-
- project = ComponentTesting.newProjectDto().setKey("MyProject");
- tester.get(ComponentDao.class).insert(session, project);
- SnapshotDto projectSnapshot = SnapshotTesting.createForProject(project);
- db.snapshotDao().insert(session, projectSnapshot);
-
- file = ComponentTesting.newFileDto(project).setKey("MyComponent");
- tester.get(ComponentDao.class).insert(session, file);
- db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, projectSnapshot));
- session.commit();
- // project can be seen by anyone
- MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
- tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
-
- issue = IssueTesting.newDto(rule, file, project);
- tester.get(IssueDao.class).insert(session, issue);
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
- }
-
- @After
- public void after() {
- session.close();
+ backendCleanup = new BackendCleanup(esTester.client(), dbTester.myBatis());
}
@Test
public void clear_db() throws Exception {
- backendCleanup.clearDb();
- session.commit();
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
- // Everything should be removed from db
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNull();
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(IssueDao.class).selectNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNull();
+ backendCleanup.clearDb();
- // Nothing should be removed from indexes
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNotNull();
- assertThat(tester.get(RuleIndex.class).getNullableByKey(rule.getKey())).isNotNull();
+ assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("snapshots")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("rules")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("properties")).isEqualTo(0);
}
@Test
public void clear_indexes() throws Exception {
- backendCleanup.clearIndexes();
- session.commit();
+ esTester.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueTesting.newDoc());
+ esTester.putDocuments(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType(), newRuleDoc());
- // Nothing should be removed from db
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNotNull();
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNotNull();
- assertThat(tester.get(IssueDao.class).selectNullableByKey(session, issue.getKey())).isNotNull();
- assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNotNull();
+ backendCleanup.clearIndexes();
- // Everything should be removed from indexes
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNull();
- assertThat(tester.get(RuleIndex.class).getNullableByKey(rule.getKey())).isNull();
+ assertThat(esTester.countDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE)).isEqualTo(0);
}
@Test
public void clear_all() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+ esTester.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueTesting.newDoc());
+ esTester.putDocuments(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType(), newRuleDoc());
+
backendCleanup.clearAll();
- session.commit();
- // Everything should be removed from db
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNull();
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(IssueDao.class).selectNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNull();
+ assertThat(esTester.countDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE)).isEqualTo(0);
+ assertThat(esTester.countDocuments(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType())).isEqualTo(0);
- // Everything should be removed from indexes
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNull();
- assertThat(tester.get(RuleIndex.class).getNullableByKey(rule.getKey())).isNull();
+ assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("snapshots")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("rules")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("properties")).isEqualTo(0);
}
@Test
public void reset_data() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+ esTester.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueTesting.newDoc());
+ esTester.putDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, new SourceLineDoc().setProjectUuid("ABCD").setFileUuid("BCDE"));
+ esTester.putDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW, new ViewDoc().setUuid("CDEF").setProjects(newArrayList("DEFG")));
+ esTester.putDocuments(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType(), newRuleDoc());
+
backendCleanup.resetData();
- session.commit();
- // Every projects and issues are removed (from db and indexes)
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNull();
- assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(IssueDao.class).selectNullableByKey(session, issue.getKey())).isNull();
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNull();
+ assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("snapshots")).isEqualTo(0);
+ assertThat(dbTester.countRowsOfTable("properties")).isEqualTo(0);
+ assertThat(esTester.countDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE)).isEqualTo(0);
+ assertThat(esTester.countDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE)).isEqualTo(0);
+ assertThat(esTester.countDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW)).isEqualTo(0);
+
+ // Rules should not be removed
+ assertThat(dbTester.countRowsOfTable("rules")).isEqualTo(1);
+ assertThat(esTester.countDocuments(IndexDefinition.RULE.getIndexName(), IndexDefinition.RULE.getIndexType())).isEqualTo(1);
+ }
- // Every rules should not be removed (from db and indexes)
- assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNotNull();
- assertThat(tester.get(RuleIndex.class).getNullableByKey(rule.getKey())).isNotNull();
+ private static RuleDoc newRuleDoc() {
+ return new RuleDoc(ImmutableMap.<String, Object>of(RuleNormalizer.RuleField.RULE_KEY.field(), RuleTesting.XOO_X1));
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.view.index;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.issue.IssueQuery;
+import org.sonar.server.issue.IssueTesting;
+import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.InternalPermissionService;
+import org.sonar.server.permission.PermissionChange;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.QueryContext;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * It's not possible to only used EsTester as IssueIndex does not support it yet.
+ *
+ * This class
+ */
+public class ViewIndexerMediumTest {
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester();
+
+ DbSession dbSession;
+
+ ViewIndexer indexer;
+
+ IssueIndex index;
+
+ @Before
+ public void setUp() throws Exception {
+ tester.clearDbAndIndexes();
+ dbSession = tester.get(DbClient.class).openSession(false);
+ index = tester.get(IssueIndex.class);
+ indexer = tester.get(ViewIndexer.class);
+ }
+
+ @After
+ public void after() {
+ dbSession.close();
+ }
+
+ @Test
+ public void clear_views_lookup_cache_on_index_view_uuid() throws Exception {
+ String viewUuid = "ABCD";
+
+ RuleDto rule = RuleTesting.newXooX1();
+ tester.get(RuleDao.class).insert(dbSession, rule);
+ ComponentDto project1 = addProjectWithIssue(rule);
+
+ ComponentDto view = ComponentTesting.newView("ABCD");
+ ComponentDto techProject1 = ComponentTesting.newProjectCopy("CDEF", project1, view);
+ tester.get(ComponentDao.class).insert(dbSession, view, techProject1);
+ dbSession.commit();
+
+ // First view indexation
+ indexer.index(viewUuid);
+
+ // Execute issue query on view -> 1 issue on view
+ assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(1);
+
+ // Add a project to the view and index it again
+ ComponentDto project2 = addProjectWithIssue(rule);
+ ComponentDto techProject2 = ComponentTesting.newProjectCopy("EFGH", project2, view);
+ tester.get(ComponentDao.class).insert(dbSession, techProject2);
+ dbSession.commit();
+ indexer.index(viewUuid);
+
+ // Execute issue query on view -> issue of project2 are well taken into account : the cache has been cleared
+ assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new QueryContext()).getHits()).hasSize(2);
+ }
+
+ private ComponentDto addProjectWithIssue(RuleDto rule) {
+ ComponentDto project = ComponentTesting.newProjectDto();
+ ComponentDto file = ComponentTesting.newFileDto(project);
+ tester.get(ComponentDao.class).insert(dbSession, project, file);
+
+ IssueDto issue = IssueTesting.newDto(rule, file, project);
+ tester.get(IssueDao.class).insert(dbSession, issue);
+ dbSession.commit();
+
+ setDefaultProjectPermission(project);
+ tester.get(IssueIndexer.class).indexAll();
+
+ return project;
+ }
+
+ private void setDefaultProjectPermission(ComponentDto project) {
+ // project can be seen by anyone and by code viewer
+ MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+ tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
+ MockUserSession.set();
+ }
+
+}
// Some views are not in the db
dbTester.prepareDbUnit(getClass(), "index.xml");
esTester.putDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW,
- new ViewDoc().setUuid("ABCD").setProjects(newArrayList("BCDE")).getFields());
+ new ViewDoc().setUuid("ABCD").setProjects(newArrayList("BCDE")));
indexer.index();
--- /dev/null
+<dataset>
+
+ <projects id="100" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts"
+ uuid="JKLM" project_uuid="JKLM" module_uuid="[null]" module_uuid_path="."
+ enabled="[true]" copy_resource_id="[null]" path="[null]"/>
+
+ <snapshots id="100" project_id="100" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" version="[null]" path=""/>
+
+ <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="NewRuleKey" plugin_name="plugin" name="new name" description="new description" status="DEPRECATED"
+ plugin_config_key="NewConfigKey" priority="0" is_template="[true]" language="dart" created_at="2013-12-16" updated_at="2013-12-16" template_id="3"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]"
+ characteristic_id="100" default_characteristic_id="101"
+ remediation_function="LINEAR" default_remediation_function="LINEAR_OFFSET"
+ remediation_coeff="1h" default_remediation_coeff="5d"
+ remediation_offset="5min" default_remediation_offset="10h"
+ effort_to_fix_description="squid.S115.effortToFix" description_format="MARKDOWN"/>
+
+ <properties id="1" prop_key="sonar.profile.java" text_value="Sonar Way" resource_id="1" user_id="[null]"/>
+
+</dataset>