/**
*
*/
package info.walnutstreet.vs.ps04.p2p;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import info.walnutstreet.vs.ps04.p2p.ring.interfaces.NodeInterface;
/**
* @author Christoph Gostner
* @version 0.1
*
*/
public final class P2PFingerTable implements Serializable {
private static final long serialVersionUID = 1898436139967952514L;
private static final int MODULO_VALUE = Integer.MAX_VALUE;
private NodeInterface localNode;
private Map<Integer, NodeInterface> remoteNodes;
public P2PFingerTable(NodeInterface node) throws RemoteException {
this.localNode = node;
this.remoteNodes = new HashMap<Integer, NodeInterface>();
}
public void createFingerTable() throws RemoteException {
this.remoteNodes.clear();
int maxNum = this.localNode.numberOfNodes();
for (int i = 0; i < Math.sqrt(maxNum); i++) {
int nextId = (this.localNode.getId() + (int)Math.pow(2, i)) % P2PFingerTable.MODULO_VALUE;
NodeInterface nodeThatAlreadyExists = this.getEntry(nextId);
if (nodeThatAlreadyExists == null) { // if the node with the id 'nextId' doesn't exists
NodeInterface predecessorOfSearchedNextId = this.getPrevFTEntry(nextId);
NodeInterface nodeWithIdAsNextId = null;
if (predecessorOfSearchedNextId == null) { // no predecessor exists
nodeWithIdAsNextId = this.localNode.lookup(nextId);
} else { // ok, we have a predecessor in the table
nodeWithIdAsNextId = predecessorOfSearchedNextId.lookupChord(nextId);
}
if (nodeWithIdAsNextId != null) {
this.setEntry(i, nodeWithIdAsNextId);
}
}
}
}
private void setEntry(int i, NodeInterface node) {
this.remoteNodes.put(i, node);
}
public NodeInterface getEntry(int nextId) throws RemoteException {
Set<Integer> set = this.remoteNodes.keySet();
for (Integer integer : set) {
NodeInterface node = this.remoteNodes.get(integer);
if (node.getId() == nextId)
return node;
}
return null;
}
private NodeInterface getPrevFTEntry(int nextid) throws RemoteException {
Set<Integer> ids = this.remoteNodes.keySet();
NodeInterface n = null;
for (Integer integer : ids) {
NodeInterface node = this.remoteNodes.get(integer);
if (node.getId() < nextid)
n = node;
else
break;
}
return n;
}
/**
* @return the remoteNodes
*/
public Map<Integer, NodeInterface> getRemoteNodes() {
return remoteNodes;
}
}