Commit b3c75941 authored by Tobias Meuser's avatar Tobias Meuser
Browse files

Implemented abstract spatial plot functionality

parent 4a2e7fa0
......@@ -2,17 +2,17 @@
* 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/>.
*
......@@ -37,6 +37,9 @@ import de.tud.kom.p2psim.impl.util.db.metric.MetricDescription;
import de.tud.kom.p2psim.impl.util.oracle.GlobalOracle;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveMetric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveSpatialMetric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveSpatialMetric.ActiveSpatialMetricListener;
import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveSpatialMetric.SpatialMetricValue;
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.MetricValue;
......@@ -45,7 +48,7 @@ import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* This class maps {@link Metric}s to calls to the DAO on regular intervals or
* special actions.
*
*
* @author Bjoern Richerzhagen
* @version 1.0, 13.08.2012
*/
......@@ -57,10 +60,10 @@ public class MetricOutputDAO extends AbstractOutput {
protected Set<String> metricsToAggregate = new LinkedHashSet<>();
protected List<MetricDaoAdapter> daoAdapters = new LinkedList<>();
protected List<DaoAdapter> daoAdapters = new LinkedList<>();
/**
*
*
* @param table
*/
@XMLConfigurableConstructor({ "table" })
......@@ -88,7 +91,7 @@ public class MetricOutputDAO extends AbstractOutput {
* 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) {
......@@ -96,7 +99,7 @@ public class MetricOutputDAO extends AbstractOutput {
this.metricsToAggregate.add(metric);
}
}
public boolean isToAggregate(Metric metric) {
for (String string : metricsToAggregate) {
if (metric.getName().equals(string)) {
......@@ -133,12 +136,18 @@ public class MetricOutputDAO extends AbstractOutput {
am.addActiveMetricListener(adapter);
daoAdapters.add(adapter);
}
if (metric instanceof ActiveSpatialMetric) {
ActiveSpatialMetric asm = (ActiveSpatialMetric) metric;
SpatialMetricDaoAdapter adapter = new SpatialMetricDaoAdapter(asm);
asm.addActiveSpatialMetricListener(adapter);
daoAdapters.add(adapter);
}
}
}
@Override
public void onStop() {
for (MetricDaoAdapter adapter : daoAdapters) {
for (DaoAdapter adapter : daoAdapters) {
adapter.onStop();
}
/*
......@@ -147,145 +156,236 @@ public class MetricOutputDAO extends AbstractOutput {
DAO.commitQueue();
}
/**
* This class helps in persisting a metric using the {@link MeasurementDAO}
*
* @author Bjoern Richerzhagen
* @version 1.0, 13.08.2012
*/
private class MetricDaoAdapter implements ActiveMetricListener {
private final ActiveMetric metric;
private final MetricDescription md;
private final MeasurementDAO dao = new MeasurementDAO();
private final List<SimHost> hosts;
private final boolean writeAggregates;
private final Map<String, List<SimHost>> hostsByGroup;
private final Map<String, DescriptiveStatistics> globalStatsByGroup;
private long timestampLastEvent = -1;
public MetricDaoAdapter(ActiveMetric metric) {
this.metric = metric;
this.md = new MetricDescription(MetricOutputDAO.class.getName(),
metric.getName(), metric.getDescription(),
metric.getUnit().toString());
this.hosts = GlobalOracle.getHosts();
this.writeAggregates = isToAggregate(metric);
this.hostsByGroup = new LinkedHashMap<>();
this.globalStatsByGroup = new LinkedHashMap<>();
for (SimHost simHost : hosts) {
String groupId = simHost.getProperties().getGroupID();
if (!this.hostsByGroup.containsKey(groupId)) {
this.hostsByGroup.put(groupId, new LinkedList<>());
this.globalStatsByGroup.put(groupId,
new DescriptiveStatistics());
}
this.hostsByGroup.get(groupId).add(simHost);
}
}
public void onStop() {
if (writeAggregates) {
for (Entry<String, DescriptiveStatistics> groupData : globalStatsByGroup
.entrySet()) {
MeasurementDAO.storeGroupStatisticsMeasurement(md,
groupData.getKey(), Time.getCurrentTime(),
groupData.getValue(),
Time.getCurrentTime() - timeEnableDao, true);
}
globalStatsByGroup.clear();
}
}
@Override
public void onMetricUpdate(ActiveMetric metric) {
long time = Time.getCurrentTime();
if (time < timeEnableDao || time > timeStopDao) {
return;
}
if (metric.isOverallMetric()) {
// global
MetricValue mv = metric.getOverallMetric();
Object val = mv.getValue();
if (mv.isValid()) {
if (val instanceof Number) {
double vd = ((Number) val).doubleValue();
dao.storeGlobalSingleMeasurement(md, time, vd);
}
}
} else {
// per-host metric
if (writeAggregates) {
/*
* Write aggregates instead of individual metric values.
* This can be improved w.r.t. performance, but currently we
* do not really care.
*/
// Iterate over groups
for (String group : hostsByGroup.keySet()) {
DescriptiveStatistics stats = new DescriptiveStatistics();
DescriptiveStatistics globalStats = globalStatsByGroup
.get(group);
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);
globalStats.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);
}
}
}
}
}
}
}
private interface DaoAdapter {
void onStop();
}
/**
* This class helps in persisting a metric using the {@link MeasurementDAO}
*
* @author Bjoern Richerzhagen
* @version 1.0, 13.08.2012
*/
private class MetricDaoAdapter implements ActiveMetricListener, DaoAdapter {
private final ActiveMetric metric;
private final MetricDescription md;
private final MeasurementDAO dao = new MeasurementDAO();
private final List<SimHost> hosts;
private final boolean writeAggregates;
private final Map<String, List<SimHost>> hostsByGroup;
private final Map<String, DescriptiveStatistics> globalStatsByGroup;
private long timestampLastEvent = -1;
public MetricDaoAdapter(ActiveMetric metric) {
this.metric = metric;
this.md = new MetricDescription(MetricOutputDAO.class.getName(),
metric.getName(), metric.getDescription(),
metric.getUnit().toString());
this.hosts = GlobalOracle.getHosts();
this.writeAggregates = isToAggregate(metric);
this.hostsByGroup = new LinkedHashMap<>();
this.globalStatsByGroup = new LinkedHashMap<>();
for (SimHost simHost : hosts) {
String groupId = simHost.getProperties().getGroupID();
if (!this.hostsByGroup.containsKey(groupId)) {
this.hostsByGroup.put(groupId, new LinkedList<>());
this.globalStatsByGroup.put(groupId,
new DescriptiveStatistics());
}
this.hostsByGroup.get(groupId).add(simHost);
}
}
public void onStop() {
if (writeAggregates) {
for (Entry<String, DescriptiveStatistics> groupData : globalStatsByGroup
.entrySet()) {
MeasurementDAO.storeGroupStatisticsMeasurement(md,
groupData.getKey(), Time.getCurrentTime(),
groupData.getValue(),
Time.getCurrentTime() - timeEnableDao, true);
}
globalStatsByGroup.clear();
}
}
@Override
public void onMetricUpdate(ActiveMetric metric) {
long time = Time.getCurrentTime();
if (time < timeEnableDao || time > timeStopDao) {
return;
}
if (metric.isOverallMetric()) {
// global
MetricValue mv = metric.getOverallMetric();
Object val = mv.getValue();
if (mv.isValid()) {
if (val instanceof Number) {
double vd = ((Number) val).doubleValue();
dao.storeGlobalSingleMeasurement(md, time, vd);
}
}
} else {
// per-host metric
if (writeAggregates) {
/*
* Write aggregates instead of individual metric values.
* This can be improved w.r.t. performance, but currently we
* do not really care.
*/
// Iterate over groups
for (String group : hostsByGroup.keySet()) {
DescriptiveStatistics stats = new DescriptiveStatistics();
DescriptiveStatistics globalStats = globalStatsByGroup
.get(group);
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);
globalStats.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);
}
}
}
}
}
}
}
}
/**
* This class helps in persisting a spatial metric using the {@link MeasurementDAO}
*
* @author Tobias Meuser
* @version 1.0, 10.10.2018
*/
private class SpatialMetricDaoAdapter implements ActiveSpatialMetricListener, DaoAdapter {
private final MetricDescription md;
private final MeasurementDAO dao = new MeasurementDAO();
private final List<SimHost> hosts;
private final Map<String, List<SimHost>> hostsByGroup;
private final Map<String, DescriptiveStatistics> globalStatsByGroup;
private double spatialResolution = 20;
public SpatialMetricDaoAdapter(ActiveSpatialMetric metric) {
this.md = new MetricDescription(MetricOutputDAO.class.getName(),
metric.getName(), metric.getDescription(),
metric.getUnit().toString());
this.hosts = GlobalOracle.getHosts();
this.hostsByGroup = new LinkedHashMap<>();
this.globalStatsByGroup = new LinkedHashMap<>();
for (SimHost simHost : hosts) {
String groupId = simHost.getProperties().getGroupID();
if (!this.hostsByGroup.containsKey(groupId)) {
this.hostsByGroup.put(groupId, new LinkedList<>());
this.globalStatsByGroup.put(groupId,
new DescriptiveStatistics());
}
this.hostsByGroup.get(groupId).add(simHost);
}
}
@Override
public void onStop() {
// Noting to do here
}
@Override
public void onMetricUpdate(ActiveSpatialMetric<?> metric) {
long time = Time.getCurrentTime();
if (time < timeEnableDao || time > timeStopDao) {
return;
}
if (metric.isOverallMetric()) {
// global
SpatialMetricValue mv = metric.getOverallMetric();
Object val = mv.getValue();
if (mv.isValid()) {
if (val instanceof Number) {
double vd = ((Number) val).doubleValue();
dao.storeGlobalSpatialMeasurement(md, time, vd,
(int) (mv.getLocation().getLongitude() / spatialResolution),
(int) (mv.getLocation().getLatitude() / spatialResolution));
}
}
} else {
for (SimHost host : hosts) {
SpatialMetricValue 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.storeSpatialMeasurement(md, host.getId().value(), time, vd,
(int) (mv.getLocation().getLongitude() / spatialResolution),
(int) (mv.getLocation().getLatitude() / spatialResolution));
}
}
}
}
}
}
}
}
/*
* 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.analyzer.metric.spatial;
import java.util.ArrayList;
import java.util.List;
import de.tudarmstadt.maki.simonstrator.api.common.metric.AbstractMetric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveSpatialMetric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric;
public abstract class AbstractSpatialMetric<T extends AbstractSpatialMetricValue<?>> extends AbstractMetric<T> implements Metric<T>, ActiveSpatialMetric<T> {
public AbstractSpatialMetric(String pDescription, MetricUnit pUnit) {
super(pDescription, pUnit);
}
public AbstractSpatialMetric(String pName, String pDescription, MetricUnit pUnit) {
super(pName, pDescription, pUnit);
}
protected void setOverallMetric(T aggregate) {
super.setOverallMetric(aggregate);
}
private List<ActiveSpatialMetricListener> _listeners = new ArrayList<>();
@Override
public void addActiveSpatialMetricListener(ActiveSpatialMetricListener pListener) {
_listeners.add(pListener);
}
@Override
public void notifyListeners() {
for (ActiveSpatialMetricListener activeSpatialMetricListener : _listeners) {
activeSpatialMetricListener.onMetricUpdate(this);
}
}
}
/*
* 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.analyzer.metric.spatial;
import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveSpatialMetric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.ActiveSpatialMetric.SpatialMetricValue;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
public abstract class AbstractSpatialMetricValue<S extends Object> implements SpatialMetricValue<S> {
private S value;
private Location location;
private ActiveSpatialMetric<?> metric;
public AbstractSpatialMetricValue(ActiveSpatialMetric<?> pMetric) {
metric = pMetric;
}
public AbstractSpatialMetricValue(ActiveSpatialMetric<?> pMetric, S pValue) {
metric = pMetric;
value = pValue;
}
public void setValue(S pValue, Location pLocation) {
value = pValue;
location = pLocation;
metric.notifyListeners();
}
@Override
public S getValue() {
return value;
}
@Override
public Location getLocation() {
return location;
}
}
\ No newline at end of file
......@@ -102,31 +102,47 @@ public class MeasurementDAO extends DAO {
hostMetric);
addToPersistQueue(measurement);
}
/**
* Store a single measurement for a host, tied to a specific location.
*
* @param metricDesc
* @param hostId
* @param time
* @param value
* @param locationX
* @param locationY
*/
public static void storeSpatialMeasurement(MetricDescription metricDesc,
long hostId, long time, double value, int locationX,
int locationY) {
if (inactive) {
return;
}
Metric metric = MetricDAO.lookupSpatialMetric(metricDesc);
HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId);
/**
* Store a single measurement for a host, tied to a specific location.
*
* @param metricDesc
* @param hostId
* @param time
* @param value
* @param locationX
* @param locationY
*/
public static void storeSpatialMeasurement(MetricDescription metricDesc,
long hostId, long time, double value, int locationX,
int locationY) {
if (inactive) {
return;
}
Metric metric = MetricDAO.lookupSpatialMetric(metricDesc);
HostMetric hostMetric = HostMetricDAO.lookupHostMetric(metric, hostId);
MeasurementSpatial measurement = new MeasurementSpatial(time, value,
hostMetric, locationX, locationY);
addToPersistQueue(measurement);
}
/**
* Store a global single measurement for a host, tied to a specific location.
*
* @param metricDesc
* @param hostId
* @param time
* @param value
* @param locationX
* @param locationY
*/
public static void storeGlobalSpatialMeasurement(MetricDescription metricDesc,
long time, double value, int locationX, int locationY) {
storeSpatialMeasurement(metricDesc, GLOBAL_HOST_ID, time, value, locationX, locationY);
}
MeasurementSpatial measurement = new MeasurementSpatial(time, value,
hostMetric, locationX, locationY);
addToPersistQueue(measurement);
}
/**
* Stores for a series of measurements the given values for a host. The
......@@ -194,7 +210,7 @@ public class MeasurementDAO extends DAO {
groupMetric, observationDuration, describesWholeSimulation);
addToPersistQueue(measurement);
}
/**
* Stores a statistical description of a series of values for group of
* hosts and a given spatial coordinate.
......@@ -233,7 +249,7 @@ public class MeasurementDAO extends DAO {
/**
* Store a list-based measurement with a key (i.e., as a
* {@link MeasurementPairList}).
*
*
* @param metricDesc
* @param hostId
* @param time
......@@ -256,7 +272,7 @@ public class MeasurementDAO extends DAO {
/**
* Shortcut for {@link MeasurementPairList} metrics based on a single list.
*
*
* @param metric
* @param hostId
* @param time
......
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