Commit f6a12e49 authored by Marc Schiller's avatar Marc Schiller
Browse files

Merge remote-tracking branch 'origin/master' into nr/monitoring-model

parents 6275ae2f c2ecb39e
...@@ -20,7 +20,14 @@ ...@@ -20,7 +20,14 @@
package de.tud.kom.p2psim.impl.analyzer.metric.output; package de.tud.kom.p2psim.impl.analyzer.metric.output;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.util.db.dao.DAO; import de.tud.kom.p2psim.impl.util.db.dao.DAO;
...@@ -47,6 +54,8 @@ public class MetricOutputDAO extends AbstractOutput { ...@@ -47,6 +54,8 @@ public class MetricOutputDAO extends AbstractOutput {
protected long timeStopDao = Long.MAX_VALUE; protected long timeStopDao = Long.MAX_VALUE;
protected Set<String> metricsToAggregate = new LinkedHashSet<>();
/** /**
* *
* @param table * @param table
...@@ -72,6 +81,18 @@ public class MetricOutputDAO extends AbstractOutput { ...@@ -72,6 +81,18 @@ public class MetricOutputDAO extends AbstractOutput {
this.timeStopDao = timeStopDao; this.timeStopDao = timeStopDao;
} }
/**
* A list of PER-HOST metrics that are NOT written individually but instead
* statistical figures for a group of hosts is written. The group of hosts
* is defined by the hostGroup from the XML-config.
*
* @param metricsToAggregate
*/
public void setToAggregate(String[] metricsToAggregate) {
for (String metric : metricsToAggregate) {
this.metricsToAggregate.add(metric);
}
}
@Override @Override
public void onInitialize(List<Metric> metrics) { public void onInitialize(List<Metric> metrics) {
...@@ -111,12 +132,27 @@ public class MetricOutputDAO extends AbstractOutput { ...@@ -111,12 +132,27 @@ public class MetricOutputDAO extends AbstractOutput {
private final List<SimHost> hosts; private final List<SimHost> hosts;
private final boolean writeAggregates;
private final Map<String, List<SimHost>> hostsByGroup;
private long timestampLastEvent = -1;
public MetricDaoAdapter(ActiveMetric metric) { public MetricDaoAdapter(ActiveMetric metric) {
this.metric = metric; this.metric = metric;
this.md = new MetricDescription(MetricOutputDAO.class.getName(), this.md = new MetricDescription(MetricOutputDAO.class.getName(),
metric.getName(), metric.getDescription(), metric.getUnit() metric.getName(), metric.getDescription(),
.toString()); metric.getUnit().toString());
this.hosts = GlobalOracle.getHosts(); this.hosts = GlobalOracle.getHosts();
writeAggregates = metricsToAggregate.contains(metric.getName());
this.hostsByGroup = new LinkedHashMap<>();
for (SimHost simHost : hosts) {
String groupId = simHost.getProperties().getGroupID();
if (!this.hostsByGroup.containsKey(groupId)) {
this.hostsByGroup.put(groupId, new LinkedList<>());
}
this.hostsByGroup.get(groupId).add(simHost);
}
} }
@Override @Override
...@@ -139,18 +175,56 @@ public class MetricOutputDAO extends AbstractOutput { ...@@ -139,18 +175,56 @@ public class MetricOutputDAO extends AbstractOutput {
} }
} else { } else {
// per-host metric // per-host metric
for (SimHost host : hosts) { if (writeAggregates) {
MetricValue mv = metric.getPerHostMetric(host.getId()); /*
if (mv != null) { * Write aggregates instead of individual metric values.
Object val = mv.getValue(); * This can be improved w.r.t. performance, but currently we
if (mv.isValid()) { * do not really care.
if (val instanceof Number) { */
double vd = ((Number) val).doubleValue(); // Iterate over groups
if (Double.isNaN(vd)) { for (String group : hostsByGroup.keySet()) {
continue; DescriptiveStatistics stats = new DescriptiveStatistics();
for (SimHost host : hostsByGroup.get(group)) {
MetricValue mv = metric
.getPerHostMetric(host.getId());
if (mv != null) {
Object val = mv.getValue();
if (mv.isValid()) {
if (val instanceof Number) {
double vd = ((Number) val)
.doubleValue();
if (Double.isNaN(vd)) {
continue;
}
// Add value
stats.addValue(vd);
}
}
}
}
// Write Group stats
long observationDuration = Time.getCurrentTime() - timestampLastEvent;
if (timestampLastEvent == -1) {
observationDuration = Time.getCurrentTime() - timeEnableDao;
}
MeasurementDAO.storeGroupStatisticsMeasurement(md,
group, time, stats, observationDuration, false);
}
timestampLastEvent = Time.getCurrentTime();
} else {
for (SimHost host : hosts) {
MetricValue mv = metric.getPerHostMetric(host.getId());
if (mv != null) {
Object val = mv.getValue();
if (mv.isValid()) {
if (val instanceof Number) {
double vd = ((Number) val).doubleValue();
if (Double.isNaN(vd)) {
continue;
}
dao.storeSingleMeasurement(md,
host.getHostId(), time, vd);
} }
dao.storeSingleMeasurement(md,
host.getHostId(), time, vd);
} }
} }
} }
......
...@@ -28,6 +28,8 @@ import javax.persistence.EntityManager; ...@@ -28,6 +28,8 @@ import javax.persistence.EntityManager;
import org.hibernate.Session; import org.hibernate.Session;
import de.tud.kom.p2psim.impl.util.db.metric.CustomMeasurement; import de.tud.kom.p2psim.impl.util.db.metric.CustomMeasurement;
import de.tud.kom.p2psim.impl.util.db.metric.GroupMetric;
import de.tud.kom.p2psim.impl.util.db.metric.GroupMetricBound;
import de.tud.kom.p2psim.impl.util.db.metric.HostMetric; import de.tud.kom.p2psim.impl.util.db.metric.HostMetric;
import de.tud.kom.p2psim.impl.util.db.metric.HostMetricBound; import de.tud.kom.p2psim.impl.util.db.metric.HostMetricBound;
import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
...@@ -98,6 +100,15 @@ public class CommitThread implements Runnable { ...@@ -98,6 +100,15 @@ public class CommitThread implements Runnable {
((HostMetricBound) persist).setHostMetric(foundMetric); ((HostMetricBound) persist).setHostMetric(foundMetric);
} }
} }
}
if (persist instanceof GroupMetricBound) {
GroupMetric metric = ((GroupMetricBound) persist).getGroupMetric();
if (metric != null) {
GroupMetric foundMetric = (GroupMetric) s.get(GroupMetric.class, metric.getId());
if (foundMetric != null) {
((GroupMetricBound) persist).setGroupMetric(foundMetric);
}
}
} }
// log.info("Persisting " + persist); // log.info("Persisting " + persist);
s.persist(persist); s.persist(persist);
......
...@@ -40,12 +40,15 @@ import org.omg.CORBA.CustomMarshal; ...@@ -40,12 +40,15 @@ import org.omg.CORBA.CustomMarshal;
import de.tud.kom.p2psim.impl.util.db.metric.CustomMeasurement; import de.tud.kom.p2psim.impl.util.db.metric.CustomMeasurement;
import de.tud.kom.p2psim.impl.util.db.metric.Experiment; import de.tud.kom.p2psim.impl.util.db.metric.Experiment;
import de.tud.kom.p2psim.impl.util.db.metric.GroupMetric;
import de.tud.kom.p2psim.impl.util.db.metric.GroupMetricBound;
import de.tud.kom.p2psim.impl.util.db.metric.HostMetric; import de.tud.kom.p2psim.impl.util.db.metric.HostMetric;
import de.tud.kom.p2psim.impl.util.db.metric.HostMetricBound; import de.tud.kom.p2psim.impl.util.db.metric.HostMetricBound;
import de.tud.kom.p2psim.impl.util.db.metric.Measurement; import de.tud.kom.p2psim.impl.util.db.metric.Measurement;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPair; import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPair;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPairList; import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPairList;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSingle; import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSingle;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementStatistic;
import de.tud.kom.p2psim.impl.util.db.metric.Metric; import de.tud.kom.p2psim.impl.util.db.metric.Metric;
import de.tud.kom.p2psim.impl.util.db.metric.MetricDescription; import de.tud.kom.p2psim.impl.util.db.metric.MetricDescription;
import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
...@@ -146,10 +149,13 @@ public class DAO { ...@@ -146,10 +149,13 @@ public class DAO {
cfg.addAnnotatedClass(Experiment.class); cfg.addAnnotatedClass(Experiment.class);
cfg.addAnnotatedClass(HostMetric.class); cfg.addAnnotatedClass(HostMetric.class);
cfg.addAnnotatedClass(HostMetricBound.class); cfg.addAnnotatedClass(HostMetricBound.class);
cfg.addAnnotatedClass(GroupMetric.class);
cfg.addAnnotatedClass(GroupMetricBound.class);
cfg.addAnnotatedClass(Measurement.class); cfg.addAnnotatedClass(Measurement.class);
cfg.addAnnotatedClass(MeasurementPair.class); cfg.addAnnotatedClass(MeasurementPair.class);
cfg.addAnnotatedClass(MeasurementPairList.class); cfg.addAnnotatedClass(MeasurementPairList.class);
cfg.addAnnotatedClass(MeasurementSingle.class); cfg.addAnnotatedClass(MeasurementSingle.class);
cfg.addAnnotatedClass(MeasurementStatistic.class);
cfg.addAnnotatedClass(Metric.class); cfg.addAnnotatedClass(Metric.class);
cfg.addAnnotatedClass(MetricDescription.class); cfg.addAnnotatedClass(MetricDescription.class);
...@@ -350,17 +356,33 @@ public class DAO { ...@@ -350,17 +356,33 @@ public class DAO {
} }
/** /**
* Wait for all queue committing threads to finish. * Wait for all queue committing threads to finish AND close the session
* factory.
*/ */
public static void finishCommits() { public static void finishCommits() {
waitForCommitsToFinish();
if (sessionFactory != null) {
sessionFactory.close();
}
StandardServiceRegistryBuilder.destroy(serviceRegistry);
Monitor.log(DAO.class, Level.INFO, "commit threads finished. \n stored "
+ objectCount + " objects in " + commitCount
+ " threaded transactions taking " + commitTime + " ms");
}
/**
* Basically the same as finishCommits(), but without closing the session
* factory.
*/
public static void waitForCommitsToFinish() {
while (!threads.isEmpty()) { while (!threads.isEmpty()) {
Thread thread = threads.peek(); Thread thread = threads.peek();
try { try {
Monitor.log(DAO.class, Level.INFO, "Waiting for thread " Monitor.log(DAO.class, Level.INFO, "Waiting for thread "
+ thread.getName() + " to finish"); + thread.getName() + " to finish");
thread.join(); thread.join();
Monitor.log(DAO.class, Level.INFO, "Thread " + thread.getName() Monitor.log(DAO.class, Level.INFO,
+ " finished"); "Thread " + thread.getName() + " finished");
} catch (InterruptedException e) { } catch (InterruptedException e) {
Monitor.log(DAO.class, Level.WARN, Monitor.log(DAO.class, Level.WARN,
"got interrupted while waiting for commit threads"); "got interrupted while waiting for commit threads");
...@@ -368,14 +390,6 @@ public class DAO { ...@@ -368,14 +390,6 @@ public class DAO {
} }
threads.poll(); threads.poll();
} }
if (sessionFactory != null) {
sessionFactory.close();
}
StandardServiceRegistryBuilder.destroy(serviceRegistry);
Monitor.log(DAO.class, Level.INFO,
"commit threads finished. \n stored " + objectCount
+ " objects in " + commitCount
+ " threaded transactions taking " + commitTime + " ms");
} }
/** /**
......
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
package de.tud.kom.p2psim.impl.util.db.dao.metric; package de.tud.kom.p2psim.impl.util.db.dao.metric;
import java.util.Date; import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.impl.simengine.Simulator; import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.util.db.dao.DAO; import de.tud.kom.p2psim.impl.util.db.dao.DAO;
...@@ -61,13 +65,20 @@ public class ExperimentDAO extends DAO { ...@@ -61,13 +65,20 @@ public class ExperimentDAO extends DAO {
long seed = Simulator.getSeed(); long seed = Simulator.getSeed();
String system = Simulator.getInstance().getConfigurator() String system = Simulator.getInstance().getConfigurator()
.getResolvedConfiguration(); .getResolvedConfiguration();
// FIXME: The following has to be uncommented again. Map<String, String> vars = new LinkedHashMap<>(Simulator.getInstance().getConfigurator()
// String workload = Simulator.getInstance().getConfigurator() .getVariables());
// .getVariables().toString(); // Remove seed for database copy
List<String> keys = new LinkedList<>(vars.keySet());
for (String key : keys) {
if (key.equalsIgnoreCase("seed")) {
vars.remove(key);
}
}
String workload = vars.toString();
String experimentDescription = Simulator.getMonitor() String experimentDescription = Simulator.getMonitor()
.getExperimentDescription(); .getExperimentDescription();
experiment = new Experiment(seed, actTime, experimentDescription, experiment = new Experiment(seed, actTime, experimentDescription,
system, ""); system, workload);
persistImmediately(experiment); persistImmediately(experiment);
} }
......
/*
* 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 <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.util.db.dao.metric;
import java.util.HashMap;
import java.util.Map;
import de.tud.kom.p2psim.impl.util.db.dao.DAO;
import de.tud.kom.p2psim.impl.util.db.metric.GroupMetric;
import de.tud.kom.p2psim.impl.util.db.metric.Metric;
public class GroupMetricDAO extends DAO {
/** Cache of {@link GroupMetric} objects to avoid database lookups. */
private static Map<Metric, Map<String, GroupMetric>> groupMetricCache = new HashMap<Metric, Map<String, GroupMetric>>();
/**
* Retrieve the {@link GroupMetric} object for the given metric and group
* name.
*
* If there is no matching Metric object, it is created, persisted, and
* cached automatically.
*/
public static GroupMetric lookupGroupMetric(Metric metric,
String groupName) {
Map<String, GroupMetric> metricMap = groupMetricCache.get(metric);
if (metricMap == null) {
metricMap = new HashMap<String, GroupMetric>();
groupMetricCache.put(metric, metricMap);
}
GroupMetric gm = metricMap.get(groupName);
if (gm == null) {
gm = new GroupMetric(metric, groupName);
metricMap.put(groupName, gm);
addToPersistQueue(gm);
// TODO: block commit and avoid multiple threads for commit of first
// object definition
commitQueue();
}
return gm;
}
}
...@@ -68,8 +68,7 @@ public class HostMetricDAO extends DAO { ...@@ -68,8 +68,7 @@ public class HostMetricDAO extends DAO {
// TODO: block commit and avoid multiple threads for commit of first // TODO: block commit and avoid multiple threads for commit of first
// object definition // object definition
commitQueue(); commitQueue();
// finishCommits(); waitForCommitsToFinish();
} }
return metricMap.get(hostId); return metricMap.get(hostId);
......
...@@ -22,23 +22,27 @@ package de.tud.kom.p2psim.impl.util.db.dao.metric; ...@@ -22,23 +22,27 @@ package de.tud.kom.p2psim.impl.util.db.dao.metric;
import java.util.List; import java.util.List;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import de.tud.kom.p2psim.impl.util.db.dao.DAO; import de.tud.kom.p2psim.impl.util.db.dao.DAO;
import de.tud.kom.p2psim.impl.util.db.metric.CustomMeasurement; import de.tud.kom.p2psim.impl.util.db.metric.CustomMeasurement;
import de.tud.kom.p2psim.impl.util.db.metric.GroupMetric;
import de.tud.kom.p2psim.impl.util.db.metric.HostMetric; import de.tud.kom.p2psim.impl.util.db.metric.HostMetric;
import de.tud.kom.p2psim.impl.util.db.metric.Measurement; import de.tud.kom.p2psim.impl.util.db.metric.Measurement;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPair; import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPair;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPairList; import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPairList;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSingle; import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSingle;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementStatistic;
import de.tud.kom.p2psim.impl.util.db.metric.Metric; import de.tud.kom.p2psim.impl.util.db.metric.Metric;
import de.tud.kom.p2psim.impl.util.db.metric.MetricDescription; import de.tud.kom.p2psim.impl.util.db.metric.MetricDescription;
import de.tud.kom.p2psim.impl.util.stats.StatisticComputation; import de.tud.kom.p2psim.impl.util.stats.StatisticComputation;
/** This class provides methods to persist measurements in a database. /**
* This class provides methods to persist measurements in a database.
* *
* Please use only this class to store measurements with the * Please use only this class to store measurements with the existing database
* existing database structure. The other DAOs ({@link ExperimentDAO}, * structure. The other DAOs ({@link ExperimentDAO}, {@link MetricDAO}, and
* {@link MetricDAO}, and {@link HostMetricDAO}) will be called by * {@link HostMetricDAO}) will be called by this class for the right mapping.
* this class for the right mapping.
* *
* @author Christoph Muenker * @author Christoph Muenker
* @author Andreas Hemel * @author Andreas Hemel
...@@ -49,21 +53,23 @@ public class MeasurementDAO extends DAO { ...@@ -49,21 +53,23 @@ public class MeasurementDAO extends DAO {
* The Host ID that is used for global metrics. * The Host ID that is used for global metrics.
*/ */
private static final long GLOBAL_HOST_ID = -1; private static final long GLOBAL_HOST_ID = -1;
private static boolean inactive = false; private static boolean inactive = false;
public static void storeCustomMeasurement(MetricDescription metricDesc, long hostId, long time, CustomMeasurement measurement) { public static void storeCustomMeasurement(MetricDescription metricDesc,
if (inactive) return; long hostId, long time, CustomMeasurement measurement) {
if (inactive)
return;
Metric metric = MetricDAO.lookupSingleMetric(metricDesc); Metric metric = MetricDAO.lookupSingleMetric(metricDesc);
HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId); HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId);
measurement.setTime(time); measurement.setTime(time);
measurement.setHostMetric(hostMetric); measurement.setHostMetric(hostMetric);
addToPersistQueue(measurement); addToPersistQueue(measurement);
} }
public static void setInactive(boolean inactive) { public static void setInactive(boolean inactive) {
MeasurementDAO.inactive = inactive; MeasurementDAO.inactive = inactive;
} }
...@@ -83,13 +89,16 @@ public class MeasurementDAO extends DAO { ...@@ -83,13 +89,16 @@ public class MeasurementDAO extends DAO {
* @param value * @param value
* The measurement to this metric. * The measurement to this metric.
*/ */
public static void storeSingleMeasurement(MetricDescription metricDesc, long hostId, long time, double value) { public static void storeSingleMeasurement(MetricDescription metricDesc,
if (inactive) return; long hostId, long time, double value) {
if (inactive)
return;
Metric metric = MetricDAO.lookupSingleMetric(metricDesc); Metric metric = MetricDAO.lookupSingleMetric(metricDesc);
HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId); HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId);
MeasurementSingle measurement = new MeasurementSingle(time, value, hostMetric); MeasurementSingle measurement = new MeasurementSingle(time, value,
hostMetric);
addToPersistQueue(measurement); addToPersistQueue(measurement);
} }
...@@ -117,17 +126,49 @@ public class MeasurementDAO extends DAO { ...@@ -117,17 +126,49 @@ public class MeasurementDAO extends DAO {
* @param min * @param min
* The minimum value of the measurements * The minimum value of the measurements
*/ */
public static void storeMeasurement(MetricDescription metricDesc, long hostId, public static void storeMeasurement(MetricDescription metricDesc,
long time, double sum, double sum2, int count, double max, double min) { long hostId, long time, double sum, double sum2, int count,
if (inactive) return; double max, double min) {
if (inactive)
return;
Metric metric = MetricDAO.lookupSingleMetric(metricDesc); Metric metric = MetricDAO.lookupSingleMetric(metricDesc);
HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId); HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId);
Measurement measurement = new Measurement(time, count, sum, sum2, min, max, hostMetric); Measurement measurement = new Measurement(time, count, sum, sum2, min,
max, hostMetric);
addToPersistQueue(measurement);
}
/**
* Stores a statistical description of a series of values for group of
* hosts.
*
* @param metricDesc
* The {@link MetricDescription} which describes the metric.
* @param groupName
* The host group
* @param time
* A time for the measurement in simulation time
* @param stats
* the {@link DescriptiveStatistics} object used as input
* @param observationDuration
* duration of this observation in simulation time
* @param describesWholeSimulation
* true, if this measurement is a description of the WHOLE
* simulation
*/
public static void storeGroupStatisticsMeasurement(
MetricDescription metricDesc, String groupName, long time,
DescriptiveStatistics stats, long observationDuration,
boolean describesWholeSimulation) {
Metric metric = MetricDAO.lookupStatisticsMetric(metricDesc);
GroupMetric groupMetric = GroupMetricDAO.lookupGroupMetric(metric,
groupName);
MeasurementStatistic measurement = new MeasurementStatistic(time, stats,
groupMetric, observationDuration, describesWholeSimulation);
addToPersistQueue(measurement); addToPersistQueue(measurement);
} }
/** /**
* Store a list-based measurement with a key (i.e., as a * Store a list-based measurement with a key (i.e., as a
* {@link MeasurementPairList}). * {@link MeasurementPairList}).
...@@ -143,15 +184,15 @@ public class MeasurementDAO extends DAO { ...@@ -143,15 +184,15 @@ public class MeasurementDAO extends DAO {
* @param min * @param min
*/ */
public static void storePairListMeasurement(MetricDescription metricDesc, public static void storePairListMeasurement(MetricDescription metricDesc,
long hostId, long time, int key, double sum, double sum2, long hostId, long time, int key, double sum, double sum2, int count,
int count, double max, double min) { double max, double min) {
Metric metric = MetricDAO.lookupPairListMetric(metricDesc); Metric metric = MetricDAO.lookupPairListMetric(metricDesc);
HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId); HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId);
MeasurementPairList measurement = new MeasurementPairList(time, key, MeasurementPairList measurement = new MeasurementPairList(time, key,
count, sum, sum2, min, max, hostMetric); count, sum, sum2, min, max, hostMetric);
addToPersistQueue(measurement); addToPersistQueue(measurement);
} }
/** /**
* Shortcut for {@link MeasurementPairList} metrics based on a single list. * Shortcut for {@link MeasurementPairList} metrics based on a single list.
* *
...@@ -174,7 +215,7 @@ public class MeasurementDAO extends DAO { ...@@ -174,7 +215,7 @@ public class MeasurementDAO extends DAO {
StatisticComputation.max(values), StatisticComputation.max(values),
StatisticComputation.min(values)); StatisticComputation.min(values));
} }
/** /**
* Store a measurement for table {@link MeasurementPair}. It contains the * Store a measurement for table {@link MeasurementPair}. It contains the
* metric description, a hostId, the timestamp of the measurement in * metric description, a hostId, the timestamp of the measurement in
...@@ -196,7 +237,8 @@ public class MeasurementDAO extends DAO { ...@@ -196,7 +237,8 @@ public class MeasurementDAO extends DAO {
long hostId, long time, int key, double value) { long hostId, long time, int key, double value) {
Metric metric = MetricDAO.lookupPairMetric(metricDesc); Metric metric = MetricDAO.lookupPairMetric(metricDesc);
HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId); HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId);
MeasurementPair measurement = new MeasurementPair(time, key, value, hostMetric); MeasurementPair measurement = new MeasurementPair(time, key, value,
hostMetric);
addToPersistQueue(measurement); addToPersistQueue(measurement);
} }
...@@ -215,14 +257,15 @@ public class MeasurementDAO extends DAO { ...@@ -215,14 +257,15 @@ public class MeasurementDAO extends DAO {
* @param values * @param values
* A series of measurements, which should be not null! * A series of measurements, which should be not null!
*/ */
public static void storeListMeasurement(MetricDescription metric, long hostId, long time, List<Double> values) { public static void storeListMeasurement(MetricDescription metric,
if (inactive) return; long hostId, long time, List<Double> values) {
if (inactive)
return;
if (values == null) if (values == null)
throw new AssertionError("The list with values should be not null"); throw new AssertionError("The list with values should be not null");
storeMeasurement(metric, hostId, time, storeMeasurement(metric, hostId, time, StatisticComputation.sum(values),
StatisticComputation.sum(values),
StatisticComputation.sum2(values), values.size(), StatisticComputation.sum2(values), values.size(),
StatisticComputation.max(values), StatisticComputation.max(values),
StatisticComputation.min(values)); StatisticComputation.min(values));
...@@ -249,11 +292,14 @@ public class MeasurementDAO extends DAO { ...@@ -249,11 +292,14 @@ public class MeasurementDAO extends DAO {
* @param min * @param min
* The minimum value of the measurements * The minimum value of the measurements
*/ */
public static void storeGlobalMeasurement(MetricDescription metric, long time, public static void storeGlobalMeasurement(MetricDescription metric,
double sum, double sum2, int count, double max, double min) { long time, double sum, double sum2, int count, double max,
if (inactive) return; double min) {
if (inactive)
storeMeasurement(metric, GLOBAL_HOST_ID, time, sum, sum2, count, max, min); return;
storeMeasurement(metric, GLOBAL_HOST_ID, time, sum, sum2, count, max,
min);
} }
/** /**
...@@ -272,13 +318,14 @@ public class MeasurementDAO extends DAO { ...@@ -272,13 +318,14 @@ public class MeasurementDAO extends DAO {
* @param value * @param value
* The measurement to this metric. * The measurement to this metric.
*/ */
public static void storeGlobalSingleMeasurement(MetricDescription metric, long time, double value) { public static void storeGlobalSingleMeasurement(MetricDescription metric,
if (inactive) return; long time, double value) {
if (inactive)
return;
storeSingleMeasurement(metric, GLOBAL_HOST_ID, time, value); storeSingleMeasurement(metric, GLOBAL_HOST_ID, time, value);
} }
/** /**
* Store a measurement for table {@link MeasurementPair}. It contains the * Store a measurement for table {@link MeasurementPair}. It contains the
* metric description, a hostId, the timestamp of the measurement in * metric description, a hostId, the timestamp of the measurement in
...@@ -295,7 +342,8 @@ public class MeasurementDAO extends DAO { ...@@ -295,7 +342,8 @@ public class MeasurementDAO extends DAO {
* @param value * @param value
* The double value * The double value
*/ */
public static void storeGlobalPairMeasurement(MetricDescription metric, long time, int key, double value) { public static void storeGlobalPairMeasurement(MetricDescription metric,
long time, int key, double value) {
storePairMeasurement(metric, GLOBAL_HOST_ID, time, key, value); storePairMeasurement(metric, GLOBAL_HOST_ID, time, key, value);
} }
...@@ -314,9 +362,11 @@ public class MeasurementDAO extends DAO { ...@@ -314,9 +362,11 @@ public class MeasurementDAO extends DAO {
* @param values * @param values
* A series of measurements, which should be not null! * A series of measurements, which should be not null!
*/ */
public static void storeGlobalListMeasurement(MetricDescription metric, long time, List<Double> values) { public static void storeGlobalListMeasurement(MetricDescription metric,
if (inactive) return; long time, List<Double> values) {
if (inactive)
return;
storeListMeasurement(metric, GLOBAL_HOST_ID, time, values); storeListMeasurement(metric, GLOBAL_HOST_ID, time, values);
} }
} }
...@@ -31,7 +31,7 @@ public class MetricDAO extends DAO { ...@@ -31,7 +31,7 @@ public class MetricDAO extends DAO {
/** /**
* Identifier for an aggregate metric * Identifier for an aggregate metric
*/ */
AGGREGATE, PAIR, PAIRLIST AGGREGATE, PAIR, PAIRLIST, STATISTICS
} }
/** Retrieve a {@link Metric} object for the given MetricDescription and MetricType. /** Retrieve a {@link Metric} object for the given MetricDescription and MetricType.
...@@ -93,4 +93,14 @@ public class MetricDAO extends DAO { ...@@ -93,4 +93,14 @@ public class MetricDAO extends DAO {
public static Metric lookupAggregateMetric(MetricDescription metricDesc){ public static Metric lookupAggregateMetric(MetricDescription metricDesc){
return lookupMetric(metricDesc, MetricType.AGGREGATE); return lookupMetric(metricDesc, MetricType.AGGREGATE);
} }
/** Retrieve a {@link Metric} object for the given MetricDescription
* for statistics value metrics.
*
* If there is no matching Metric object, it is created, persisted, and cached
* automatically.
*/
public static Metric lookupStatisticsMetric(MetricDescription metricDesc){
return lookupMetric(metricDesc, MetricType.STATISTICS);
}
} }
/*
* 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 <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.util.db.metric;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "groupmetrics", indexes = {
@Index(columnList = "id", name = "id"),
@Index(columnList = "groupName", name = "groupName"),
@Index(columnList = "metricId", name = "metricId") })
/**
* Assign a metric measurement to a group of hosts instead of single hosts or
* global.
*
* @author Bjoern Richerzhagen
* @version 1.0, Jan 30, 2017
*/
public class GroupMetric {
@Id
@GeneratedValue
private int id;
/**
* GroupName of the host
*/
@Column(length = 1023)
private String groupName;
@ManyToOne
@JoinColumn(name = "metricId")
private Metric metric;
protected GroupMetric() {
}
public GroupMetric(Metric metric, String groupName) {
this.metric = metric;
this.groupName = groupName;
}
public String getGroupName() {
return this.groupName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((groupName == null) ? 0 : groupName.hashCode());
result = prime * result + ((metric == null) ? 0 : metric.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GroupMetric other = (GroupMetric) obj;
if (groupName == null) {
if (other.groupName != null)
return false;
} else if (!groupName.equals(other.groupName))
return false;
if (metric == null) {
if (other.metric != null)
return false;
} else if (!metric.equals(other.metric))
return false;
return true;
}
@Override
public String toString() {
return "GroupMetric{" +
"id=" + id +
", group=" + groupName +
", metric=" + metric +
'}';
}
public int getId() {
return id;
}
}
/*
* 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 <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.util.db.metric;
public interface GroupMetricBound {
public GroupMetric getGroupMetric();
public void setGroupMetric(GroupMetric metric);
}
/*
* 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 <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.util.db.metric;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
/**
*
* Statistical representation of a series of measurements in the database,
* intended to capture all relevant metrics for boxplots.
*
* @author Bjoern Richerzhagen
*/
@Entity
@Table(name = "measurements_statistics", indexes = {
@Index(columnList = "id", name = "id") })
public class MeasurementStatistic implements GroupMetricBound {
/**
* The id of this table
*/
@Id
@GeneratedValue
private int id;
/**
* The simulation time for to this measurement in simulator time, that is,
* microseconds.
*/
@Column(nullable = true, name = "[time]")
private long time;
@Column(nullable = false, name = "[describesWholeSimulation]")
private boolean describesWholeSimulation;
/**
* The simulation time for to this measurement in simulator time, that is,
* microseconds.
*/
@Column(nullable = true, name = "[observationDuration]")
private long observationDuration;
/**
* The number of values
*/
@Column(nullable = true, name = "[values]")
private Double values;
@Column(nullable = true, name = "[sum]")
private Double sum;
@Column(nullable = true, name = "[sum2]")
private Double sum2;
/**
* The minimum of all values for this measurement
*/
@Column(nullable = true, name = "[min]")
private Double min;
/**
* The maximum of all values for this measurement
*/
@Column(nullable = true, name = "[max]")
private Double max;
@Column(nullable = true, name = "[mean]")
private Double mean;
@Column(nullable = true, name = "[median]")
private Double median;
@Column(nullable = true, name = "[perc25]")
private Double perc25;
@Column(nullable = true, name = "[perc75]")
private Double perc75;
@Column(nullable = true, name = "[perc97]")
private Double perc97; // 97,7
@Column(nullable = true, name = "[perc2]")
private Double perc2; // 2,3
@Column(nullable = true, name = "[perc95]")
private Double perc95; // 95
@Column(nullable = true, name = "[perc5]")
private Double perc5; // 5
@Column(nullable = true, name = "[skewness]")
private Double skewness;
@Column(nullable = true, name = "[kurtosis]")
private Double kurtosis;
/**
* Mapping to group metric
*/
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "groupMetricId")
GroupMetric groupMetric;
/**
* Creates a {@link Measurement}-Object using the provided
* {@link DescriptiveStatistics} object.
*
* @param time
* The simulation time for to this measurement as Date
* @param stats
* the {@link DescriptiveStatistics} object
* @param hostMetric
* The reference to the {@link HostMetric}-Object, which
* describes this metric. Is used for the mapping.
* @param observationDuration
* duration of the observation
* @param describesWholeSimulation
* true, if this measurement describes the whole simulation
*/
public MeasurementStatistic(long time, DescriptiveStatistics stats,
GroupMetric groupMetric, long observationDuration,
boolean describesWholeSimulation) {
this(time, stats, observationDuration, describesWholeSimulation);
this.groupMetric = groupMetric;
}
/**
* Internal - write statistics
*
* @param time
* @param stats
* @param observationDuration
* duration covered by this measurement in simulation units
*/
private MeasurementStatistic(long time, DescriptiveStatistics stats,
long observationDuration, boolean describesWholeSimulation) {
super();
this.time = time;
this.observationDuration = observationDuration;
this.describesWholeSimulation = describesWholeSimulation;
this.values = checkForSpecialNumbers((double) stats.getN());
this.sum = checkForSpecialNumbers(stats.getSum());
this.sum2 = checkForSpecialNumbers(stats.getSumsq());
this.min = checkForSpecialNumbers(stats.getMin());
this.max = checkForSpecialNumbers(stats.getMax());
this.mean = checkForSpecialNumbers(stats.getMean());
this.median = checkForSpecialNumbers(stats.getPercentile(50));
this.perc2 = checkForSpecialNumbers(stats.getPercentile(2.3));
this.perc25 = checkForSpecialNumbers(stats.getPercentile(25));
this.perc75 = checkForSpecialNumbers(stats.getPercentile(75));
this.perc97 = checkForSpecialNumbers(stats.getPercentile(97.7));
this.perc5 = checkForSpecialNumbers(stats.getPercentile(5));
this.perc95 = checkForSpecialNumbers(stats.getPercentile(95));
this.skewness = checkForSpecialNumbers(stats.getSkewness());
this.kurtosis = checkForSpecialNumbers(stats.getKurtosis());
}
/**
* Check for special numbers, like infinity or NaN. If the given value is
* equals this numbers then will be return null, otherwise will be returned
* the given value.
*
* @param value
* The value, which should be checked.
* @return The value or null, if it is a special number.
*/
private Double checkForSpecialNumbers(Double value) {
if (value == null)
return value;
if (value.equals(Double.NEGATIVE_INFINITY)
|| value.equals(Double.POSITIVE_INFINITY)
|| value.equals(Double.NaN)) {
return null;
} else {
return value;
}
}
@Override
public GroupMetric getGroupMetric() {
return groupMetric;
}
@Override
public void setGroupMetric(GroupMetric metric) {
this.groupMetric = metric;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment