All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.endoscope.storage.gzip.GzipStorage Maven / Gradle / Ivy

The newest version!
package com.github.endoscope.storage.gzip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import com.github.endoscope.core.Stat;
import com.github.endoscope.core.Stats;
import com.github.endoscope.storage.Filters;
import com.github.endoscope.storage.Histogram;
import com.github.endoscope.storage.StatDetails;
import com.github.endoscope.storage.Storage;
import com.github.endoscope.util.JsonUtil;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;

import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Simple gzip file store. Simply dumps whole stats to JSON.
 *
 * Search capabilities are for test/demo purposes rather than for practical use on larger stats.
 */
public class GzipStorage implements Storage {
    private static final Logger log = getLogger(GzipStorage.class);
    private File dir;
    private JsonUtil jsonUtil = new JsonUtil();

    public void setup(String dirName){
        this.dir = toFile(dirName);
        if( dir.exists() && dir.isFile() ){
            throw new RuntimeException("location exists and is a file - cannot use it as storage directory: " + dir.getAbsolutePath());
        }
        if( !dir.exists() && !dir.mkdirs() ){
            throw new RuntimeException("cannot create storage directory: " + dir.getAbsolutePath());
        }
        log.info("Using storage directory: {}", dir.getAbsolutePath());
    }

    private static File toFile(String dir){
        if(dir == null || dir.trim().length() <1){
            throw new IllegalArgumentException("Storage directory cannot be blank");
        }
        return new File(dir);
    }

    @Override
    public String save(Stats stats, String instance, String type) {
        String fileName = new GzipFileInfo(stats.getStartDate(), stats.getEndDate(), instance, type).build();
        try {
            return writeToGzipFile(stats, fileName).getName();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String replace(String statsId, Stats stats, String instance, String type) {
        if( isNotBlank(statsId) ){
            File file = buildFile(statsId);
            if( file.exists() ){
                file.delete();
            }
        }
        return save(stats, instance, type);
    }

    @Override
    public Stats load(String statsId) {
        try {
            return readFromGzipFile(statsId);
        } catch (Exception e) {
            throw new RuntimeException("Failed to read stats with ID: " + statsId, e);
        }
    }

    @Override
    public List find(Date from, Date to, String instance, String type){
        String[] arr = dir.list((dir, name) -> {
            GzipFileInfo info = GzipFileInfo.safeParse(name);
            return info != null && info.match(from, to, instance, type);
        });
        Arrays.sort(arr);
        return Arrays.asList(arr);
    }

    @Override
    public Filters findFilters(Date from, Date to, String type){
        Set types = new HashSet<>();
        Set instances = new HashSet<>();
        dir.list((dir, name) -> {
            GzipFileInfo info = GzipFileInfo.safeParse(name);
            if( info != null && info.match(from, to, null, type)){
                if( info.getInstance() != null ){
                    instances.add(info.getInstance());
                }
                if( info.getType() != null ){
                    types.add(info.getType());
                }
            }
            return false;
        });

        return new Filters(new ArrayList(instances), new ArrayList(types));
    }

    private void processStats(List statsIds, Consumer consumer){
        statsIds.stream()
                .map( statsId -> load(statsId) )
                .filter( stats -> stats != null && stats.getStartDate() != null )
                .sorted( (stats1, stats2) -> stats1.getStartDate().compareTo(stats2.getStartDate()) )
                .forEach( stats -> consumer.accept(stats));
    }

    private Stat getDetailsOrEmpty(String detailsId, Stats stats){
        Map map = stats.getMap();
        if( map != null ){
            Stat stat = map.get(detailsId);
            if( stat != null ){
                return stat;
            }
        }
        return Stat.emptyStat();
    }

    @Override
    public StatDetails loadDetails(String detailsId, List statsIds){
        StatDetails result = new StatDetails(detailsId, null);
        processStats(statsIds, stats -> {
            Stat stat = getDetailsOrEmpty(detailsId, stats);
            result.add(stat);
        });
        return result;
    }

    @Override
    public StatDetails loadDetails(String detailsId, Date from, Date to, String instance, String type){
        List statsIds = find(from, to, instance, type);
        return loadDetails(detailsId, statsIds);
    }

    @Override
    public Histogram loadHistogram(String detailsId, Date from, Date to, String instance, String type, String lastGroupId){
        List statsIds = find(from, to, instance, type);
        Histogram result = new Histogram(detailsId);
        processStats(statsIds, stats -> {
            Stat stat = getDetailsOrEmpty(detailsId, stats);
            result.add(stat, stats.getStartDate(),stats.getEndDate());
        });
        return result;
    }

    @Override
    public Stats loadAggregated(boolean topLevelOnly, Date from, Date to, String instance, String type){
        Stats result = new Stats();
        List statsIds = find(from, to, instance, type);
        if( !statsIds.isEmpty() ){
            statsIds.stream()
                    .map( statsId -> load(statsId) )
                    .forEach( stats -> result.merge(stats, !topLevelOnly ) );
        }
        return result;
    }

    private File buildFile(String fileName){
        return new File( dir.getAbsolutePath() + File.separator + fileName);
    }

    private File writeToGzipFile(Stats stats, String fileName) throws IOException {
        File file = buildFile(fileName);
        OutputStream out = null;
        try {
            out = new GZIPOutputStream(new FileOutputStream(file));
            jsonUtil.toJson(stats, out);
            return file;
        } finally {
            IOUtils.closeQuietly(out);
        }
    }

    private Stats readFromGzipFile(String fileName) throws IOException {
        File file = buildFile(fileName);

        InputStream in = null;
        try {
            in = new GZIPInputStream(new FileInputStream(file));
            return jsonUtil.fromJson(Stats.class, in);
        } catch (FileNotFoundException fnf){
            return null;
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    @Override
    public void cleanup(int daysToKeep, String type) {}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy