/* * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * * This file is part of PeerfactSim.KOM. * * PeerfactSim.KOM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * PeerfactSim.KOM 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PeerfactSim.KOM. If not, see . * */ package de.tud.kom.p2psim.impl.analyzer.metric.filter; import java.util.LinkedList; import java.util.List; import de.tudarmstadt.maki.simonstrator.api.Host; import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; import de.tudarmstadt.maki.simonstrator.api.common.metric.AbstractMetric; import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveMetric; import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveMetric.ActiveMetricListener; import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric; import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricUnit; import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricValue; import de.tudarmstadt.maki.simonstrator.api.common.metric.MetricFilter; /** * Base class of a {@link MetricFilter} * * @author Bjoern Richerzhagen * @version 1.0, 08.08.2012 */ public abstract class AbstractFilter> implements MetricFilter { private final String name; private final LinkedList> incomingMetrics = new LinkedList>(); private final LinkedList> outgoingMetrics = new LinkedList>(); private final LinkedList outgoingActiveMetrics = new LinkedList(); private String[] blacklist = null; private String[] whitelist = null; public AbstractFilter(String name) { this.name = name; } public AbstractFilter() { this.name = getClass().getSimpleName(); } protected boolean inFilter(Metric metric, String[] filter) { for (int i = 0; i < filter.length; i++) { String string = filter[i]; if (metric.getName().equals(string)) { return true; } if (string.endsWith("*")) { // prefix matching String mName = metric.getName(); if (mName.startsWith(string.substring(0, string.length()-1))) { return true; } } if (string.startsWith("*")) { // postfix matching String mName = metric.getName(); if (mName.endsWith(string.substring(1, string.length()))) { return true; } } } return false; } @Override public final void initialize(List> metrics, List hosts) { for (Metric metric : metrics) { if (blacklist != null && inFilter(metric, blacklist)) { continue; } if (whitelist != null && !inFilter(metric, whitelist)) { continue; } incomingMetrics.add(metric); } if (incomingMetrics.isEmpty()) { Monitor.log(getClass(), Level.WARN, "["+this.getName()+"] No incoming metrics configured! Available metrics are: " + metrics.toString(), this); System.err.println("["+this.getName()+"] No incoming metrics configured! Available metrics are: " + metrics.toString() ); return; } onInitialize(incomingMetrics); for (Metric metric : outgoingMetrics) { metric.initialize(hosts); } } /** * Called with the filtered list of metrics. Call createDerivedMetric once * or multiple times in this method! * * @param incomingMetrics */ protected abstract void onInitialize(List> incomingMetrics); /** * Call this to create a derived metric out of the specified metrics * * @param incomingMetrics * all incoming metrics that are used by the resulting metric * @param isOverallMetric * false, if this is a per-host metric * @param unit * Metric unit * @param description * @param isActiveMetric * is this metric active, i.e. does the filter actively update * the metric in defined intervals or on other defined actions */ protected void createDerivedMetric(List> incomingMetrics, boolean isOverallMetric, MetricUnit unit, String description, boolean isActiveMetric) { DerivedMetric m = null; if (isActiveMetric) { DerivedActiveMetric am = new DerivedActiveMetric(this, description, unit, isOverallMetric, incomingMetrics); outgoingActiveMetrics.add(am); m = am; } else { m = new DerivedMetric(this, description, unit, isOverallMetric, incomingMetrics); } outgoingMetrics.add(m); } /** * Create a derived metric out of a single incoming metric. * * @param incomingMetric * @param isOverallMetric * @param unit * @param description * @param isActiveMetric * is this metric active, i.e. does the filter actively update * the metric in defined intervals or on other defined actions */ protected void createDerivedMetric(Metric incomingMetric, boolean isOverallMetric, MetricUnit unit, String description, boolean isActiveMetric) { List> metrics = new LinkedList>(); metrics.add(incomingMetric); createDerivedMetric(metrics, isOverallMetric, unit, description, isActiveMetric); } @Override public final List> getOutputMetrics() { return outgoingMetrics; } @Override public final List> getInputMetrics() { return incomingMetrics; } @Override public String getName() { return name; } /** * This is invoked once for overall metrics and multiple times for per-host * metrics. * * @param derivedMetric * the derived metric * @param inputs * @param host * or null if it is an overall metric * @return */ protected abstract M getDerivedMetricValueFor(Metric derivedMetric, List> inputs, Host host); /** * Class for a derived metric. * * @author Bjoern Richerzhagen * @version 1.0, 08.08.2012 * @param */ private class DerivedMetric extends AbstractMetric { private final List> incoming = new LinkedList>(); private final boolean isOverallMetric; public DerivedMetric(AbstractFilter filter, String description, MetricUnit unit, boolean isOverallMetric, List> incomingMetrics) { super(getNameForDerivedMetric(incomingMetrics), description, unit); this.isOverallMetric = isOverallMetric; incoming.addAll(incomingMetrics); } @Override public void initialize(List hosts) { if (isOverallMetric) { M overall = getDerivedMetricValueFor(DerivedMetric.this, incoming, null); if (overall != null) { setOverallMetric(overall); } } else { for (Host host : hosts) { M perHost = getDerivedMetricValueFor(DerivedMetric.this, incoming, host); if (perHost != null) { addHost(host, perHost); } } } } @Override public boolean isOverallMetric() { return isOverallMetric; } } /** * Class for a derived metric that implements the active metric interface * * @author Bjoern Richerzhagen * @version 1.0, 13.08.2012 */ private class DerivedActiveMetric extends DerivedMetric implements ActiveMetric { private final List listeners; public DerivedActiveMetric(AbstractFilter filter, String description, MetricUnit unit, boolean isOverallMetric, List> incomingMetrics) { super(filter, description, unit, isOverallMetric, incomingMetrics); listeners = new LinkedList(); } @Override public void addActiveMetricListener(ActiveMetricListener listener) { listeners.add(listener); } protected void notifyListenersOfUpdate() { for (ActiveMetricListener listener : listeners) { listener.onMetricUpdate(DerivedActiveMetric.this); } } } /** * Call this to notify all {@link ActiveMetricListener}s of an update of one * or many {@link ActiveMetric}s */ protected void notifyListenersOfUpdate() { for (DerivedActiveMetric am : outgoingActiveMetrics) { am.notifyListenersOfUpdate(); } } /** * Use this to name your derived metric. * * @param inputs * @return */ protected String getNameForDerivedMetric(List> inputs) { String str = getName(); for (Metric metric : inputs) { str += "_" + metric.getName(); } return str; } /** * List of Metrics * * @param blacklist */ public void setBlacklist(String blacklist) { this.blacklist = blacklist.split(";|;\\n"); for (String string : this.blacklist) string = string.replaceAll("\\s+", ""); } public void setWhitelist(String whitelist) { this.whitelist = whitelist.split(";|;\\n"); for (int i = 0; i < this.whitelist.length; i++) this.whitelist[i] = this.whitelist[i].replaceAll("\\s+", ""); } }