fr.gael.dhus.datastore.eviction.EvictionManager.java Source code

Java tutorial

Introduction

Here is the source code for fr.gael.dhus.datastore.eviction.EvictionManager.java

Source

/*
 * Data Hub Service (DHuS) - For Space data distribution.
 * Copyright (C) 2013,2014,2015 GAEL Systems
 *
 * This file is part of DHuS software sources.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package fr.gael.dhus.datastore.eviction;

import java.io.File;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import fr.gael.dhus.database.dao.EvictionDao;
import fr.gael.dhus.database.dao.ProductDao;
import fr.gael.dhus.database.object.Eviction;
import fr.gael.dhus.database.object.Product;
import fr.gael.dhus.database.object.config.system.ArchiveConfiguration;
import fr.gael.dhus.datastore.DefaultDataStore;
import fr.gael.dhus.datastore.exception.DataStoreException;
import fr.gael.dhus.system.config.ConfigurationManager;

/**
 * Manages eviction functions
 *
 */
@Service
public class EvictionManager {
    private static Log logger = LogFactory.getLog(EvictionManager.class);

    @Autowired
    private ProductDao productDao;

    @Autowired
    private EvictionDao evictionDao;

    @Autowired
    private DefaultDataStore dataStore;

    @Autowired
    private ConfigurationManager cfgManager;

    private EvictionManager() {
    }

    /**
     * Computes the path to be evicted. If the incoming path has been
     * entered, eviction spaces is managed according to this directory.
     * Otherwise it is computed from the archive data path.
     *
     * @return the path where the eviction is performed.
     */
    private String getPath() {
        ArchiveConfiguration archive = cfgManager.getArchiveConfiguration();
        String path = archive.getIncomingConfiguration().getPath();
        if (path == null)
            path = archive.getPath();
        return path;
    }

    /**
     * Computes the date <i>days</i> days ago.
     *
     * @param days number of days
     * @return a date representation of date <i>days</i> ago.
     */
    public Date getKeepPeriod(int days) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, -days);
        logger.info("Eviction Max date : " + cal.getTime());
        return cal.getTime();
    }

    /**
     * Computes free space on disk where the eviction works.
     *
     * @return number of available bytes on disk partition.
     */
    public long getFreeSpace() {
        String path = getPath();
        File fpath = new File(path);
        return fpath.getFreeSpace();
    }

    /**
     * Computes the total space on disk where the eviction works.
     *
     * @return the total space in byte on disk partition.
     */
    public long getTotalSpace() {
        String path = getPath();
        File fpath = new File(path);
        return fpath.getTotalSpace();
    }

    /**
     * Compute space disk usage on partition where the eviction works.
     *
     * @return space disk usage in bytes on disk partition.
     */
    public long getUsableSpace() {
        String path = getPath();
        File fpath = new File(path);
        return fpath.getUsableSpace();
    }

    /**
     * Compute percentage of usage space disk of eviction partition.
     *
     * @return space disk usage in percent on disk partition.
     * @see EvictionManager#getUsableSpace()
     * @see EvictionManager#getTotalSpace()
     */
    public float getSpaceUsagePercentage() {
        return 100 - (((float) getUsableSpace() / getTotalSpace()) * 100.0f);
    }

    /**
     * Check if the limit of disk usage is exceeded
     *
     * @param eviction eviction system contains the limit of disk usage.
     * @return true if disk usage of <i>eviction</i> is exceeded, otherwise false
     */
    public boolean canEvictFromArchive(Eviction eviction) {
        if ((getSpaceUsagePercentage() > eviction.getMaxDiskUsage()))
            return true;
        return false;
    }

    /**
     * Seeks all products ingested <i>keep_period</i> days ago or more.
     *
     * @param keep_period number of days.
     * @return a iterator of {@link Product}.
     */
    public Iterator<Product> getProductsByIngestionDate(int keep_period) {
        return productDao.getProductsByIngestionDate(getKeepPeriod(keep_period));
    }

    /**
     * Seeks the least watched products on the given period.
     * @param keep_period the period in day.
     * @return a iterator of {@link Product}.
     */
    public Iterator<Product> getProductsByLowestAccess(int keep_period) {
        // FIXME never call
        return productDao.getProductsLowerAccess(getKeepPeriod(keep_period));
    }

    /**
     * Compute of next evictable products
     */
    public void computeNextProducts() {
        Eviction eviction = evictionDao.getEviction();
        if (eviction == null) {
            logger.warn("No Eviction setting found.");
            return;
        }
        Set<Product> products = eviction.getStrategy().getProductsToEvict(eviction);
        evictionDao.setProducts(products);
    }

    /**
     * Returns the next evictable products.
     * @return a set of {@link Product}.
     */
    public Set<Product> getProducts() {
        return evictionDao.getEviction().getProducts();
    }

    /**
     * Performs a eviction of products.
     */
    public void doEvict() {
        Set<Product> products = getProducts();
        evictionDao.setProducts(new HashSet<Product>());
        int evicted = 0;
        if (products != null) {
            evicted = products.size();
            doEvict(products);
        }
        if (evicted == 0) {
            logger.info("No product Evicted.");
        }
    }

    /**
     * Evicts <i>products</i> in a new {@link Thread}
     *
     * @param products set of products to evict.
     */
    public void doEvict(Set<Product> products) {
        Thread t = new Thread(new DeleteProductTask(products), "doEvictionTread");
        t.start();
    }

    private class DeleteProductTask implements Runnable {
        private Set<Product> products;

        public DeleteProductTask(Set<Product> products) {
            this.products = products;
        }

        @Override
        public void run() {
            for (Product product : products) {
                String path = ProductDao.getPathFromProduct(product);
                path = path.replaceAll("file://?", "/");
                logger.info("Trying to evict product \"" + path + "\".");

                try {
                    dataStore.removeProduct(product.getId());
                    logger.info("Evicted " + product.getIdentifier() + " (" + product.getSize() + " bytes, "
                            + product.getDownloadableSize() + " bytes compressed)");
                } catch (DataStoreException e) {
                    logger.error("Unable to delete product at path \"" + path + "\": " + e.getMessage(), e);
                }
            }
        }
    }

}