package peer;
import java.util.Enumeration;
import main.ui.ILog;
import main.ui.NodeConsole;
import network.Message;
import network.Transmitter;
import main.ui.ILog;
/**
* Class Acts as a 'HashMap on Steriods'
*
* 1)Holds the peers that we know about in the network
* 2)Holds a reference to the Strategy Object (with our plans for dealing with them)
* 3)Holds a reference to the class used to communicate to them
*
* This class aims to be threadsafe
*/
public class PeerGroup {
//Lest of the peers that know of
private PeerHash listOfPeers = new PeerHash();
//Handle to the transmitter to communicate over the network
private Transmitter localTransmitter;
//Handle to single singleton
private static PeerGroup singleInstance;
/**
* Constructor - private - use getInstance() instead
* @param transmit - the Transmitter object we will use to do network comms
* @param strategy - the object we use to select the closest peers
*/
private PeerGroup(Transmitter transmit){
setLocalTransmitter(transmit);
}
public static PeerGroup getInstance(){
if(singleInstance==null){
singleInstance = new PeerGroup(new Transmitter(2002));
}
return singleInstance;
}
/**
* This method should whenever a notify method is recieved from *another* node
* This allows us to add / update our internal hashmap of nodes that we are aware of
* @param noOfFiles TODO
* @param the hostName of the node that did the broadcast
* @param the network latency of this node
*/
public void notifyOccurred(Peer peerIn, NodeConsole log){
//Add - overwrite entry to internal hashtable
synchronized(listOfPeers){
log.log("Adding peer to peergroup " + peerIn.getHostName() +" number of peers:"+listOfPeers.getHashtable().size());
listOfPeers.set(peerIn);
//log.log("Putting peer in table : " + peerIn.getHostName());
}
}
/**
* Call this method when we want to tell peers about a file add/modify/removal
* The method
* 1) Removes any 'Dead' Nodes - as determined by PeerStrategy object
* 2) Passes the 'Event' onto X nearest nodes - as determined by PeerStrategy object
*
* TODO - use a 'real' transmit object!
*/
public void transmitEventToPeers(Message messageToSend,ILog log){
//Find out which strategy to use
IStrategy strat = AutonomicStrategyChooser.chooseStrategy(listOfPeers,log);
//1. remove dead nodes
//synchronized(listOfPeers){
strat.removeDeadNodes(listOfPeers, log);
//}
//2a. get nearest nodes
PeerHash nearestPeer = strat.getNearestPeers(listOfPeers, log);
//2b loop and transmit
Peer thisPeer;
Object tmpObject;
if(nearestPeer!=null){
Enumeration loopList = nearestPeer.getHashtable().elements();
while (loopList.hasMoreElements()){
//Check the class coming back
tmpObject = loopList.nextElement();
if(tmpObject instanceof Peer){
// pass on the message
thisPeer = (Peer)tmpObject;
getLocalTransmitter().send(messageToSend,thisPeer.getHostName(),log);
System.out.println("Sent Message to node:"+thisPeer);
} else {
System.out.println("Did not send message as class was:"+tmpObject.getClass());
System.out.println("Value of Object:"+tmpObject);
}
}
}
}
/**
* @param localTransmitter The localTransmitter to set.
*/
public void setLocalTransmitter(Transmitter localTransmitter) {
this.localTransmitter = localTransmitter;
}
/**
* @return Returns the localTransmitter.
*/
public Transmitter getLocalTransmitter() {
return localTransmitter;
}
}