org.artifactory.storage.db.binstore.service.FileBinaryProviderBase.java Source code

Java tutorial

Introduction

Here is the source code for org.artifactory.storage.db.binstore.service.FileBinaryProviderBase.java

Source

/*
 * Artifactory is a binaries repository manager.
 * Copyright (C) 2012 JFrog Ltd.
 *
 * Artifactory 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.
 *
 * Artifactory 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 Artifactory.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.artifactory.storage.db.binstore.service;

import org.apache.commons.lang.StringUtils;
import org.artifactory.api.common.MultiStatusHolder;
import org.artifactory.api.storage.StorageUnit;
import org.artifactory.storage.StorageException;
import org.artifactory.storage.StorageProperties;
import org.artifactory.storage.binstore.service.FileBinaryProvider;
import org.artifactory.util.Files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;

/**
 * Date: 12/13/12
 * Time: 7:56 AM
 *
 * @author freds
 */
public abstract class FileBinaryProviderBase extends FileBinaryProviderReadOnlyBase {
    private static final Logger log = LoggerFactory.getLogger(FileBinaryProviderBase.class);

    public FileBinaryProviderBase(File binariesDir) {
        super(binariesDir);
    }

    @Override
    protected void verifyState(File binariesDir) {
        super.verifyState(binariesDir);
        // the pre folder should be writable also
        if (!tempBinariesDir.canWrite()) {
            throw new StorageException(
                    "Temporary pre store folder '" + tempBinariesDir.getAbsolutePath() + "' is not writable!");
        }
    }

    protected static File getDataFolder(File rootDataDir, StorageProperties storageProperties,
            StorageProperties.Key keyProperty, String defaultName) {
        String name = storageProperties.getProperty(keyProperty);
        if (StringUtils.isBlank(name)) {
            return new File(rootDataDir, defaultName);
        }
        File currentFile = new File(name);
        if (currentFile.isAbsolute()) {
            return currentFile;
        }
        return new File(rootDataDir, name);
    }

    @Override
    public boolean delete(String sha1) {
        if (deleteNoChain(sha1)) {
            return next().delete(sha1);
        }
        return false;
    }

    protected boolean deleteNoChain(String sha1) {
        check();
        if (getContext().isActivelyUsed(sha1)) {
            log.info("File {} is read. Deletion is skipped", sha1);
            return false;
        }
        File file = getFile(sha1);
        log.debug("Deleting file {}", file.getAbsolutePath());
        Files.removeFile(file);
        if (file.exists()) {
            log.error("Could not delete file " + file.getAbsolutePath());
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void prune(MultiStatusHolder statusHolder) {
        File binariesFolder = getBinariesDir();
        statusHolder.status("Starting cleaning folder " + binariesFolder.getAbsolutePath(), log);
        long start = System.currentTimeMillis();
        MovedCounter movedCounter = new MovedCounter();

        File[] firstLevel = binariesFolder.listFiles();
        // In case the binaries folder does not contain files, it returns null
        if (firstLevel == null) {
            statusHolder.warn("No files found in folder: " + binariesFolder.getAbsolutePath() + ": "
                    + Files.readFailReason(binariesFolder), log);
        } else {
            // Then prune empty dirs
            statusHolder.status("Starting removing empty folders in " + binariesFolder.getAbsolutePath(), log);
            for (File first : firstLevel) {
                if (first.getName().equals(tempBinariesDir.getName())) {
                    // Never prune temp folder
                    continue;
                }
                // Do the pruning
                pruneFiles(statusHolder, movedCounter, first);
                pruneIfNeeded(statusHolder, movedCounter, first);
            }
        }
        long tt = (System.currentTimeMillis() - start);
        statusHolder.status("Removed " + movedCounter.foldersRemoved + " empty folders and "
                + movedCounter.filesMoved + " files in total size of "
                + StorageUnit.toReadableString(movedCounter.totalSize) + " (" + tt + "ms).", log);
        BinaryProviderBase next = next();
        if (next instanceof FileBinaryProviderBase) {
            ((FileBinaryProvider) next()).prune(statusHolder);
        }
    }

    protected void pruneIfNeeded(MultiStatusHolder statusHolder, MovedCounter movedCounter, File first) {
        File[] files = first.listFiles();
        if (files == null || files.length == 0) {
            if (!first.delete()) {
                statusHolder.warn("Could not remove empty directory " + first.getAbsolutePath(), log);
            } else {
                movedCounter.foldersRemoved++;
            }
        }
    }

    protected abstract void pruneFiles(MultiStatusHolder statusHolder, MovedCounter movedCounter, File first);

    static class MovedCounter {
        long foldersRemoved = 0;
        long filesMoved = 0;
        long totalSize = 0;
    }
}