001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2011 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.core.purge; 021 022 import org.sonar.api.batch.Purge; 023 import org.sonar.api.database.DatabaseSession; 024 import org.sonar.api.database.model.*; 025 import org.sonar.api.design.DependencyDto; 026 import org.sonar.api.utils.TimeProfiler; 027 028 import java.util.List; 029 030 import javax.persistence.Query; 031 032 /** 033 * @deprecated since 2.5. The DBCleaner plugin implements all required purge taks, but you can extend org.sonar.plugins.dbcleaner.api.Purge 034 */ 035 @Deprecated 036 public abstract class AbstractPurge implements Purge { 037 038 private static final int MAX_IN_ELEMENTS = 950; 039 040 private int sqlInPageSize = MAX_IN_ELEMENTS; 041 private DatabaseSession session; 042 private TimeProfiler profiler = new TimeProfiler().setLevelToDebug(); 043 044 public AbstractPurge(DatabaseSession session) { 045 this.session = session; 046 } 047 048 protected DatabaseSession getSession() { 049 return session; 050 } 051 052 /** 053 * Delete SNAPSHOTS and all dependent tables (MEASURES, ...) 054 */ 055 protected void deleteSnapshotData(List<Integer> snapshotIds) { 056 deleteMeasuresBySnapshotId(snapshotIds); 057 deleteSources(snapshotIds); 058 deleteViolations(snapshotIds); 059 deleteDependencies(snapshotIds); 060 deleteSnapshots(snapshotIds); 061 } 062 063 protected void deleteDependencies(List<Integer> snapshotIds) { 064 executeQuery("delete dependencies", snapshotIds, "delete from " + DependencyDto.class.getSimpleName() 065 + " d where d.fromSnapshotId in (:ids)"); 066 executeQuery("delete dependencies", snapshotIds, "delete from " + DependencyDto.class.getSimpleName() 067 + " d where d.toSnapshotId in (:ids)"); 068 } 069 070 /** 071 * Delete all measures, including MEASURE_DATA 072 */ 073 protected void deleteMeasuresBySnapshotId(List<Integer> snapshotIds) { 074 executeQuery("delete measures by snapshot id", snapshotIds, "delete from " + MeasureData.class.getSimpleName() 075 + " m where m.snapshotId in (:ids)"); 076 executeQuery("delete measures by snapshot id", snapshotIds, "delete from " + MeasureModel.class.getSimpleName() 077 + " m where m.snapshotId in (:ids)"); 078 } 079 080 /** 081 * Delete all measures, including MEASURE_DATA 082 */ 083 protected void deleteMeasuresById(List<Integer> measureIds) { 084 executeQuery("delete measures by id", measureIds, "delete from " + MeasureData.class.getSimpleName() 085 + " m where m.measure.id in (:ids)"); 086 executeQuery("delete measures by id", measureIds, "delete from " + MeasureModel.class.getSimpleName() + " m where m.id in (:ids)"); 087 } 088 089 /** 090 * Delete SNAPSHOT_SOURCES table 091 */ 092 protected void deleteSources(List<Integer> snapshotIds) { 093 executeQuery("delete sources", snapshotIds, "delete from " + SnapshotSource.class.getSimpleName() + " e where e.snapshotId in (:ids)"); 094 } 095 096 /** 097 * Delete violations (RULE_FAILURES table) 098 */ 099 protected void deleteViolations(List<Integer> snapshotIds) { 100 executeQuery("delete violations", snapshotIds, "delete from " + RuleFailureModel.class.getSimpleName() 101 + " e where e.snapshotId in (:ids)"); 102 } 103 104 /** 105 * Delete SNAPSHOTS table 106 */ 107 protected void deleteSnapshots(List<Integer> snapshotIds) { 108 executeQuery("delete snapshots", snapshotIds, "delete from " + Snapshot.class.getSimpleName() + " s where s.id in (:ids)"); 109 } 110 111 /** 112 * Paginate execution of SQL requests to avoid exceeding size of rollback segment 113 */ 114 private void executeQuery(String name, List<Integer> ids, String hql) { 115 if (ids == null || ids.isEmpty()) { 116 return; 117 } 118 119 TimeProfiler profiler = new TimeProfiler().setLevelToDebug().start("Execute " + name); 120 121 int page = 1; 122 int index = 0; 123 while (index < ids.size()) { 124 TimeProfiler pageProfiler = new TimeProfiler().setLevelToDebug().start("Execute " + name + " " + page + " page"); 125 Query query = session.createQuery(hql); 126 List<Integer> paginedSids = ids.subList(index, Math.min(ids.size(), index + sqlInPageSize)); 127 query.setParameter("ids", paginedSids); 128 query.executeUpdate(); 129 index += sqlInPageSize; 130 page++; 131 session.commit(); 132 pageProfiler.stop(); 133 } 134 135 profiler.stop(); 136 } 137 138 protected void executeQuery(List<Integer> ids, String hql) { 139 executeQuery("delete for " + getClass().getSimpleName(), ids, hql); 140 } 141 142 protected List<Integer> selectIds(Query query) { 143 profiler.start("Select IDs for " + getClass().getSimpleName()); 144 List<Integer> result = query.getResultList(); 145 profiler.stop(); 146 return result; 147 } 148 }