/**
*
*/
package info.walnutstreet.vs.ps04.member;
import info.walnutstreet.vs.ps04.p2p.ring.Node;
import info.walnutstreet.vs.ps04.p2p.ring.interfaces.NodeInterface;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import org.apache.log4j.Logger;
/**
* @author Christoph Gostner
* @version 0.1
*
*/
public class P2PMemberController {
private final static int PORT = Integer.parseInt(System.getProperty(P2PMemberController.class.getName() + ".port"));
private static Logger logger = Logger.getLogger(P2PMemberController.class);
private static P2PMemberController instance;
private NodeInterface bootstrap;
private NodeInterface node; /* node of the member */
/**
* Constructor.
*/
private P2PMemberController() {
super();
this.node = null;
this.bootstrap = null;
}
/**
* Get a singleton instance pf the member controller.
*
* @return The singleton instance
*/
public static P2PMemberController getInstance() {
if (P2PMemberController.instance == null)
P2PMemberController.instance = new P2PMemberController();
return P2PMemberController.instance;
}
/**
* Get the member's node.
*
* @return The member's node
*/
public NodeInterface getNode() {
return this.node;
}
/**
* Set the bootstrap node.
*
* @param hostname The hostname of the registry server
* @throws RemoteException
* @throws NotBoundException
*/
public void setBootstrap(String hostname) throws RemoteException, NotBoundException {
P2PMemberController.logger.debug("Controller: get bootstrap node");
Registry registry = LocateRegistry.getRegistry(hostname, P2PMemberController.PORT);
this.bootstrap = (NodeInterface)registry.lookup(Node.class.getCanonicalName());
}
/**
* Register the own node in the ring.
*
* @param name The node's name/id
* @return If the node could be inserted correctly
* @throws RemoteException
*/
public boolean register(String name) throws RemoteException {
if (this.bootstrap == null) { // i'll be the bootstrap node
this.createBootstrap(name, -1);
return true;
} else {
P2PMemberController.logger.debug("Controller: search name in the ring: " + name);
if (this.bootstrap.lookup(name) == null) {
P2PMemberController.logger.debug("Controller: name doesn't exist, start insert");
this.node = new Node(name);
if (this.bootstrap.join(this.node)) {
P2PMemberController.logger.debug("Controller: insert ok");
return true;
}
}
}
return false;
}
/**
* Search a node by it's name to get the direct receiver of the message.
*
* @param name The name/id to search
* @return The node or null to send the message to
* @throws RemoteException
*/
public NodeInterface getReceiver(String name) throws RemoteException {
return this.node.lookup(name);
}
/**
* Return the own name.
*
* @return the name
* @throws RemoteException
*/
public String getName() throws RemoteException {
return this.node.getName();
}
/**
* Create the bootstrap node.
*
* @param name The name of the bootstrap node.
* @param number
* @throws RemoteException
*/
public void createBootstrap(String name, int number) throws RemoteException {
P2PMemberController.logger.debug("Controller: create bootstrap node");
Registry registry = LocateRegistry.createRegistry(P2PMemberController.PORT);
this.node = new Node(name, number);
registry.rebind(Node.class.getCanonicalName(), this.node);
this.bootstrap = this.node;
}
/**
* Checks if the bootstrap node exists.
*
* @param hostname The server's host name
* @return If the bootstrap node exists
* @throws RemoteException
* @throws NotBoundException
*/
public boolean bootstrapExists(String hostname) throws RemoteException, NotBoundException {
P2PMemberController.logger.debug("Controller: check if the bootstrap node exists");
try {
Registry registry = LocateRegistry.getRegistry(hostname, P2PMemberController.PORT);
/*Object object = */registry.lookup(Node.class.getCanonicalName());
return true;
} catch (NotBoundException e) {
return false;
} catch (RemoteException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
/**
* Let the bootstrap node create a new node.
*
* @return
* @throws RemoteException
*/
public boolean createNode() throws RemoteException {
P2PMemberController.logger.debug("Controller: create a my node");
String name = this.bootstrap.generateNewNodeName();
if (name != null) {
this.node = new Node(name);
this.bootstrap.join(node);
P2PMemberController.logger.debug("Controller: register my node");
return true;
}
P2PMemberController.logger.debug("Controller: can't get a valid node");
return false;
}
/**
* Rebuild the finger table.
*
* @return If the table was build successful
*/
public boolean rebuildFingerTable() {
try {
this.node.rebuildFingerTable();
return true;
} catch (RemoteException e) {
}
return false;
}
/**
* Get a node using the chord lookup.
*
* @param name
* @return
* @throws RemoteException
*/
public NodeInterface getChordNode(String name) throws RemoteException {
return this.node.lookupChord(name);
}
}