/*
* 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.util.oracle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph;
import de.tudarmstadt.maki.simonstrator.api.common.graph.IEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INode;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.core.OracleComponent;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetID;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface;
import de.tudarmstadt.maki.simonstrator.api.component.topology.TopologyID;
import de.tudarmstadt.maki.simonstrator.api.component.topology.TopologyProvider;
/**
* This class gives access to the hosts of the scenario. To work, it has to be
* referenced in the configuration file after the host builder.
*
* The purpose of this class is to enable a global knowledge for analyzing. It
* is not meant to be used within any functional parts of simulated systems.
*
* @author Julius Rueckert
*
*/
public class GlobalOracle implements OracleComponent {
private static HashMap hostIDtoHosts = new LinkedHashMap();
private static HashMap netIDtoHosts = new LinkedHashMap();
private static List hosts = new LinkedList();
private static List bootstrapList = new LinkedList();
private static GlobalOracle instance = new GlobalOracle();
private GlobalOracle() {
//
}
public static GlobalOracle getInstance() {
return instance;
}
/**
* Initial population with hosts.
*
* @param hostBuilder
*/
public static void populate(List allHosts) {
hosts = allHosts;
if (hosts == null || hosts.size() <= 0) {
return;
}
for (SimHost host : hosts) {
/* Might happen in case of FakeHost. */
if (host.getNetworkComponent() == null) {
continue;
}
hostIDtoHosts.put(host.getHostId(), host);
for (NetInterface net : host.getNetworkComponent()
.getNetworkInterfaces()) {
netIDtoHosts.put(net.getLocalInetAddress(), host);
bootstrapList.add(net.getLocalInetAddress());
}
}
return;
}
/**
* Sets the bootstrap hosts. To be called by netLayer.
*
* @param bootstrapList
* the new bootstrap hosts
*/
public static void setBootstrapHosts(List bootstrapList) {
GlobalOracle.bootstrapList = bootstrapList;
}
/**
* Gets the bootstrap hosts.
*
* @return the bootstrap hosts
*/
public static List getBootstrapHosts() {
return GlobalOracle.bootstrapList;
}
/**
* Gets the random host.
*
* @return the random host
*/
public static NetID getRandomHost() {
return bootstrapList.get(Randoms.getRandom(GlobalOracle.class)
.nextInt() % bootstrapList.size());
}
/**
* Gets the first host.
*
* @return the first host
*/
public static NetID getFirstHost() {
if (bootstrapList.size() == 0) {
assert (false) : "Bootstraplist is empty";
return null;
}
return bootstrapList.get(0);
}
/**
* @param id
* @return the host with the given NetID
*/
public static SimHost getHostForNetID(NetID id) {
return netIDtoHosts.get(id);
}
/**
* @param id
* @return the host with the given host ID
*/
public static SimHost getHostForHostID(Long id) {
return hostIDtoHosts.get(id);
}
/**
* @return the list with all hosts of the scenario
*/
public static List getHosts() {
synchronized (hosts) {
return new ArrayList(hosts);
}
}
/**
* @return the list with all hosts of the scenario
*/
public static List getHosts(String groupID) {
if(groupID.equals("")) {
return getHosts();
}
else {
synchronized (hosts) {
ArrayList groupedHosts = new ArrayList();
for (SimHost h : hosts) {
if(h.getProperties().getGroupID().equals(groupID)) {
groupedHosts.add(h);
}
}
return groupedHosts;
}
}
}
@Override
public List getAllHosts() {
return new ArrayList(hosts);
}
@Override
public boolean isSimulation() {
return true;
}
/**
* Returns a global view of the topology for the specified mechanism. The
* mechanism must be a HostComponent that is registered at the local host.
* Otherwise, this method will not be able to find the local mechanism
* objects.
*
* @param component
* @param identifier
* @return
*/
public static Graph getTopology(
Class component, TopologyID identifier) {
HashSet edges = new LinkedHashSet<>();
HashSet nodes = new LinkedHashSet<>();
LinkedList allProviders = new LinkedList<>();
for (SimHost host : getHosts()) {
try {
TopologyProvider topologyProvider = host
.getComponent(component);
INode providerNode = topologyProvider.getNode(identifier);
nodes.add(providerNode);
allProviders.add(topologyProvider);
} catch (ComponentNotAvailableException e) {
// if the component is not available on the host, we can't do
// anything about it
// no reason to crash the simulation as this might be the case
// in various scenarios
}
}
for (TopologyProvider topologyProvider : allProviders) {
Set neighbors = topologyProvider.getNeighbors(identifier);
edges.addAll(neighbors);
}
/*
* Copy elements and (!) attached properties
*/
Graph graph = Graphs.createGraph();
for(INode node : nodes){
INode copy = graph.createNode(node.getId());
copy.addPropertiesFrom(node);
}
for(IEdge edge : edges) {
IEdge copy = graph.createEdge(edge.fromId(), edge.toId());
copy.addPropertiesFrom(edge);
}
return graph;
}
/**
* Returns available topology identifiers for the given component. Throws an
* {@link ComponentNotAvailableException} if the component is not available
* on any node in the network. Assumes that all instances of a given
* component class provide the same topology identifiers.
*
* @throws ComponentNotAvailableException
*/
public static Iterable getTopologyIdentifiers(
Class component) throws ComponentNotAvailableException {
// iterate over all the hosts, find one host that contains the given
// component class and ask this component about available topologies
for (SimHost host : getHosts()) {
try {
TopologyProvider topologyProvider = host
.getComponent(component);
return topologyProvider.getTopologyIdentifiers();
} catch (ComponentNotAvailableException e) {
// if the component is not available on the host, we can't do
// anything about it
// no reason to crash the simulation as this might be the case
// in various scenarios
}
}
throw new ComponentNotAvailableException();
}
/**
* Checks whether the host with the given NetID is online using a global
* list of all hosts in the current scenario.
*
* @param receiver
* @return true if online
*/
public static boolean isHostOnline(NetID receiver) {
if (netIDtoHosts.get(receiver) == null)
return false;
return netIDtoHosts.get(receiver).getNetworkComponent()
.getByNetId(receiver).isUp();
}
}