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

org.epics.graphene.rrdtool.GangliaRrdCluster Maven / Gradle / Ivy

There is a newer version: 0.5
Show newest version
/**
 * Copyright (C) 2012 University of Michigan
 * All rights reserved. Use is subject to license terms.
 */
package org.epics.graphene.rrdtool;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.epics.graphene.Point3DWithLabelDataset;
import org.epics.graphene.Point3DWithLabelDatasets;
import org.epics.util.array.ArrayDouble;
import org.epics.util.array.ListDouble;
import org.epics.util.time.TimeDuration;
import org.epics.util.time.Timestamp;

/**
 *
 * @author carcassi
 */
public class GangliaRrdCluster {
    
    private static Logger log = Logger.getLogger(GangliaRrdCluster.class.getName());
    
    private final File baseDir;
    private Set machines;
    private Set signals;
    private Map> machinesToSignals;
    private Pattern filePattern = rrdFilePattern;
    private Pattern dirPattern = null;
    
    public GangliaRrdCluster(String baseDirectory) {
        log.fine("Reading Ganglia directory at " + baseDirectory);
        baseDir = new File(baseDirectory);
        if (!baseDir.isDirectory()) {
            throw new IllegalArgumentException(baseDirectory + "is not a directory");
        }
        scanDirectory();
        log.finest("Machines " + machines + "\nSignals " + signals);
    }

    public void setDirPattern(Pattern filePattern) {
        this.dirPattern = filePattern;
        scanDirectory();
    }

    public Pattern getDirPattern() {
        return dirPattern;
    }
    
    private static Pattern rrdFilePattern = Pattern.compile(".*\\.rrd", Pattern.CASE_INSENSITIVE);
    
    private void scanDirectory() {
        // All the subdirectories are taken to be machine names
        File[] subdirs = baseDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (!pathname.isDirectory()) {
                    return false;
                }
                if (dirPattern != null && !dirPattern.matcher(pathname.getName()).matches()) {
                    return false;
                }
                return true;
            }
        });
        
        signals = new HashSet<>();
        machines = new HashSet<>();
        machinesToSignals = new HashMap<>();
        
        for (int i = 0; i < subdirs.length; i++) {
            File subdir = subdirs[i];
            String[] rrdFiles = subdir.list(new FilenameFilter() {

                @Override
                public boolean accept(File dir, String name) {
                    return filePattern.matcher(name).matches();
                }
            });
            HashSet machineSignals = new HashSet<>();
            for (int j = 0; j < rrdFiles.length; j++) {
                String rrdFileName = rrdFiles[j];
                String signal = rrdFileName.substring(0, rrdFileName.length() - 4);
                signals.add(signal);
                machineSignals.add(signal);
            }
            String machine = subdir.getName();
            machinesToSignals.put(machine, machineSignals);
            machines.add(machine);
        }
    }

    public Set getMachines() {
        return machines;
    }

    public Set getSignals() {
        return signals;
    }
    
    private RrdToolReader reader = new RrdToolReader();
    
    public Point3DWithLabelDataset dataset(List machineNames, List signals, Timestamp time) {
        if (signals.size() != 3) {
            throw new IllegalArgumentException("3 signal names are required");
        }
        
        if (machineNames.isEmpty()) {
            throw new IllegalArgumentException("Must provide at least one machine");
        }
        
        return Point3DWithLabelDatasets.build(dataset(machineNames, signals.get(0), time),
                dataset(machineNames, signals.get(1), time),
                dataset(machineNames, signals.get(2), time),
                machineNames);
    }
    
    public Point3DWithLabelDataset dataset(List signals, Timestamp time) {
        log.fine("Creating dataset for signals " + signals + " at " + time);
        List machineNames = new ArrayList<>();
        
        for (Map.Entry> entry : machinesToSignals.entrySet()) {
            String machine = entry.getKey();
            Set machineSignals = entry.getValue();
            if (machineSignals.containsAll(signals)) {
                machineNames.add(machine);
            }
        }
        
        return dataset(machineNames, signals, time);
    }
    
    private ListDouble dataset(List machineNames, String signal, Timestamp time) {
        log.fine("Creating dataset for signal " + signal + " on machines " + machineNames + " at " + time);
        double[] values = new double[machineNames.size()];
        for (int i = 0; i < values.length; i++) {
            values[i] = getValue(machineNames.get(i), signal, time);
        }
        return new ArrayDouble(values);
    }
    
    public double getValue(String machine, String signal, Timestamp time) {
        log.fine("Get value for signal " + signals + " on machine " + machine + " at " + time);
        Set machineSignals = machinesToSignals.get(machine);
        if (machineSignals == null || !machineSignals.contains(signal)) {
            return Double.NaN;
        }
        TimeSeriesMulti data = reader.readFile(baseDir.getAbsolutePath() + File.separator + machine + File.separator + signal + ".rrd",
                                           "AVERAGE", time.minus(TimeDuration.ofMinutes(30)), time.plus(TimeDuration.ofMinutes(30)));
        ListDouble series = data.getValues().values().iterator().next();
        List times = data.getTime();
        
        // Get the value that is the one right before the time becomes
        // greater
        int i = 0;
        while (i < times.size() && times.get(i).compareTo(time) <= 0) {
            i++;
        }
        if (i != 0) {
            i--;
        }
        
        return series.getDouble(i);
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy