/*
* Copyright (c) 2005-2011 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.network.gnp.topology;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.dom4j.tree.DefaultDocument;
import org.dom4j.tree.DefaultElement;
import de.tud.kom.p2psim.impl.network.IPv4NetID;
import de.tud.kom.p2psim.impl.network.gnp.geoip.IspLookupService;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.City;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.Continent;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.Country;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.PingErRegion;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.Region;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
/**
* This class holds all informations needed to built an xml-Host File for the
* simulations with the GnpNetLayer and GnpLatencyModel
*
* @author Gerald Klunker
* @version 0.1, 05.02.2008
*
*/
public class HostMap {
private static final String GROUP_WORLD = "World";
private static final String COUNTRY_UNLOCATABLE = "#UNLOCATABLE_COUNTRY";
private static final String REGION_UNLOCATABLE = "#UNLOCATABLE_REGION";
private static final String PINGER_REGION_UNLOCATABLE = "#PINGER_REGION_UNLOCATABLE";
// importet Files
private HashMap> skitterFiles = new HashMap>();
private File geolocationFile;
private IspLookupService ispService;
// Host Index and Groups
private HashMap monitorIndex = new HashMap();
private HashMap hostIndex = new HashMap();
private ArrayList[][][] quickLookup;
private HashMap> groups = new HashMap>();
// Country - Region - PingEr dictionary
private PingErLookup pingErLookup = new PingErLookup();
private CountryLookup countryLookup = new CountryLookup();
private GnpSpace gnpRef;
/**
* import Hosts and RTTs from a CAIDA skitter File
*
* @param skitterFile
*/
public void importSkitterFile(File skitterFile, boolean oldFormat) {
try {
skitterFiles.put(skitterFile.getAbsolutePath(), new HashSet());
FileReader inputFile = new FileReader(skitterFile);
BufferedReader input = new BufferedReader(inputFile);
int validLines = 0;
String line = input.readLine();
while (line != null) {
if (line.length() < 1024) {
int commentbegin = line.indexOf("#");
String line2parse = commentbegin < 0?line:line.substring(0, commentbegin); //ignore comments
//System.out.println("Line to parse is: " + line2parse);
if (!"".equals(line2parse.trim())) {
if(oldFormat?parseLineOldFormat(line2parse, skitterFile):parseLineNewFormat(line2parse, skitterFile)) validLines++;
}
} else {
//sometimes weird long lines occur when the file is corrupted:
Monitor.log(HostMap.class, Level.ERROR,
"The weird long line with length " + line.length()
+ "' could not be parsed in skitter file "
+ skitterFile);
}
line = input.readLine();
}
System.gc();
System.out.println("Imported " + validLines + " valid entries from skitter file " + skitterFile + ".");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean parseLineOldFormat(String line, File skitterFile) {
int monitorIP;
int peerIP;
double rtt;
Host currentMonitor;
Host currentPeer;
String[] tokens = line.split("\\s+");
if (tokens[0].equals("C") || tokens[0].equals("I")) {
if (tokens.length >= 5) {
String mo = tokens[1];
String pe = tokens[2];
String rt = tokens[4];
monitorIP = IPv4NetID.ipToInt(mo);
peerIP = IPv4NetID.ipToInt(pe);
rtt = Double.valueOf(rt);
currentMonitor = hostIndex.get(monitorIP);
if (currentMonitor == null) {
currentMonitor = new Host(monitorIP, this);
monitorIndex.put(monitorIP, currentMonitor);
hostIndex.put(monitorIP, currentMonitor);
}
if (!monitorIndex.containsValue(currentMonitor)) {
monitorIndex.put(monitorIP, currentMonitor);
}
currentMonitor.setHostType(Host.MONITOR);
currentPeer = hostIndex.get(peerIP);
if (currentPeer == null) {
currentPeer = new Host(peerIP, this);
currentPeer.setHostType(Host.HOST);
hostIndex.put(peerIP, currentPeer);
}
currentPeer.addRtt(currentMonitor, rtt);
skitterFiles.get(skitterFile.getAbsolutePath()).add(currentPeer);
return true;
} else
Monitor.log(HostMap.class, Level.ERROR, "The line '" + line
+ "' did not contain enough elements. in skitter file "
+ skitterFile);
}
return false;
}
private boolean parseLineNewFormat(String line, File skitterFile) {
int monitorIP;
int peerIP;
double rtt;
Host currentMonitor;
Host currentPeer;
String[] tokens = line.split("\\s+");
//System.out.println(StringToolkit.arrayToString(tokens, "|"));
if (tokens[0].equals("T") && tokens.length >= 7) {
if (tokens[6].equals("R") && tokens.length >= 8) {
String mo = tokens[1];
String pe = tokens[2];
String rt = tokens[7];
monitorIP = IPv4NetID.ipToInt(mo);
peerIP = IPv4NetID.ipToInt(pe);
rtt = Double.valueOf(rt);
currentMonitor = hostIndex.get(monitorIP);
if (currentMonitor == null) {
currentMonitor = new Host(monitorIP, this);
monitorIndex.put(monitorIP, currentMonitor);
hostIndex.put(monitorIP, currentMonitor);
}
if (!monitorIndex.containsValue(currentMonitor)) {
monitorIndex.put(monitorIP, currentMonitor);
}
currentMonitor.setHostType(Host.MONITOR);
currentPeer = hostIndex.get(peerIP);
if (currentPeer == null) {
currentPeer = new Host(peerIP, this);
currentPeer.setHostType(Host.HOST);
hostIndex.put(peerIP, currentPeer);
}
currentPeer.addRtt(currentMonitor, rtt);
skitterFiles.get(skitterFile.getAbsolutePath()).add(currentPeer);
//System.out.println("Successfully loaded value.");
return true;
} else
Monitor.log(HostMap.class, Level.ERROR, "The line '" + line
+ "' did not contain enough elements. in skitter file "
+ skitterFile);
}
return false;
}
/**
* import PingER summary report File
*
* @param file
*/
public void importPingErMinimumRtt(File file) {
pingErLookup.loadFromTSV(file, PingErLookup.DataType.MIN_RTT);
}
/**
* import PingER summary report File
*
* @param file
*/
public void importPingErAverageRtt(File file) {
pingErLookup.loadFromTSV(file, PingErLookup.DataType.AVERAGE_RTT);
}
/**
* import PingER summary report File
*
* @param file
*/
public void importPingErDelayVariation(File file) {
pingErLookup.loadFromTSV(file, PingErLookup.DataType.VARIATION_RTT);
}
/**
* import PingER summary report File
*
* @param file
*/
public void importPingErPacketLoss(File file) {
pingErLookup.loadFromTSV(file, PingErLookup.DataType.PACKET_LOSS);
}
/**
*
* @return country dictionary
*/
public CountryLookup getCountryLookup() {
return countryLookup;
}
/**
*
* @return pingerEr lookup table
*/
public PingErLookup getPingErLookup() {
return pingErLookup;
}
/**
*
* @param longitude
* @param latitude
* @return set of the nearest hosts to longitude/latitude position
*/
public Set getNearestHosts(double longitude, double latitude) {
HashSet result = new HashSet();
int index0 = (int) Math.floor(HostMap.getGeographicalDistance(90, 0, latitude, longitude) / 1000.0);
int index1 = (int) Math.floor(HostMap.getGeographicalDistance(0, 0, latitude, longitude) / 1000.0);
int index2 = (int) Math.floor(HostMap.getGeographicalDistance(0, 90, latitude, longitude) / 1000.0);
PeerComparatorDistance comparator = new PeerComparatorDistance();
comparator.setPosition(latitude, longitude);
Host peer = null;
if (quickLookup != null && quickLookup[index0][index1][index2] != null) {
for (Host p : quickLookup[index0][index1][index2]) {
if (peer == null) {
peer = p;
} else if (comparator.compare(peer, p) == 1) {
peer = p;
}
}
for (Host p : quickLookup[index0][index1][index2]) {
if (comparator.compare(peer, p) == 0)
result.add(p);
}
}
return result;
}
/**
* rebuilt an array of hosts for fast finding of nearest hosts
*/
private void builtQuickLookup() {
quickLookup = new ArrayList[21][21][21];
int index0 = 0;
int index1 = 0;
int index2 = 0;
Set ips = this.hostIndex.keySet();
for (Integer ip : ips) {
index0 = (int) Math.floor(HostMap.getGeographicalDistance(90, 0, hostIndex.get(ip).getLatitude(), hostIndex.get(ip).getLongitude()) / 1000.0);
index1 = (int) Math.floor(HostMap.getGeographicalDistance(0, 0, hostIndex.get(ip).getLatitude(), hostIndex.get(ip).getLongitude()) / 1000.0);
index2 = (int) Math.floor(HostMap.getGeographicalDistance(0, 90, hostIndex.get(ip).getLatitude(), hostIndex.get(ip).getLongitude()) / 1000.0);
if (quickLookup[index0][index1][index2] == null)
quickLookup[index0][index1][index2] = new ArrayList();
quickLookup[index0][index1][index2].add(hostIndex.get(ip));
}
}
/**
*
* @return reference to the related GNP Space object
*/
public GnpSpace getGnpRef() {
return gnpRef;
}
/**
*
* @param gnp
* reference to the related GNP Space object
*/
public void setGnpRef(GnpSpace gnp) {
gnpRef = gnp;
}
/**
*
* @return map of importet skitter files and hosts
*/
public HashMap> getImportedSkitterFiles() {
return skitterFiles;
}
/**
* counts the number of hosts with a certain number of measured RTTs [0]:
* number of Hosts with 0 measured RTTs, [1] number of Hosts with 1 measured
* RTTs ...
*
* @return map from number of measured RTTs to number of related hosts
*/
public int[] getConnectivityOfHosts() {
int[] counter = new int[getNoOfMonitors() + 1];
for (Host host : hostIndex.values()) {
if (host.getHostType() == Host.HOST)
counter[host.getMeasuredMonitors().size()]++;
}
return counter;
}
/**
*
* @param groupName
* @return Set of Host related to the Group
*/
public Collection getGroup(String groupName) {
if (groups.containsKey(groupName))
return groups.get(groupName);
else
return new HashSet();
}
/**
*
* @return map of groupnames to related hosts
*/
public HashMap> getGroups() {
return groups;
}
/**
*
* @param groupName
* @param host
*/
public void addHostToGroup(String groupName, Host host) {
String name = groupName.replace(" ", "");
if (!groups.containsKey(name))
groups.put(name, new HashSet());
groups.get(name).add(host);
}
/**
*
* @param groupName
* @param hosts
* set of hosts
*/
public void addHostToGroup(String groupName, Collection hosts) {
String name = groupName.replace(" ", "");
if (!groups.containsKey(name))
groups.put(name, new HashSet());
groups.get(name).addAll(hosts);
}
/**
*
* @param groupName
* @param grid
*/
public void addHostToGroup(String groupName, boolean grid[][]) {
Set[][] peerGrid = getHostGrid(grid.length, grid[0].length);
for (int x = 0; x < grid.length; x++) {
for (int y = 0; y < grid[x].length; y++) {
if (grid[x][y]) {
addHostToGroup(groupName, peerGrid[x][y]);
}
}
}
}
/**
*
* @param resLon
* number of horizontal divisions
* @param resLat
* number of vertical divisions
* @return hosts grouped by their geographical position
*/
private Set[][] getHostGrid(int resLon, int resLat) {
Set[][] peerGrid = new HashSet[resLon][resLat];
int posLon;
int posLat;
double stepLon = 360 / (double) resLon;
double stepLat = 180 / (double) resLat;
for (Host host : hostIndex.values()) {
posLon = (int) Math.floor((180 + host.getLongitude()) / stepLon);
posLat = (int) Math.floor((90 + host.getLatitude()) / stepLat);
if (peerGrid[posLon][posLat] == null)
peerGrid[posLon][posLat] = new HashSet();
peerGrid[posLon][posLat].add(host);
}
return peerGrid;
}
/**
*
* @param groupName
*/
public void removeGroup(String groupName) {
groups.remove(groupName);
}
/**
*
* @param groupNames
* set of group names
*/
public void removeGroup(Set groupNames) {
for (String name : groupNames)
removeGroup(name);
}
/**
* reduce the number of hosts in a group
*
* @param groupName
* @param noOfHosts
*/
public void scaleGroup(String groupName, int newSize) {
Set oldGroup = groups.get(groupName);
Set newGroup = new HashSet();
while (newGroup.size() < newSize && oldGroup.size() > 0) {
Host[] hosts = oldGroup.toArray(new Host[0]);
for (int c = 0; c < newSize - newGroup.size(); c++) {
int random = (int) Math.floor(Math.random() * hosts.length);
newGroup.add(hosts[random]);
oldGroup.remove(hosts[random]);
}
}
oldGroup.clear();
oldGroup.addAll(newGroup);
}
/**
* generate groups with the name of GeoIP country names
*/
public void builtCountryGroups() {
for (Host host : hostIndex.values()) {
String country = countryLookup.getGeoIpCountryName(host.getCountryCode());
if (country == null)
country = COUNTRY_UNLOCATABLE;
this.addHostToGroup(country, host);
}
}
/**
* generate groups with the name of GeoIP country names
*/
public void builtRegionGroups() {
for (Host host : hostIndex.values()) {
String region = host.getRegion();
if (region == null)
region = REGION_UNLOCATABLE;
this.addHostToGroup(region, host);
}
}
/**
* generate groups with the name of PingER region names
*/
public void builtPingerGroups() {
for (Host host : hostIndex.values()) {
String country = countryLookup.getPingErRegionName(host.getCountryCode());
if (country == null)
country = PINGER_REGION_UNLOCATABLE;
this.addHostToGroup(country, host);
}
}
/**
* built a group with all hosts
*/
public void builtWorldGroups() {
this.addHostToGroup(GROUP_WORLD, hostIndex.values());
}
/**
*
* @return number of hosts in this map
*/
public int getNoOfHosts() {
return hostIndex.size();
}
/**
*
* @return number of monitors in this map
*/
public int getNoOfMonitors() {
return monitorIndex.size();
}
/**
*
* @param file
* filename of a GeoIP binary database
*/
public void setGeolocationDatabase(File file) {
geolocationFile = file;
}
public void setIspLocationDatabase(String db) {
ispService = new IspLookupService(db);
}
/**
*
* @return filename of the current GeoIP database
*/
public File getGeolocationDatabase() {
return geolocationFile;
}
/**
* position all hosts with the current GeoIP database
*/
public void setLocationOfHosts() {
if (geolocationFile == null) {
return;
}
Geolocator locator = new GeolocatorGeoIP(geolocationFile);
for (Host host : hostIndex.values()) {
host.setLocation(locator, ispService);
}
builtQuickLookup();
// distanceVsRttPlot("test100", null, 100);
}
/**
*
* @return map from 2-digits country code to the related hosts
*/
public HashMap> getLocations() {
HashMap> locations = new HashMap>();
locations.put("# LOCATABLE", new HashSet());
locations.put("# UNLOCATABLE", new HashSet());
for (Host host : hostIndex.values()) {
if (host.isLocatable()) {
if (!locations.containsKey(host.getCountryCode()))
locations.put(host.getCountryCode(), new HashSet());
locations.get(host.getCountryCode()).add(host);
locations.get("# LOCATABLE").add(host);
} else {
locations.get("# UNLOCATABLE").add(host);
}
}
return locations;
}
/**
*
* @return map from ip to related monitor Host object
*/
public HashMap getMonitorIndex() {
return monitorIndex;
}
/**
*
* @return map from ip to related Host object
*/
public HashMap getHostIndex() {
return hostIndex;
}
/**
* make the measured inter-monitor RTTs adjacency matrix symmetrical. => RTT
* A->B = RTT B->A assumtion is needed within the GNP coordinate model.
*/
public void makeSymmetrical() {
for (Host monitorA : monitorIndex.values()) {
for (Host monitorB : monitorIndex.values()) {
if (monitorA == monitorB) {
monitorA.removeRTT(monitorB);
} else {
double rtt1 = monitorA.getRtt(monitorB);
double rtt2 = monitorB.getRtt(monitorA);
double newRtt = Double.NaN;
if (rtt1 > 0 && rtt2 > 0)
newRtt = (rtt1 + rtt2) / 2;
else if (rtt1 > 0)
newRtt = rtt1;
else if (rtt2 > 0)
newRtt = rtt2;
monitorA.setRtt(monitorB, newRtt);
monitorB.setRtt(monitorA, newRtt);
}
}
}
}
/**
*
* @param p1
* host 1
* @param p2
* host 2
* @return distance in km
*/
private static double getGeographicalDistance(Host p1, Host p2) {
return HostMap.getGeographicalDistance(p1.getLatitude(), p1.getLongitude(), p2.getLatitude(), p2.getLongitude());
}
/**
*
* @param latitude1
* host 1
* @param longitude1
* host 1
* @param latitude2
* host 2
* @param longitude2
* host 2
* @return distance in km
*/
private static double getGeographicalDistance(double latitude1, double longitude1, double latitude2, double longitude2) {
GeographicPosition pos1 = new GeographicPosition(longitude1, latitude1);
GeographicPosition pos2 = new GeographicPosition(longitude2, latitude2);
return pos1.distanceTo(pos2);
}
/**
* unlocatable on the globe (unkonw ip, proxy, satelite)
*
* @return number of unlocatable hosts
*/
public int getNoOfUnlocatableHosts() {
int unlocatedPeers = 0;
int unlocatedMonitors = 0;
Set ips = this.hostIndex.keySet();
for (Integer ip : ips) {
unlocatedPeers += (hostIndex.get(ip).isLocatable()) ? 0 : 1;
unlocatedMonitors += (hostIndex.get(ip).isLocatable() || hostIndex.get(ip).getHostType() == Host.HOST) ? 0 : 1;
}
return unlocatedPeers - unlocatedMonitors;
}
/**
*
* @param monitor
*/
public void removeMonitor(Host monitor) {
this.monitorIndex.remove(monitor.getIpAddress());
this.hostIndex.remove(monitor.getIpAddress());
for (Host host : hostIndex.values()) {
host.removeRTT(monitor);
}
this.builtQuickLookup();
}
/**
*
* Removes the given set of hosts from the map.
*
* @param hosts
* set of hosts
*/
public void removeHosts(Set hosts) {
for (Host host : hosts) {
// if (host.getHostType() == Host.HOST) {
if (this.getGnpRef() != null)
this.getGnpRef().removePosition(host.getIpAddress());
this.hostIndex.remove(host.getIpAddress());
// }
}
for (Set group : groups.values())
group.removeAll(hosts);
countryLookup.keepCountries(getLocations().keySet());
this.builtQuickLookup();
}
/**
* SEEMS TO remove all hosts that were pinged by exactly noOfConnections
* distinct monitors.
*
* removes all hosts that have noOfConnections measured RTTs
*
* @param noOfConnections
*/
public void removeHosts(int noOfConnections) {
Set hosts = new HashSet();
for (Host host : hostIndex.values()) {
if (host.getMeasuredMonitors().size() == noOfConnections)
hosts.add(host);
}
removeHosts(hosts);
}
/**
* remove all hosts that have at least one measured RTT with a error bigger
* than the argument. Removing that errors will improve the quality of the
* Gnp Space.
*
* @param error
* relative error
*/
public void removeHostsWithMaximumRelativeError(double error) {
HashSet delete = new HashSet();
for (Host host : hostIndex.values()) {
for (int c = 0; c < gnpRef.getNumberOfMonitors(); c++) {
double relError = Math.abs(host.getGnpPositionReference().getDirectionalRelativError(gnpRef.getMonitorPosition(c)));
if (relError >= error) {
delete.add(host);
break;
}
}
}
removeHosts(delete);
}
/**
* SEEMS TO only keep the 'noOfMonitorsToKeep' monitor hosts in the GNP space that have the
* maximum distance between each other, the other ones are being deleted.
*
* keeps the maximum separated monitors
*
* @param noOfMonitorsToKeep
*/
public void removeMonitorsKeepMaximumSparation(int noOfMonitorsToKeep) {
ArrayList maxSeperatedPeers = getMaximumSeparatedMonitors(noOfMonitorsToKeep);
ArrayList deleteMonitors = new ArrayList();
for (Host monitor : monitorIndex.values()) {
if (!maxSeperatedPeers.contains(monitor))
deleteMonitors.add(monitor);
}
for (Host monitor : deleteMonitors) {
this.removeMonitor(monitor);
}
}
/**
*
*
* @param noOfMonitors
* @return maximum separated monitors
*/
private ArrayList getMaximumSeparatedMonitors(int noOfMonitors) {
ArrayList> allCombinations = getMonitorCombinations(noOfMonitors);
int posWithMax = 0;
double valueMax = 0.0;
for (int c = 0; c < allCombinations.size(); c++) {
double currentDistance = getInterMonitorDistance(allCombinations.get(c));
if (currentDistance > valueMax) {
valueMax = currentDistance;
posWithMax = c;
}
}
return allCombinations.get(posWithMax);
}
/**
*
* @param monitors
* @return sum measured RTTs between monitors
*/
private double getInterMonitorDistance(ArrayList monitors) {
double result = 0.0;
for (int c = 0; c < monitors.size() - 1; c++)
for (int d = c + 1; d < monitors.size(); d++)
result += monitors.get(c).getRtt(monitors.get(d));
return result;
}
/**
*
* @param size
* @return all combinations of monitors with size "size"
*/
private ArrayList> getMonitorCombinations(int size) {
ArrayList monitors = new ArrayList();
monitors.addAll(monitorIndex.values());
Collections.sort(monitors, new PeerComparatorNoOfConnections());
return builtRecursive(new ArrayList(), size, monitors, 0);
}
/**
* recursive built of all combinations of monitors with size "size"
*
* @param current
* @param max
* @param monitors
* @param posInMonitors
* @return array of combinations
*/
private ArrayList> builtRecursive(ArrayList current, int max, ArrayList monitors, int posInMonitors) {
ArrayList> result = new ArrayList>();
if (current.size() == max) {
result.add(current);
return result;
} else {
for (int c = posInMonitors; c < monitors.size() - (max - current.size()); c++) {
ArrayList copy = (ArrayList) current.clone();
copy.add(monitors.get(c));
result.addAll(builtRecursive(copy, max, monitors, c + 1));
}
return result;
}
}
/**
* generate two files with distance - rtt pairs, that can be used with
* gnuplot
*
* filename.txt1 plots each measured host - monitor RTT filename.txt2
* aggregates distances within a range and calculates the average RTT
*
* @param filename
* @param steps
* number of divisions within the 0 - 20000km for aggregated plot
*/
public void distanceVsRttPlot(String filename, Host monitor, int steps) {
try {
double[] test1 = new double[steps];
int[] test2 = new int[steps];
FileWriter all = new FileWriter(filename + ".txt1");
for (Host host : hostIndex.values()) {
for (Host mon : host.getMeasuredMonitors()) {
double distance = getGeographicalDistance(host, mon);
double rtt = host.getRtt(mon);
all.write(distance + " " + rtt + "\n");
int pos = (int) Math.floor((distance / 20000.0) * steps);
test1[pos] += rtt;
test2[pos]++;
}
}
all.close();
all = new FileWriter(filename + ".txt2");
for (int c = 0; c < steps; c++) {
double x = (c * (20000.0 / steps)) + (20000.0 / (2 * steps));
double y = test1[c] / test2[c];
all.write(x + " " + y + "\n");
}
all.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* saves host postion location, GNP position, groups, GNP Space, PingER
* Lookup table in an xml file used within the simulation
*
* @param file
*/
public void exportToXml(File file) {
try {
OutputFormat format = OutputFormat.createPrettyPrint();
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
XMLWriter writer = new XMLWriter(out, format);
writer.write(getDocument());
writer.close();
} catch (IOException e) {
System.out.println(e);
}
}
/**
*
* @return xml Document Object of relevant Class Attributes
*/
private Document getDocument() {
Set hosts = new HashSet();
// "GroupLookup" Element
DefaultElement groups = new DefaultElement("GroupLookup");
for (String group : this.groups.keySet()) {
hosts.addAll(this.groups.get(group));
DefaultElement peerXml = new DefaultElement("Group");
peerXml.addAttribute("id", group);
peerXml.addAttribute("maxsize", String.valueOf(this.groups.get(group).size()));
String ip = "";
int x = 0;
int blockSize = 1000;
// IP Block of 1000, too long blocks leads to hangUp ??
for (Host host : this.groups.get(group)) {
x++;
ip += "," + host.getIpAddress();
if (x % blockSize == 0) {
ip = ip.substring(1);
DefaultElement ips = new DefaultElement("IPs");
ips.addAttribute("value", ip);
peerXml.add(ips);
ip = "";
}
}
if (ip.length() > 0) {
ip = ip.substring(1);
DefaultElement ips = new DefaultElement("IPs");
ips.addAttribute("value", ip);
peerXml.add(ips);
}
groups.add(peerXml);
}
// "Hosts" Element
DefaultElement peers = new DefaultElement("Hosts");
for (Host host : hosts) {
DefaultElement peer = new DefaultElement("Host");
peer.addAttribute("ip", String.valueOf(host.getIpAddress()));
String area = (host.getArea() != null) ? host.getArea() : "--";
peer.addAttribute("continentalArea", area);
String countryCode = (host.getCountryCode() != null) ? host.getCountryCode() : "--";
peer.addAttribute("countryCode", countryCode);
String region = (host.getRegion() != null) ? host.getRegion() : "--";
peer.addAttribute("region", region);
String city = (host.getCity() != null) ? host.getCity() : "--";
peer.addAttribute("city", city);
String isp = (host.getISP() != null) ? host.getISP() : "--";
peer.addAttribute("isp", isp);
peer.addAttribute("longitude", String.valueOf(host.getLongitude()));
peer.addAttribute("latitude", String.valueOf(host.getLatitude()));
String coordinates = (host.getGnpPositionReference() != null) ? host.getGnpPositionReference().getCoordinateString() : "0";
peer.addAttribute("coordinates", coordinates);
peers.add(peer);
}
// "PingErLookup" Elements
Element pingEr = pingErLookup.exportToXML();
// "CountryLookup" Element
Element country = countryLookup.exportToXML();
DefaultDocument document = new DefaultDocument(new DefaultElement("gnp"));
document.getRootElement().add(groups);
document.getRootElement().add(peers);
document.getRootElement().add(pingEr);
document.getRootElement().add(country);
return document;
}
public void insertIntoRelationalDB(NetMeasurementDB db) {
Map hostsScanned = new HashMap();
for (String group : this.groups.keySet()) {
Set hosts = this.groups.get(group);
List dbHosts = new ArrayList(hosts.size());
for (Host h : hosts) {
NetMeasurementDB.Host host = hostsScanned.get(h);
if (host == null) {
String countryStr = h.getCountryName();
String pingErRegionStr = countryLookup.getPingErRegionName(countryStr);
assert pingErRegionStr != null : "No PingEr region found for country " + countryStr;
City city = getCity(db, h.getCity(), h.getRegion(), countryStr, h.getCountryCode(), h.getArea(), pingErRegionStr);
GnpPosition pos = h.getGnpPositionReference();
List gnpCoords;
if (pos != null) {
int dims = pos.getNoOfDimensions();
gnpCoords = new ArrayList(dims);
for (int i= 0; i {
double latitude;
double longitude;
public void setPosition(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public int compare(Host peer1, Host peer2) {
double distance1 = HostMap.getGeographicalDistance(peer1.getLatitude(), peer1.getLongitude(), latitude, longitude);
double distance2 = HostMap.getGeographicalDistance(peer2.getLatitude(), peer2.getLongitude(), latitude, longitude);
if (distance1 < distance2)
return -1;
else if (distance1 > distance2)
return 1;
else
return 0;
}
}
/**
* Comparator implementation for sorting of Host with the number of measured
* RTTs per Host.
*/
private class PeerComparatorNoOfConnections implements Comparator {
public int compare(Host peer1, Host peer2) {
int coonections1 = peer1.getMeasuredMonitors().size();
int coonections2 = peer2.getMeasuredMonitors().size();
if (coonections1 < coonections2)
return 1;
else if (coonections1 > coonections2)
return -1;
else
return 0;
}
}
}