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.


Reply via email to