package lbms.plugins.mldht.kad;
import java.util.HashMap;
import java.util.Map;
import lbms.plugins.mldht.kad.messages.MessageBase;
import lbms.plugins.mldht.kad.messages.PingRequest;
/**
* @author Damokles
*
*/
public class PingRefreshTask extends Task {
private boolean cleanOnTimeout;
private Map<MessageBase, KBucketEntry> lookupMap;
/**
* @param rpc
* @param node
* @param cleanOnTimeout if true Nodes that fail to respond are removed. should be false for normal use.
*/
public PingRefreshTask (RPCServerBase rpc, Node node, boolean cleanOnTimeout) {
this(rpc, node, node.getBuckets(), cleanOnTimeout);
}
/**
* @param rpc
* @param node
* @param bucket the bucket to refresh
* @param cleanOnTimeout if true Nodes that fail to respond are removed. should be false for normal use.
*/
public PingRefreshTask (RPCServerBase rpc, Node node, KBucket bucket,
boolean cleanOnTimeout) {
super(node.getOurID(),rpc, node);
this.cleanOnTimeout = cleanOnTimeout;
if (cleanOnTimeout) {
lookupMap = new HashMap<MessageBase, KBucketEntry>();
}
if (bucket != null) {
for (KBucketEntry e : bucket.getEntries()) {
if (e.isQuestionable() || cleanOnTimeout) {
todo.add(e);
}
}
}
}
/**
* @param rpc
* @param node
* @param bucket the bucket to refresh
* @param cleanOnTimeout if true Nodes that fail to respond are removed. should be false for normal use.
*/
public PingRefreshTask (RPCServerBase rpc, Node node, KBucket[] buckets,
boolean cleanOnTimeout) {
super(node.getOurID(), rpc, node,"Multi Bucket Refresh");
this.cleanOnTimeout = cleanOnTimeout;
if (cleanOnTimeout) {
lookupMap = new HashMap<MessageBase, KBucketEntry>();
}
for (int i = 1; i < buckets.length; i++) {
if (buckets[i] != null) {
for (KBucketEntry e : buckets[i].getEntries()) {
if (e.isQuestionable() || cleanOnTimeout) {
todo.add(e);
}
}
}
}
}
/* (non-Javadoc)
* @see lbms.plugins.mldht.kad.Task#callFinished(lbms.plugins.mldht.kad.RPCCallBase, lbms.plugins.mldht.kad.messages.MessageBase)
*/
@Override
void callFinished (RPCCallBase c, MessageBase rsp) {
if (cleanOnTimeout) {
synchronized (lookupMap) {
lookupMap.remove(c.getRequest());
}
}
}
/* (non-Javadoc)
* @see lbms.plugins.mldht.kad.Task#callTimeout(lbms.plugins.mldht.kad.RPCCallBase)
*/
@Override
void callTimeout (RPCCallBase c) {
if (cleanOnTimeout) {
MessageBase mb = c.getRequest();
synchronized (lookupMap) {
if (lookupMap.containsKey(mb)) {
KBucketEntry e = lookupMap.remove(mb);
KBucket bucket = node.getBuckets()[node.getOurID().findApproxKeyDistance(
e.getID())];
if (bucket != null) {
DHT.logDebug("Removing invalid entry from cache.");
bucket.removeEntry(e, true);
}
}
}
}
}
/* (non-Javadoc)
* @see lbms.plugins.mldht.kad.Task#update()
*/
@Override
void update () {
// go over the todo list and send ping
// until we have nothing left
synchronized (todo) {
while (!todo.isEmpty() && canDoRequest()) {
KBucketEntry e = todo.first();
todo.remove(e);
if (e.isGood()) {
//Node responded in the meantime
continue;
}
PingRequest pr = new PingRequest(node.getOurID());
pr.setDestination(e.getAddress());
if (cleanOnTimeout) {
synchronized (lookupMap) {
lookupMap.put(pr, e);
}
}
rpcCall(pr);
}
}
if (todo.isEmpty() && getNumOutstandingRequests() == 0 && !isFinished()) {
done();
}
}
}