You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PurgeCommands.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.db.purge;
  21. import com.google.common.annotations.VisibleForTesting;
  22. import com.google.common.collect.Lists;
  23. import java.util.Collection;
  24. import java.util.HashSet;
  25. import java.util.List;
  26. import java.util.Set;
  27. import javax.annotation.Nullable;
  28. import org.sonar.api.utils.System2;
  29. import org.sonar.db.DbSession;
  30. import static org.sonar.db.DatabaseUtils.executeLargeInputs;
  31. class PurgeCommands {
  32. private static final int MAX_SNAPSHOTS_PER_QUERY = 1000;
  33. private static final int MAX_RESOURCES_PER_QUERY = 1000;
  34. private static final String[] UNPROCESSED_STATUS = new String[] {"U"};
  35. private final DbSession session;
  36. private final PurgeMapper purgeMapper;
  37. private final PurgeProfiler profiler;
  38. private final System2 system2;
  39. PurgeCommands(DbSession session, PurgeMapper purgeMapper, PurgeProfiler profiler, System2 system2) {
  40. this.session = session;
  41. this.purgeMapper = purgeMapper;
  42. this.profiler = profiler;
  43. this.system2 = system2;
  44. }
  45. @VisibleForTesting
  46. PurgeCommands(DbSession session, PurgeProfiler profiler, System2 system2) {
  47. this(session, session.getMapper(PurgeMapper.class), profiler, system2);
  48. }
  49. List<IdUuidPair> selectSnapshotIdUuids(PurgeSnapshotQuery query) {
  50. return purgeMapper.selectAnalysisIdsAndUuids(query);
  51. }
  52. void deleteAnalyses(String rootComponentUuid) {
  53. profiler.start("deleteAnalyses (event_component_changes)");
  54. purgeMapper.deleteEventComponentChangesByComponentUuid(rootComponentUuid);
  55. session.commit();
  56. profiler.stop();
  57. profiler.start("deleteAnalyses (events)");
  58. purgeMapper.deleteEventsByComponentUuid(rootComponentUuid);
  59. session.commit();
  60. profiler.stop();
  61. List<List<String>> analysisUuidsPartitions = Lists.partition(IdUuidPairs.uuids(
  62. purgeMapper.selectAnalysisIdsAndUuids(new PurgeSnapshotQuery(rootComponentUuid))), MAX_SNAPSHOTS_PER_QUERY);
  63. deleteAnalysisDuplications(analysisUuidsPartitions);
  64. profiler.start("deleteAnalyses (project_measures)");
  65. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisMeasures);
  66. session.commit();
  67. profiler.stop();
  68. profiler.start("deleteAnalyses (analysis_properties)");
  69. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisProperties);
  70. session.commit();
  71. profiler.stop();
  72. profiler.start("deleteAnalyses (snapshots)");
  73. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalyses);
  74. session.commit();
  75. profiler.stop();
  76. }
  77. void deleteAbortedAnalyses(String rootUuid) {
  78. PurgeSnapshotQuery query = new PurgeSnapshotQuery(rootUuid)
  79. .setIslast(false)
  80. .setStatus(UNPROCESSED_STATUS);
  81. deleteAnalyses(purgeMapper.selectAnalysisIdsAndUuids(query));
  82. }
  83. @VisibleForTesting
  84. void deleteAnalyses(List<IdUuidPair> analysisIdUuids) {
  85. List<List<String>> analysisUuidsPartitions = Lists.partition(IdUuidPairs.uuids(analysisIdUuids), MAX_SNAPSHOTS_PER_QUERY);
  86. deleteAnalysisDuplications(analysisUuidsPartitions);
  87. profiler.start("deleteAnalyses (event_component_changes)");
  88. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisEventComponentChanges);
  89. session.commit();
  90. profiler.stop();
  91. profiler.start("deleteAnalyses (events)");
  92. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisEvents);
  93. session.commit();
  94. profiler.stop();
  95. profiler.start("deleteAnalyses (project_measures)");
  96. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisMeasures);
  97. session.commit();
  98. profiler.stop();
  99. profiler.start("deleteAnalyses (analysis_properties)");
  100. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisProperties);
  101. session.commit();
  102. profiler.stop();
  103. profiler.start("deleteAnalyses (snapshots)");
  104. analysisUuidsPartitions.forEach(purgeMapper::deleteAnalyses);
  105. session.commit();
  106. profiler.stop();
  107. }
  108. void purgeAnalyses(List<IdUuidPair> analysisUuids) {
  109. List<List<String>> analysisUuidsPartitions = Lists.partition(IdUuidPairs.uuids(analysisUuids), MAX_SNAPSHOTS_PER_QUERY);
  110. deleteAnalysisDuplications(analysisUuidsPartitions);
  111. profiler.start("updatePurgeStatusToOne (snapshots)");
  112. analysisUuidsPartitions.forEach(purgeMapper::updatePurgeStatusToOne);
  113. session.commit();
  114. profiler.stop();
  115. }
  116. void purgeDisabledComponents(String rootComponentUuid, Collection<String> disabledComponentUuids, PurgeListener listener) {
  117. Set<String> missedDisabledComponentUuids = new HashSet<>();
  118. profiler.start("purgeDisabledComponents (file_sources)");
  119. missedDisabledComponentUuids.addAll(
  120. executeLargeInputs(
  121. purgeMapper.selectDisabledComponentsWithFileSource(rootComponentUuid),
  122. input -> {
  123. purgeMapper.deleteFileSourcesByFileUuid(input);
  124. return input;
  125. }));
  126. profiler.stop();
  127. profiler.start("purgeDisabledComponents (unresolved_issues)");
  128. missedDisabledComponentUuids.addAll(
  129. executeLargeInputs(
  130. purgeMapper.selectDisabledComponentsWithUnresolvedIssues(rootComponentUuid),
  131. input -> {
  132. purgeMapper.resolveComponentIssuesNotAlreadyResolved(input, system2.now());
  133. return input;
  134. }));
  135. profiler.stop();
  136. profiler.start("purgeDisabledComponents (live_measures)");
  137. missedDisabledComponentUuids.addAll(
  138. executeLargeInputs(
  139. purgeMapper.selectDisabledComponentsWithLiveMeasures(rootComponentUuid),
  140. input -> {
  141. purgeMapper.deleteLiveMeasuresByComponentUuids(input);
  142. return input;
  143. }));
  144. profiler.stop();
  145. session.commit();
  146. // notify listener for any disabled component we found child data for which isn't part of the disabled components
  147. // provided
  148. missedDisabledComponentUuids.removeAll(disabledComponentUuids);
  149. if (!missedDisabledComponentUuids.isEmpty()) {
  150. listener.onComponentsDisabling(rootComponentUuid, missedDisabledComponentUuids);
  151. }
  152. }
  153. private void deleteAnalysisDuplications(List<List<String>> snapshotUuidsPartitions) {
  154. profiler.start("deleteAnalysisDuplications (duplications_index)");
  155. snapshotUuidsPartitions.forEach(purgeMapper::deleteAnalysisDuplications);
  156. session.commit();
  157. profiler.stop();
  158. }
  159. void deletePermissions(long rootId) {
  160. profiler.start("deletePermissions (group_roles)");
  161. purgeMapper.deleteGroupRolesByComponentId(rootId);
  162. session.commit();
  163. profiler.stop();
  164. profiler.start("deletePermissions (user_roles)");
  165. purgeMapper.deleteUserRolesByComponentId(rootId);
  166. session.commit();
  167. profiler.stop();
  168. }
  169. void deleteIssues(String rootUuid) {
  170. profiler.start("deleteIssues (issue_changes)");
  171. purgeMapper.deleteIssueChangesByProjectUuid(rootUuid);
  172. session.commit();
  173. profiler.stop();
  174. profiler.start("deleteIssues (issues)");
  175. purgeMapper.deleteIssuesByProjectUuid(rootUuid);
  176. session.commit();
  177. profiler.stop();
  178. }
  179. void deleteLinks(String rootUuid) {
  180. profiler.start("deleteLinks (project_links)");
  181. purgeMapper.deleteProjectLinksByProjectUuid(rootUuid);
  182. session.commit();
  183. profiler.stop();
  184. }
  185. void deleteByRootAndModulesOrSubviews(List<IdUuidPair> rootAndModulesOrSubviewsIds) {
  186. if (rootAndModulesOrSubviewsIds.isEmpty()) {
  187. return;
  188. }
  189. List<List<Long>> idPartitions = Lists.partition(IdUuidPairs.ids(rootAndModulesOrSubviewsIds), MAX_RESOURCES_PER_QUERY);
  190. List<List<String>> uuidsPartitions = Lists.partition(IdUuidPairs.uuids(rootAndModulesOrSubviewsIds), MAX_RESOURCES_PER_QUERY);
  191. profiler.start("deleteByRootAndModulesOrSubviews (properties)");
  192. idPartitions.forEach(purgeMapper::deletePropertiesByComponentIds);
  193. session.commit();
  194. profiler.stop();
  195. profiler.start("deleteByRootAndModulesOrSubviews (manual_measures)");
  196. uuidsPartitions.forEach(purgeMapper::deleteManualMeasuresByComponentUuids);
  197. session.commit();
  198. profiler.stop();
  199. }
  200. void deleteDisabledComponentsWithoutIssues(List<IdUuidPair> disabledComponentsWithoutIssue) {
  201. if (disabledComponentsWithoutIssue.isEmpty()) {
  202. return;
  203. }
  204. List<List<Long>> idPartitions = Lists.partition(IdUuidPairs.ids(disabledComponentsWithoutIssue), MAX_RESOURCES_PER_QUERY);
  205. List<List<String>> uuidsPartitions = Lists.partition(IdUuidPairs.uuids(disabledComponentsWithoutIssue), MAX_RESOURCES_PER_QUERY);
  206. profiler.start("deleteDisabledComponentsWithoutIssues (properties)");
  207. idPartitions.forEach(purgeMapper::deletePropertiesByComponentIds);
  208. session.commit();
  209. profiler.stop();
  210. profiler.start("deleteDisabledComponentsWithoutIssues (manual_measures)");
  211. uuidsPartitions.forEach(purgeMapper::deleteManualMeasuresByComponentUuids);
  212. session.commit();
  213. profiler.stop();
  214. profiler.start("deleteDisabledComponentsWithoutIssues (projects)");
  215. uuidsPartitions.forEach(purgeMapper::deleteComponentsByUuids);
  216. session.commit();
  217. profiler.stop();
  218. }
  219. void deleteComponents(String rootUuid) {
  220. profiler.start("deleteComponents (projects)");
  221. purgeMapper.deleteComponentsByProjectUuid(rootUuid);
  222. session.commit();
  223. profiler.stop();
  224. }
  225. void deleteProject(String projectUuid) {
  226. profiler.start("deleteProject (projects)");
  227. purgeMapper.deleteProjectsByProjectUuid(projectUuid);
  228. session.commit();
  229. profiler.stop();
  230. }
  231. void deleteComponents(List<String> componentUuids) {
  232. if (componentUuids.isEmpty()) {
  233. return;
  234. }
  235. profiler.start("deleteComponents (projects)");
  236. Lists.partition(componentUuids, MAX_RESOURCES_PER_QUERY).forEach(purgeMapper::deleteComponentsByUuids);
  237. session.commit();
  238. profiler.stop();
  239. }
  240. void deleteComponentMeasures(List<String> componentUuids) {
  241. if (componentUuids.isEmpty()) {
  242. return;
  243. }
  244. profiler.start("deleteComponentMeasures (project_measures)");
  245. Lists.partition(componentUuids, MAX_RESOURCES_PER_QUERY).forEach(purgeMapper::fullDeleteComponentMeasures);
  246. session.commit();
  247. profiler.stop();
  248. }
  249. void deleteFileSources(String rootUuid) {
  250. profiler.start("deleteFileSources (file_sources)");
  251. purgeMapper.deleteFileSourcesByProjectUuid(rootUuid);
  252. session.commit();
  253. profiler.stop();
  254. }
  255. void deleteCeActivity(String rootUuid) {
  256. profiler.start("deleteCeActivity (ce_scanner_context)");
  257. purgeMapper.deleteCeScannerContextOfCeActivityByRootUuidOrBefore(rootUuid, null);
  258. session.commit();
  259. profiler.stop();
  260. profiler.start("deleteCeActivity (ce_task_characteristics)");
  261. purgeMapper.deleteCeTaskCharacteristicsOfCeActivityByRootUuidOrBefore(rootUuid, null);
  262. session.commit();
  263. profiler.stop();
  264. profiler.start("deleteCeActivity (ce_task_input)");
  265. purgeMapper.deleteCeTaskInputOfCeActivityByRootUuidOrBefore(rootUuid, null);
  266. session.commit();
  267. profiler.stop();
  268. profiler.start("deleteCeActivity (ce_task_message)");
  269. purgeMapper.deleteCeTaskMessageOfCeActivityByRootUuidOrBefore(rootUuid, null);
  270. session.commit();
  271. profiler.stop();
  272. profiler.start("deleteCeActivity (ce_activity)");
  273. purgeMapper.deleteCeActivityByRootUuidOrBefore(rootUuid, null);
  274. session.commit();
  275. profiler.stop();
  276. }
  277. void deleteCeActivityBefore(@Nullable String rootUuid, long createdAt) {
  278. profiler.start("deleteCeActivityBefore (ce_scanner_context)");
  279. purgeMapper.deleteCeScannerContextOfCeActivityByRootUuidOrBefore(rootUuid, createdAt);
  280. session.commit();
  281. profiler.stop();
  282. profiler.start("deleteCeActivityBefore (ce_task_characteristics)");
  283. purgeMapper.deleteCeTaskCharacteristicsOfCeActivityByRootUuidOrBefore(rootUuid, createdAt);
  284. session.commit();
  285. profiler.stop();
  286. profiler.start("deleteCeActivityBefore (ce_task_input)");
  287. purgeMapper.deleteCeTaskInputOfCeActivityByRootUuidOrBefore(rootUuid, createdAt);
  288. session.commit();
  289. profiler.stop();
  290. profiler.start("deleteCeActivityBefore (ce_task_message)");
  291. purgeMapper.deleteCeTaskMessageOfCeActivityByRootUuidOrBefore(rootUuid, createdAt);
  292. session.commit();
  293. profiler.stop();
  294. profiler.start("deleteCeActivityBefore (ce_activity)");
  295. purgeMapper.deleteCeActivityByRootUuidOrBefore(rootUuid, createdAt);
  296. session.commit();
  297. profiler.stop();
  298. }
  299. void deleteCeScannerContextBefore(@Nullable String rootUuid, long createdAt) {
  300. // assuming CeScannerContext of rows in table CE_QUEUE can't be older than createdAt
  301. profiler.start("deleteCeScannerContextBefore");
  302. purgeMapper.deleteCeScannerContextOfCeActivityByRootUuidOrBefore(rootUuid, createdAt);
  303. session.commit();
  304. }
  305. void deleteCeQueue(String rootUuid) {
  306. profiler.start("deleteCeQueue (ce_scanner_context)");
  307. purgeMapper.deleteCeScannerContextOfCeQueueByRootUuid(rootUuid);
  308. session.commit();
  309. profiler.stop();
  310. profiler.start("deleteCeQueue (ce_task_characteristics)");
  311. purgeMapper.deleteCeTaskCharacteristicsOfCeQueueByRootUuid(rootUuid);
  312. session.commit();
  313. profiler.stop();
  314. profiler.start("deleteCeQueue (ce_task_input)");
  315. purgeMapper.deleteCeTaskInputOfCeQueueByRootUuid(rootUuid);
  316. session.commit();
  317. profiler.stop();
  318. profiler.start("deleteCeQueue (ce_task_message)");
  319. purgeMapper.deleteCeTaskMessageOfCeQueueByRootUuid(rootUuid);
  320. session.commit();
  321. profiler.stop();
  322. profiler.start("deleteCeQueue (ce_queue)");
  323. purgeMapper.deleteCeQueueByRootUuid(rootUuid);
  324. session.commit();
  325. profiler.stop();
  326. }
  327. void deleteWebhooks(String rootUuid) {
  328. profiler.start("deleteWebhooks (webhooks)");
  329. purgeMapper.deleteWebhooksByProjectUuid(rootUuid);
  330. session.commit();
  331. profiler.stop();
  332. }
  333. void deleteWebhookDeliveries(String rootUuid) {
  334. profiler.start("deleteWebhookDeliveries (webhook_deliveries)");
  335. purgeMapper.deleteWebhookDeliveriesByProjectUuid(rootUuid);
  336. session.commit();
  337. profiler.stop();
  338. }
  339. void deleteProjectMappings(String rootUuid) {
  340. profiler.start("deleteProjectMappings (project_mappings)");
  341. purgeMapper.deleteProjectMappingsByProjectUuid(rootUuid);
  342. session.commit();
  343. profiler.stop();
  344. }
  345. void deleteProjectAlmBindings(String rootUuid) {
  346. profiler.start("deleteProjectAlmBindings (project_alm_bindings)");
  347. purgeMapper.deleteProjectAlmBindingsByProjectUuid(rootUuid);
  348. session.commit();
  349. profiler.stop();
  350. }
  351. void deleteBranch(String rootUuid) {
  352. profiler.start("deleteBranch (project_branches)");
  353. purgeMapper.deleteBranchByUuid(rootUuid);
  354. session.commit();
  355. profiler.stop();
  356. }
  357. void deleteLiveMeasures(String rootUuid) {
  358. profiler.start("deleteLiveMeasures (live_measures)");
  359. purgeMapper.deleteLiveMeasuresByProjectUuid(rootUuid);
  360. session.commit();
  361. profiler.stop();
  362. }
  363. void deleteNewCodePeriods(String rootUuid) {
  364. profiler.start("deleteNewCodePeriods (new_code_periods)");
  365. purgeMapper.deleteNewCodePeriodsByRootUuid(rootUuid);
  366. session.commit();
  367. profiler.stop();
  368. }
  369. }