org.sonar.db.purge.PurgeCommands.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.db.purge.PurgeCommands.java

Source

/*
 * SonarQube
 * Copyright (C) 2009-2017 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.db.purge;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.stream.Collectors;
import org.sonar.db.DbSession;

import static com.google.common.collect.FluentIterable.from;
import static java.util.Arrays.asList;

class PurgeCommands {

    private static final int MAX_SNAPSHOTS_PER_QUERY = 1000;
    private static final int MAX_RESOURCES_PER_QUERY = 1000;

    private final DbSession session;
    private final PurgeMapper purgeMapper;
    private final PurgeProfiler profiler;

    PurgeCommands(DbSession session, PurgeMapper purgeMapper, PurgeProfiler profiler) {
        this.session = session;
        this.purgeMapper = purgeMapper;
        this.profiler = profiler;
    }

    @VisibleForTesting
    PurgeCommands(DbSession session, PurgeProfiler profiler) {
        this(session, session.getMapper(PurgeMapper.class), profiler);
    }

    List<String> selectSnapshotUuids(PurgeSnapshotQuery query) {
        return purgeMapper.selectAnalysisIdsAndUuids(query).stream().map(IdUuidPair::getUuid)
                .collect(Collectors.toList());
    }

    List<IdUuidPair> selectSnapshotIdUuids(PurgeSnapshotQuery query) {
        return purgeMapper.selectAnalysisIdsAndUuids(query);
    }

    void deleteAnalyses(String rootUuid) {
        deleteAnalyses(purgeMapper.selectAnalysisIdsAndUuids(new PurgeSnapshotQuery().setComponentUuid(rootUuid)));
    }

    void deleteComponents(List<IdUuidPair> componentIdUuids) {
        List<List<Long>> componentIdPartitions = Lists.partition(IdUuidPairs.ids(componentIdUuids),
                MAX_RESOURCES_PER_QUERY);
        List<List<String>> componentUuidsPartitions = Lists.partition(IdUuidPairs.uuids(componentIdUuids),
                MAX_RESOURCES_PER_QUERY);
        // Note : do not merge the delete statements into a single loop of resource ids. It's
        // voluntarily grouped by tables in order to benefit from JDBC batch mode.
        // Batch requests can only relate to the same PreparedStatement.

        // possible missing optimization: filter requests according to resource scope

        profiler.start("deleteResourceLinks (project_links)");
        componentUuidsPartitions.forEach(purgeMapper::deleteComponentLinks);
        session.commit();
        profiler.stop();

        profiler.start("deleteResourceProperties (properties)");
        componentIdPartitions.forEach(purgeMapper::deleteComponentProperties);
        session.commit();
        profiler.stop();

        profiler.start("deleteResourceGroupRoles (group_roles)");
        componentIdPartitions.forEach(purgeMapper::deleteComponentGroupRoles);
        session.commit();
        profiler.stop();

        profiler.start("deleteResourceUserRoles (user_roles)");
        componentIdPartitions.forEach(purgeMapper::deleteComponentUserRoles);
        session.commit();
        profiler.stop();

        profiler.start("deleteResourceManualMeasures (manual_measures)");
        componentUuidsPartitions.forEach(purgeMapper::deleteComponentManualMeasures);
        session.commit();
        profiler.stop();

        profiler.start("deleteComponentIssueChanges (issue_changes)");
        componentUuidsPartitions.forEach(purgeMapper::deleteComponentIssueChanges);
        session.commit();
        profiler.stop();

        profiler.start("deleteComponentIssues (issues)");
        componentUuidsPartitions.forEach(purgeMapper::deleteComponentIssues);
        session.commit();
        profiler.stop();

        profiler.start("deleteComponentEvents (events)");
        componentUuidsPartitions.forEach(purgeMapper::deleteComponentEvents);
        session.commit();
        profiler.stop();

        profiler.start("deleteResource (projects)");
        componentUuidsPartitions.forEach(purgeMapper::deleteComponents);
        session.commit();
        profiler.stop();

        profiler.start("deleteAuthors (authors)");
        componentIdPartitions.forEach(purgeMapper::deleteAuthors);
        session.commit();
        profiler.stop();
    }

    public void deleteComponentMeasures(List<String> analysisUuids, List<String> componentUuids) {
        if (analysisUuids.isEmpty() || componentUuids.isEmpty()) {
            return;
        }

        List<List<String>> analysisUuidsPartitions = Lists.partition(analysisUuids, MAX_SNAPSHOTS_PER_QUERY);
        List<List<String>> componentUuidsPartitions = Lists.partition(componentUuids, MAX_RESOURCES_PER_QUERY);

        profiler.start("deleteComponentMeasures");
        for (List<String> analysisUuidsPartition : analysisUuidsPartitions) {
            for (List<String> componentUuidsPartition : componentUuidsPartitions) {
                purgeMapper.deleteComponentMeasures(analysisUuidsPartition, componentUuidsPartition);
            }
        }
        session.commit();
        profiler.stop();
    }

    void deleteAnalyses(PurgeSnapshotQuery... queries) {
        List<IdUuidPair> snapshotIds = from(asList(queries))
                .transformAndConcat(purgeMapper::selectAnalysisIdsAndUuids).toList();
        deleteAnalyses(snapshotIds);
    }

    @VisibleForTesting
    protected void deleteAnalyses(List<IdUuidPair> analysisIdUuids) {
        List<List<String>> analysisUuidsPartitions = Lists.partition(IdUuidPairs.uuids(analysisIdUuids),
                MAX_SNAPSHOTS_PER_QUERY);

        deleteAnalysisDuplications(analysisUuidsPartitions);

        profiler.start("deleteAnalyses (events)");
        analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisEvents);
        session.commit();
        profiler.stop();

        profiler.start("deleteAnalyses (project_measures)");
        analysisUuidsPartitions.forEach(purgeMapper::deleteAnalysisMeasures);
        session.commit();
        profiler.stop();

        profiler.start("deleteAnalyses (snapshots)");
        analysisUuidsPartitions.forEach(purgeMapper::deleteAnalyses);
        session.commit();
        profiler.stop();
    }

    public void purgeAnalyses(List<IdUuidPair> analysisUuids) {
        List<List<String>> analysisUuidsPartitions = Lists.partition(IdUuidPairs.uuids(analysisUuids),
                MAX_SNAPSHOTS_PER_QUERY);

        deleteAnalysisDuplications(analysisUuidsPartitions);

        profiler.start("deleteSnapshotWastedMeasures (project_measures)");
        List<Long> metricIdsWithoutHistoricalData = purgeMapper.selectMetricIdsWithoutHistoricalData();
        analysisUuidsPartitions.stream().forEach(analysisUuidsPartition -> purgeMapper
                .deleteAnalysisWastedMeasures(analysisUuidsPartition, metricIdsWithoutHistoricalData));
        session.commit();
        profiler.stop();

        profiler.start("updatePurgeStatusToOne (snapshots)");
        analysisUuidsPartitions.forEach(purgeMapper::updatePurgeStatusToOne);
        session.commit();
        profiler.stop();
    }

    private void deleteAnalysisDuplications(List<List<String>> snapshotUuidsPartitions) {
        profiler.start("deleteAnalysisDuplications (duplications_index)");
        snapshotUuidsPartitions.forEach(purgeMapper::deleteAnalysisDuplications);
        session.commit();
        profiler.stop();
    }

    public void deleteFileSources(String rootUuid) {
        profiler.start("deleteFileSources (file_sources)");
        purgeMapper.deleteFileSourcesByProjectUuid(rootUuid);
        session.commit();
        profiler.stop();
    }

    public void deleteCeActivity(String rootUuid) {
        profiler.start("deleteCeActivity (ce_activity)");
        purgeMapper.deleteCeActivityByProjectUuid(rootUuid);
        session.commit();
        profiler.stop();
    }

    public void deleteCeQueue(String rootUuid) {
        profiler.start("deleteCeQueue (ce_queue)");
        purgeMapper.deleteCeQueueByProjectUuid(rootUuid);
        session.commit();
        profiler.stop();
    }

    public void deleteWebhookDeliveries(String rootUuid) {
        profiler.start("deleteWebhookDeliveries (webhook_deliveries)");
        purgeMapper.deleteWebhookDeliveriesByProjectUuid(rootUuid);
        session.commit();
        profiler.stop();
    }
}