diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-11-05 09:37:51 +0100 |
---|---|---|
committer | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-11-05 17:21:28 +0100 |
commit | 0e9234234737081869c10678aa4468e172156b25 (patch) | |
tree | 6a379dd7ad44b8439f05c5b55ab79870b66553a8 /sonar-core/src | |
parent | b2b14860c7cd86c9156e62e309a0152746f34566 (diff) | |
download | sonarqube-0e9234234737081869c10678aa4468e172156b25.tar.gz sonarqube-0e9234234737081869c10678aa4468e172156b25.zip |
SONAR-5628 Project settings taken into account during the data cleaning of project analysis
Diffstat (limited to 'sonar-core/src')
8 files changed, 238 insertions, 26 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTask.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTask.java new file mode 100644 index 00000000000..a2e1fe842ec --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTask.java @@ -0,0 +1,77 @@ +/* + * 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.core.computation.dbcleaner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.CoreProperties; +import org.sonar.api.ServerComponent; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.TimeUtils; +import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner; +import org.sonar.core.purge.PurgeConfiguration; +import org.sonar.core.purge.PurgeDao; +import org.sonar.core.purge.PurgeProfiler; + +public class ProjectPurgeTask implements ServerComponent { + private static final Logger LOG = LoggerFactory.getLogger(ProjectPurgeTask.class); + private final PurgeProfiler profiler; + private final PurgeDao purgeDao; + private final DefaultPeriodCleaner periodCleaner; + + public ProjectPurgeTask(PurgeDao purgeDao, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) { + this.purgeDao = purgeDao; + this.periodCleaner = periodCleaner; + this.profiler = profiler; + } + + public ProjectPurgeTask purge(PurgeConfiguration configuration, Settings settings) { + long start = System.currentTimeMillis(); + profiler.reset(); + cleanHistoricalData(configuration.rootProjectId(), settings); + doPurge(configuration); + if (settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)) { + long duration = System.currentTimeMillis() - start; + LOG.info("\n -------- Profiling for purge: " + TimeUtils.formatDuration(duration) + " --------\n"); + profiler.dump(duration, LOG); + LOG.info("\n -------- End of profiling for purge --------\n"); + } + return this; + } + + private void cleanHistoricalData(long resourceId, Settings settings) { + try { + periodCleaner.clean(resourceId, settings); + } catch (Exception e) { + // purge errors must no fail the batch + LOG.error("Fail to clean historical data [id=" + resourceId + "]", e); + } + } + + private void doPurge(PurgeConfiguration configuration) { + try { + purgeDao.purge(configuration); + } catch (Exception e) { + // purge errors must no fail the report analysis + LOG.error("Fail to purge data [id=" + configuration.rootProjectId() + "]", e); + } + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java index a7f8a482533..bbb6a222ba8 100644 --- a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java +++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java @@ -25,7 +25,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.ServerExtension; import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; import org.sonar.api.task.TaskExtension; import org.sonar.api.utils.DateUtils; import org.sonar.core.purge.PurgeDao; @@ -45,11 +44,11 @@ public class DefaultPeriodCleaner implements TaskExtension, ServerExtension { this.settings = settings; } - public void purge(Project project, int projectSnapshotId) { - clean(project.getId()); + public void clean(long projectId) { + clean(projectId, settings); } - public void clean(long projectId) { + public void clean(long projectId, Settings settings) { doClean(projectId, new Filters(settings).all()); } diff --git a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java index e7a13b39f26..6865434dfcd 100644 --- a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java +++ b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java @@ -99,6 +99,15 @@ public class PropertiesDao implements BatchComponent, ServerComponent, DaoCompon return session.getMapper(PropertiesMapper.class).selectProjectProperties(resourceKey); } + public List<PropertyDto> selectProjectProperties(long resourceId) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(PropertiesMapper.class).selectProjectPropertiesByResourceId(resourceId); + } finally { + MyBatis.closeQuietly(session); + } + } + public List<PropertyDto> selectProjectProperties(String resourceKey) { SqlSession session = mybatis.openSession(false); try { diff --git a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java index 6cdf28160af..10f298b53c3 100644 --- a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java @@ -35,6 +35,8 @@ public interface PropertiesMapper { List<PropertyDto> selectProjectProperties(String resourceKey); + List<PropertyDto> selectProjectPropertiesByResourceId(Long resourceId); + List<PropertyDto> selectSetOfResourceProperties(@Param("rId") Long projectId, @Param("propKeys") List<String> propertyKeys); PropertyDto selectByKey(PropertyDto key); @@ -57,5 +59,5 @@ public interface PropertiesMapper { void renamePropertyKey(@Param("oldKey") String oldKey, @Param("newKey") String newKey); - void updateProperties(@Param("key") String key, @Param("oldValue")String oldValue, @Param("newValue") String newValue); + void updateProperties(@Param("key") String key, @Param("oldValue") String oldValue, @Param("newValue") String newValue); } diff --git a/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml b/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml index 250b49a361b..dedc3d19362 100644 --- a/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml @@ -20,23 +20,29 @@ FROM properties P, users U WHERE P.user_id = U.id AND P.prop_key = #{propKey} AND P.text_value LIKE 'true' AND ( - P.resource_id is null + P.resource_id is null <if test="componentKey != null"> OR P.resource_id in (select id from projects where kee=#{componentKey}) </if> ) </select> - <select id="selectGlobalProperties" resultType="Property" > + <select id="selectGlobalProperties" resultType="Property"> select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId from properties p where p.resource_id is null and p.user_id is null </select> - <select id="selectProjectProperties" parameterType="String" resultType="Property" > + <select id="selectProjectProperties" parameterType="String" resultType="Property"> select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId from properties p, projects r - where p.resource_id=r.id and p.user_id is null and r.kee=#{id} + where p.resource_id=r.id and p.user_id is null and r.kee=#{resourceKey} + </select> + + <select id="selectProjectPropertiesByResourceId" parameterType="Long" resultType="Property"> + select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId + from properties p + where p.resource_id=#{resourceId} and p.user_id is null </select> <select id="selectSetOfResourceProperties" parameterType="map" resultType="Property"> @@ -80,45 +86,45 @@ </where> </select> - <update id="update" parameterType="Property" > + <update id="update" parameterType="Property"> update properties set text_value = #{value} where id = #{id} </update> - <insert id="insert" parameterType="Property" useGeneratedKeys="false" > + <insert id="insert" parameterType="Property" useGeneratedKeys="false"> INSERT INTO properties (prop_key, resource_id, user_id, text_value) VALUES (#{key}, #{resourceId}, #{userId}, #{value}) </insert> - <delete id="deleteProjectProperty" parameterType="map" > + <delete id="deleteProjectProperty" parameterType="map"> delete from properties where prop_key=#{key} and resource_id=#{rId} and user_id is null </delete> - <delete id="deleteProjectProperties" parameterType="map" > + <delete id="deleteProjectProperties" parameterType="map"> DELETE FROM properties WHERE - prop_key=#{key} - AND text_value LIKE #{value} - AND resource_id IS NOT NULL - AND user_id IS NULL + prop_key=#{key} + AND text_value LIKE #{value} + AND resource_id IS NOT NULL + AND user_id IS NULL </delete> - <delete id="deleteGlobalProperty" parameterType="string" > + <delete id="deleteGlobalProperty" parameterType="string"> delete from properties where prop_key=#{id} and resource_id is null and user_id is null </delete> - <delete id="deleteGlobalProperties" > + <delete id="deleteGlobalProperties"> delete from properties where resource_id is null and user_id is null </delete> - <delete id="deleteAllProperties" parameterType="string" > + <delete id="deleteAllProperties" parameterType="string"> delete from properties where prop_key=#{id} </delete> - <update id="renamePropertyKey" parameterType="map" > + <update id="renamePropertyKey" parameterType="map"> update properties set prop_key=#{newKey} where prop_key=#{oldKey} </update> - <update id="updateProperties" parameterType="map" > + <update id="updateProperties" parameterType="map"> update properties set text_value=#{newValue} where text_value LIKE #{oldValue} and prop_key=#{key} </update> diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTaskTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTaskTest.java new file mode 100644 index 00000000000..5b96c00a150 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTaskTest.java @@ -0,0 +1,88 @@ +/* + * 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.core.computation.dbcleaner; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner; +import org.sonar.core.purge.PurgeConfiguration; +import org.sonar.core.purge.PurgeDao; +import org.sonar.core.purge.PurgeProfiler; + +import static org.mockito.Mockito.*; + +public class ProjectPurgeTaskTest { + + private ProjectPurgeTask sut; + private PurgeDao dao; + private PurgeProfiler profiler; + private DefaultPeriodCleaner periodCleaner; + + @Before + public void before() throws Exception { + this.dao = mock(PurgeDao.class); + this.profiler = mock(PurgeProfiler.class); + this.periodCleaner = mock(DefaultPeriodCleaner.class); + + this.sut = new ProjectPurgeTask(dao, periodCleaner, profiler); + } + + @Test + public void no_profiling_when_property_is_false() throws Exception { + Settings settings = mock(Settings.class); + when(settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)).thenReturn(false); + + sut.purge(mock(PurgeConfiguration.class), settings); + + verify(profiler, never()).dump(anyLong(), any(Logger.class)); + } + + @Test + public void profiling_when_property_is_true() throws Exception { + Settings settings = mock(Settings.class); + when(settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)).thenReturn(true); + + sut.purge(mock(PurgeConfiguration.class), settings); + + verify(profiler, times(1)).dump(anyLong(), any(Logger.class)); + } + + @Test + public void if_dao_purge_fails_it_should_not_interrupt_program_execution() throws Exception { + when(dao.purge(any(PurgeConfiguration.class))).thenThrow(NullPointerException.class); + + sut.purge(mock(PurgeConfiguration.class), mock(Settings.class)); + + verify(dao, times(1)).purge(any(PurgeConfiguration.class)); + } + + @Test + public void if_profiler_cleaning_fails_it_should_not_interrupt_program_execution() throws Exception { + doThrow(NullPointerException.class).when(periodCleaner).clean(anyLong(), any(Settings.class)); + + sut.purge(mock(PurgeConfiguration.class), mock(Settings.class)); + + verify(periodCleaner, times(1)).clean(anyLong(), any(Settings.class)); + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java b/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java index 807bfec1775..454ba2829c2 100644 --- a/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java @@ -36,12 +36,10 @@ import static org.junit.Assert.assertThat; public class PropertiesDaoTest extends AbstractDaoTestCase { - private DbSession session; - - private PropertiesDao dao; - @Rule public ExpectedException thrown = ExpectedException.none(); + private DbSession session; + private PropertiesDao dao; @Before public void createDao() { @@ -144,6 +142,17 @@ public class PropertiesDaoTest extends AbstractDaoTestCase { } @Test + public void selectProjectPropertiesByResourceId() { + setupData("selectProjectPropertiesByResourceId"); + + List<PropertyDto> properties = dao.selectProjectProperties(10L); + + assertThat(properties.size(), is(2)); + assertThat(properties).onProperty("key").containsOnly("struts.one", "user.two"); + assertThat(properties).onProperty("value").containsOnly("one", "two"); + } + + @Test public void selectProjectProperty() { setupData("selectProjectProperties"); PropertyDto property = dao.selectProjectProperty(11L, "commonslang.one"); diff --git a/sonar-core/src/test/resources/org/sonar/core/properties/PropertiesDaoTest/selectProjectPropertiesByResourceId.xml b/sonar-core/src/test/resources/org/sonar/core/properties/PropertiesDaoTest/selectProjectPropertiesByResourceId.xml new file mode 100644 index 00000000000..52fec852a8d --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/properties/PropertiesDaoTest/selectProjectPropertiesByResourceId.xml @@ -0,0 +1,22 @@ +<dataset> + + <!-- global --> + <properties id="1" prop_key="global.one" text_value="one" resource_id="[null]" user_id="[null]"/> + <properties id="2" prop_key="global.two" text_value="two" resource_id="[null]" user_id="[null]"/> + + <!-- struts --> + <properties id="3" prop_key="struts.one" text_value="one" resource_id="10" user_id="[null]"/> + + <!-- commons --> + <properties id="4" prop_key="commonslang.one" text_value="two" resource_id="11" user_id="[null]"/> + + <!-- user --> + <properties id="5" prop_key="user.one" text_value="one" resource_id="[null]" user_id="100"/> + <properties id="6" prop_key="user.two" text_value="two" resource_id="10" user_id="[null]"/> + + <properties id="7" prop_key="commonslang.one" text_value="one" resource_id="12" user_id="[null]"/> + + <projects id="10" uuid="A" kee="org.struts:struts"/> + <projects id="11" uuid="B" kee="org.apache:commons-lang"/> + <projects id="12" uuid="C" kee="other"/> +</dataset> |