Author: toad
Date: 2008-02-06 20:07:51 +0000 (Wed, 06 Feb 2008)
New Revision: 17610
Modified:
trunk/freenet/src/freenet/node/FailureTable.java
trunk/freenet/src/freenet/node/NodeDispatcher.java
trunk/freenet/src/freenet/node/RequestHandler.java
trunk/freenet/src/freenet/node/RequestSender.java
Log:
Migrate to new callbacks. Delete old onFailure(). Use onFailed() on nonfatal
errors and onFinalFailure() on fatal ones.
Also, set a timeout for nonfatal failures equal to the time it took to send the
request and wait for the answer. This will help with cancer nodes doing sneaky
things like waiting 90 seconds and then sending a RouteNotFound in an attempt
to get us to blame the problem on another node.
(Well it doesn't entirely solve the problem... but it's a start)
Modified: trunk/freenet/src/freenet/node/FailureTable.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTable.java 2008-02-06 20:04:55 UTC
(rev 17609)
+++ trunk/freenet/src/freenet/node/FailureTable.java 2008-02-06 20:07:51 UTC
(rev 17610)
@@ -68,6 +68,15 @@
logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
}
+ /**
+ * Called when we route to a node and it fails for some reason, but we
continue the request.
+ * Normally the timeout will be the time it took to route to that node
and wait for its
+ * response / timeout waiting for its response.
+ * @param key
+ * @param routedTo
+ * @param htl
+ * @param timeout
+ */
public void onFailed(Key key, PeerNode routedTo, short htl, int
timeout) {
long now = System.currentTimeMillis();
FailureTableEntry entry;
@@ -105,33 +114,6 @@
entry.addRequestor(requestor, now);
}
- /**
- * Called when a node kills a request: the request DNFs, is killed by a
RecentlyFailed message,
- * or times out. In any case this will create a FailureTableEntry.
- * @param key The key that was fetched.
- * @param htl The HTL it was fetched at.
- * @param requestors The nodes requesting it (if any).
- * @param requestedFrom The single node it was forwarded to, which
DNFed.
- * @param now The time at which the request was sent.
- * @param timeout The number of millis from when the request was sent
to when the failure block times out.
- * I.e. between 0 and REJECT_TIME. -1 indicates a RejectedOverload or
actual timeout.
- */
- public void onFailure(Key key, short htl, PeerNode[] requestors,
PeerNode[] requestedFrom, int timeout, long now) {
- FailureTableEntry entry;
- synchronized(this) {
- entry = (FailureTableEntry) entriesByKey.get(key);
- if(entry == null) {
- entry = new FailureTableEntry(key, htl,
requestors, requestedFrom);
- entriesByKey.push(key, entry);
- return;
- } else {
- entriesByKey.push(key, entry);
- }
- trimEntries(now);
- }
- entry.onFailure(htl, requestors, requestedFrom, timeout, now);
- }
-
private void trimEntries(long now) {
while(entriesByKey.size() > MAX_ENTRIES) {
entriesByKey.popKey();
Modified: trunk/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeDispatcher.java 2008-02-06 20:04:55 UTC
(rev 17609)
+++ trunk/freenet/src/freenet/node/NodeDispatcher.java 2008-02-06 20:07:51 UTC
(rev 17610)
@@ -290,7 +290,7 @@
} catch (NotConnectedException e) {
Logger.normal(this, "Rejecting insert request
from "+source.getPeer()+": "+e);
}
- node.failureTable.onFailure(key, htl, new PeerNode[] {
source }, null, -1, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, null, htl, -1,
source);
return true;
} else {
if(logMINOR) Logger.minor(this, "Locked "+id);
@@ -306,7 +306,7 @@
Logger.normal(this, "Rejecting (overload) data
request from "+source.getPeer()+": "+e);
}
node.unlockUID(id, isSSK, false, false, false);
- node.failureTable.onFailure(key, htl, new PeerNode[] {
source }, null, -1, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, null, htl, -1,
source);
return true;
}
//if(!node.lockUID(id)) return false;
Modified: trunk/freenet/src/freenet/node/RequestHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestHandler.java 2008-02-06 20:04:55 UTC
(rev 17609)
+++ trunk/freenet/src/freenet/node/RequestHandler.java 2008-02-06 20:07:51 UTC
(rev 17610)
@@ -150,7 +150,7 @@
if(rs == null) { // ran out of htl?
Message dnf = DMT.createFNPDataNotFound(uid);
status = RequestSender.DATA_NOT_FOUND; // for byte logging
- node.failureTable.onFailure(key, htl, sourceAsArray(), null,
FailureTable.REJECT_TIME, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, null, htl,
FailureTable.REJECT_TIME, source);
sendTerminal(dnf);
return;
}
@@ -228,7 +228,7 @@
if (now > responseDeadline) {
// Offer the data if there is any.
- node.failureTable.onFailure(key, htl, sourceAsArray(), null,
-1, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, null, htl, -1,
source);
Logger.error(this, "requestsender took too long to
respond to requestor ("+TimeUtil.formatTime((now - searchStartTime), 2,
true)+"/"+rs.getStatusString()+")");
applyByteCounts();
unregisterRequestHandlerWithNode();
Modified: trunk/freenet/src/freenet/node/RequestSender.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestSender.java 2008-02-06 20:04:55 UTC
(rev 17609)
+++ trunk/freenet/src/freenet/node/RequestSender.java 2008-02-06 20:07:51 UTC
(rev 17610)
@@ -383,7 +383,7 @@
// This used to be RNF, I dunno why
//???: finish(GENERATED_REJECTED_OVERLOAD,
null);
finish(DATA_NOT_FOUND, null, false);
- node.failureTable.onFailure(key, htl, sourceAsArray(),
pnArray(nodesRoutedTo), FailureTable.REJECT_TIME, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, null, htl,
FailureTable.REJECT_TIME, source);
return;
}
@@ -398,7 +398,7 @@
Logger.minor(this, "no more peers, but
overloads ("+rejectOverloads+"/"+routeAttempts+" overloaded)");
// Backtrack
finish(ROUTE_NOT_FOUND, null, false);
- node.failureTable.onFailure(key, htl, sourceAsArray(),
pnArray(nodesRoutedTo), -1, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, null, htl, -1, source);
return;
}
@@ -476,6 +476,7 @@
// Timeout waiting for Accepted
next.localRejectedOverload("AcceptedTimeout");
forwardRejectedOverload();
+ node.failureTable.onFailed(key, next, htl, (int)
(System.currentTimeMillis() - timeSentRequest));
// Try next node
break;
}
@@ -483,6 +484,7 @@
if(msg.getSpec() == DMT.FNPRejectedLoop) {
if(logMINOR) Logger.minor(this, "Rejected loop");
next.successNotOverload();
+ node.failureTable.onFailed(key, next, htl, (int)
(System.currentTimeMillis() - timeSentRequest));
// Find another node to route to
break;
}
@@ -494,6 +496,7 @@
if (msg.getBoolean(DMT.IS_LOCAL)) {
if(logMINOR) Logger.minor(this,
"Is local");
next.localRejectedOverload("ForwardRejectedOverload");
+ node.failureTable.onFailed(key, next, htl,
(int) (System.currentTimeMillis() - timeSentRequest));
if(logMINOR) Logger.minor(this,
"Local RejectedOverload, moving on to next peer");
// Give up on this one, try
another
break;
@@ -550,7 +553,7 @@
next.localRejectedOverload("FatalTimeout");
forwardRejectedOverload();
finish(TIMED_OUT, next, false);
- node.failureTable.onFailure(key, htl, sourceAsArray(),
pnArray(nodesRoutedTo), -1, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, next, htl, -1,
source);
return;
}
@@ -561,7 +564,7 @@
if(msg.getSpec() == DMT.FNPDataNotFound) {
next.successNotOverload();
finish(DATA_NOT_FOUND, next, false);
- node.failureTable.onFailure(key, htl, sourceAsArray(),
pnArray(nodesRoutedTo), FailureTable.REJECT_TIME, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, next, htl,
FailureTable.REJECT_TIME, source);
return;
}
@@ -626,7 +629,7 @@
// If there is, we will avoid sending requests for the
specified period.
// FIXME we need to create the FT entry.
finish(RECENTLY_FAILED, next, false);
- node.failureTable.onFailure(key, htl, sourceAsArray(),
pnArray(nodesRoutedTo), timeLeft, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key, next,
htl, timeLeft, source);
return;
}
@@ -635,6 +638,7 @@
short newHtl = msg.getShort(DMT.HTL);
if(newHtl < htl) htl = newHtl;
next.successNotOverload();
+ node.failureTable.onFailed(key, next, htl, (int)
(System.currentTimeMillis() - timeSentRequest));
break;
}
@@ -645,8 +649,10 @@
if (msg.getBoolean(DMT.IS_LOCAL)) {
//NB: IS_LOCAL means it's
terminal. not(IS_LOCAL) implies that the rejection message was forwarded from a
downstream node.
//"Local" from our peers
perspective, this has nothing to do with local requests (source==null)
+ node.failureTable.onFailed(key, next, htl,
(int) (System.currentTimeMillis() - timeSentRequest));
next.localRejectedOverload("ForwardRejectedOverload2");
- if(logMINOR) Logger.minor(this,
"Local RejectedOverload, moving on to next peer");
+ // Node in trouble suddenly??
+ Logger.normal(this, "Local
RejectedOverload after Accepted, moving on to next peer");
// Give up on this one, try
another
break;
}
@@ -692,7 +698,7 @@
} catch (KeyVerifyException e1) {
Logger.normal(this, "Got data
but verify failed: "+e1, e1);
finish(VERIFY_FAILURE, next,
false);
- node.failureTable.onFailure(key, htl,
sourceAsArray(), pnArray(nodesRoutedTo), -1, System.currentTimeMillis());
+
node.failureTable.onFinalFailure(key, next, htl, -1, source);
return;
}
finish(SUCCESS, next, false);
@@ -703,7 +709,7 @@
else
Logger.error(this, "Transfer failed
("+e.getReason()+"/"+RetrievalException.getErrString(e.getReason())+"): "+e, e);
finish(TRANSFER_FAILED, next, false);
- node.failureTable.onFailure(key, htl,
sourceAsArray(), pnArray(nodesRoutedTo), -1, System.currentTimeMillis());
+ node.failureTable.onFinalFailure(key,
next, htl, -1, source);
return;
}
} finally {
@@ -717,6 +723,7 @@
if(!(key instanceof NodeSSK)) {
Logger.error(this, "Got "+msg+" but expected a
different key type from "+next);
+ node.failureTable.onFailed(key, next, htl,
(int) (System.currentTimeMillis() - timeSentRequest));
break;
}
byte[] pubkeyAsBytes =
((ShortBuffer)msg.getObject(DMT.PUBKEY_AS_BYTES)).getData();
@@ -727,9 +734,11 @@
} catch (SSKVerifyException e) {
pubKey = null;
Logger.error(this, "Invalid pubkey from
"+source+" on "+uid+" ("+e.getMessage()+ ')', e);
+ node.failureTable.onFailed(key, next, htl,
(int) (System.currentTimeMillis() - timeSentRequest));
break; // try next node
} catch (CryptFormatException e) {
Logger.error(this, "Invalid pubkey from
"+source+" on "+uid+" ("+e+ ')');
+ node.failureTable.onFailed(key, next, htl,
(int) (System.currentTimeMillis() - timeSentRequest));
break; // try next node
}
if(sskData != null) {
@@ -745,6 +754,7 @@
if(!(key instanceof NodeSSK)) {
Logger.error(this, "Got "+msg+" but expected a
different key type from "+next);
+ node.failureTable.onFailed(key, next, htl,
(int) (System.currentTimeMillis() - timeSentRequest));
break;
}
@@ -765,15 +775,6 @@
}
}
- private PeerNode[] pnArray(HashSet nodesRoutedTo) {
- return (PeerNode[]) nodesRoutedTo.toArray(new
PeerNode[nodesRoutedTo.size()]);
- }
-
- private PeerNode[] sourceAsArray() {
- if(source == null) return null;
- else return new PeerNode[] { source };
- }
-
/**
* Finish fetching an SSK. We must have received the data, the headers and
the pubkey by this point.
* @param next The node we received the data from.