Author: toad
Date: 2005-12-03 23:02:36 +0000 (Sat, 03 Dec 2005)
New Revision: 7664

Modified:
   trunk/freenet/src/freenet/io/comm/DMT.java
   trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java
   trunk/freenet/src/freenet/node/InsertHandler.java
   trunk/freenet/src/freenet/node/InsertSender.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/Version.java
Log:
268: (mandatory)
Major changes to inserts:
Do search first, without waiting for transfers.
Then wait for transfers to complete - right down the tree.
So we can then:
a) Know reliably if downstream gets a load related timeout.
b) Do the search as fast as possible, and not go over the overall timeout due 
to unnecessary serialization

See Subject: [Tech] Insert complications

NOT TESTED! It compiles, but that's it. I'll probably test it on Monday.

Modified: trunk/freenet/src/freenet/io/comm/DMT.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/DMT.java  2005-12-03 20:38:15 UTC (rev 
7663)
+++ trunk/freenet/src/freenet/io/comm/DMT.java  2005-12-03 23:02:36 UTC (rev 
7664)
@@ -79,6 +79,7 @@
     public static final String DATA_INSERT_REJECTED_REASON = 
"dataInsertRejectedReason";
     public static final String STREAM_SEQNO = "streamSequenceNumber";
     public static final String IS_LOCAL = "isLocal";
+    public static final String ANY_TIMED_OUT = "anyTimedOut";

        //Diagnostic
        public static final MessageType ping = new MessageType("ping") {{
@@ -621,6 +622,18 @@
         return msg;
     }

+    public static final MessageType FNPInsertTransfersCompleted = new 
MessageType("FNPInsertTransfersCompleted") {{
+       addField(UID, Long.class);
+       addField(ANY_TIMED_OUT, Boolean.class);
+    }};
+
+    public static final Message createFNPInsertTransfersCompleted(long uid, 
boolean anyTimedOut) {
+       Message msg = new Message(FNPInsertTransfersCompleted);
+       msg.set(UID, uid);
+       msg.set(ANY_TIMED_OUT, anyTimedOut);
+       return msg;
+    }
+    
     public static final MessageType FNPRejectedTimeout = new 
MessageType("FNPTooSlow") {{
         addField(UID, Long.class);
     }};

Modified: trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java
===================================================================
--- trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java     2005-12-03 
20:38:15 UTC (rev 7663)
+++ trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java     2005-12-03 
23:02:36 UTC (rev 7664)
@@ -207,7 +207,7 @@

                                                long earliestSendTime = 
startCycleTime + delay;

-                                               if(earliestSendTime > 
hardLastPacketSendTime) {
+                                               if(earliestSendTime > 
newHardLastPacketSendTime) {
                                                        // Don't clog up other 
senders!
                                                        thenSend = false;
                                                        endTime = 
earliestSendTime;

Modified: trunk/freenet/src/freenet/node/InsertHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/InsertHandler.java   2005-12-03 20:38:15 UTC 
(rev 7663)
+++ trunk/freenet/src/freenet/node/InsertHandler.java   2005-12-03 23:02:36 UTC 
(rev 7664)
@@ -105,6 +105,8 @@
         // Now create an InsertSender, or use an existing one, or
         // discover that the data is in the store.

+        // From this point onwards, if we return cleanly we must go through 
finish().
+        
         prb = new PartiallyReceivedBlock(Node.PACKETS_IN_BLOCK, 
Node.PACKET_SIZE);
         if(htl > 0)
             sender = node.makeInsertSender(key, htl, uid, source, headers, 
prb, false, closestLoc, true);
@@ -154,6 +156,7 @@
                 // Cancel the sender
                 sender.receiveFailed(); // tell it to stop if it hasn't 
already failed... unless it's sending from store
                 // Nothing else we can do
+                finish();
                 return;
             }

@@ -190,6 +193,7 @@
                 if(status == InsertSender.TIMED_OUT ||
                                status == 
InsertSender.GENERATED_REJECTED_OVERLOAD)
                        canCommit = true;
+                finish();
                 return;
             }

@@ -214,6 +218,7 @@
             Logger.error(this, "Unknown status code: 
"+sender.getStatusString());
             msg = DMT.createFNPRejectedOverload(uid, true);
             source.send(msg);
+            finish();
             return;
         }
         } catch (Throwable t) {
@@ -225,6 +230,8 @@
     }

     private boolean canCommit = false;
+    private boolean sentCompletion = false;
+    private Object sentCompletionLock = new Object();

     /**
      * If canCommit, and we have received all the data, and it
@@ -232,7 +239,36 @@
      */
     private void finish() {
         Message toSend = null;
+        // Wait for completion
+        boolean sentCompletionWasSet;
+        synchronized(sentCompletionLock) {
+               sentCompletionWasSet = sentCompletion;
+               sentCompletion = true;
+        }
+        if(!sentCompletionWasSet) {
+               while(true) {
+                       synchronized(sender) {
+                               if(sender.completed()) {
+                                       break;
+                               }
+                               try {
+                                       sender.wait(10*1000);
+                               } catch (InterruptedException e) {
+                                       // Loop
+                               }
+                       }
+               }
+               Message m = DMT.createFNPInsertTransfersCompleted(uid, 
sender.anyTransfersFailed());
+               try {
+                       source.sendAsync(m, null);
+               } catch (NotConnectedException e1) {
+                       Logger.minor(this, "Not connected: "+source+" for 
"+this);
+                       // May need to commit anyway...
+               }
+        }
+        
         synchronized(this) { // REDFLAG do not use synch(this) for any other 
purpose!
+               if(prb != null || prb.isAborted()) return;
             try {
                 if(!canCommit) return;
                 if(!prb.allReceived()) return;

Modified: trunk/freenet/src/freenet/node/InsertSender.java
===================================================================
--- trunk/freenet/src/freenet/node/InsertSender.java    2005-12-03 20:38:15 UTC 
(rev 7663)
+++ trunk/freenet/src/freenet/node/InsertSender.java    2005-12-03 23:02:36 UTC 
(rev 7664)
@@ -1,8 +1,7 @@
 package freenet.node;

 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.Vector;

 import freenet.io.comm.DMT;
 import freenet.io.comm.DisconnectedException;
@@ -17,20 +16,94 @@

 public final class InsertSender implements Runnable {

+       private class AwaitingCompletion {
+               
+               /** Node we are waiting for response from */
+               final PeerNode pn;
+               /** We may be sending data to that node */
+               BlockTransmitter bt;
+               /** Have we received notice of the downstream success
+                * or failure of dependant transfers from that node?
+                * Includes timing out. */
+               boolean receivedCompletionNotice = false;
+               /** Timed out - didn't receive completion notice in
+                * the allotted time?? */
+               boolean completionTimedOut = false;
+               /** Was the notification of successful transfer? */
+               boolean completionSucceeded;
+               
+               /** Have we completed the immediate transfer? */
+               boolean completedTransfer = false;
+               /** Did it succeed? */
+               boolean transferSucceeded = false;
+               
+               AwaitingCompletion(PeerNode pn, PartiallyReceivedBlock prb) {
+                       this.pn = pn;
+                       bt = new BlockTransmitter(node.usm, pn, uid, prb);
+                       Sender s = new Sender(this);
+            Thread senderThread = new Thread(s, "Sender for "+uid+" to 
"+pn.getPeer());
+            senderThread.setDaemon(true);
+            senderThread.start();
+            makeCompletionWaiter();
+               }
+               
+               void completed(boolean timeout, boolean success) {
+                       synchronized(this) {
+                               if(timeout)
+                                       completionTimedOut = true;
+                               else
+                                       completionSucceeded = success;
+                               receivedCompletionNotice = true;
+                               notifyAll();
+                       }
+                       synchronized(nodesWaitingForCompletion) {
+                               nodesWaitingForCompletion.notifyAll();
+                       }
+               }
+               
+               void completedTransfer(boolean success) {
+                       synchronized(this) {
+                               transferSucceeded = success;
+                               completedTransfer = true;
+                               notifyAll();
+                       }
+                       synchronized(nodesWaitingForCompletion) {
+                               nodesWaitingForCompletion.notifyAll();
+                       }
+                       if(!success) {
+                               synchronized(InsertSender.this) {
+                                       transferTimedOut = true;
+                                       InsertSender.this.notifyAll();
+                               }
+                       }
+               }
+       }
+       
     public class Sender implements Runnable {
-
-       public Sender(BlockTransmitter bt) {
-               this.bt = bt;
-       }
-
-       // We will often have multiple simultaneous senders, so we need them to 
send separately.
+       
+       final AwaitingCompletion completion;
        final BlockTransmitter bt;

+       public Sender(AwaitingCompletion ac) {
+               this.bt = ac.bt;
+               this.completion = ac;
+       }
+       
                public void run() {
-                       bt.send();
+                       try {
+                               bt.send();
+                               if(bt.failedDueToOverload()) {
+                                       completion.completedTransfer(false);
+                               } else {
+                                       completion.completedTransfer(true);
+                               }
+                       } catch (Throwable t) {
+                               completion.completedTransfer(false);
+                               Logger.error(this, "Caught "+t, t);
+                       }
                }
        }
-
+    
        InsertSender(NodeCHK myKey, long uid, byte[] headers, short htl, 
             PeerNode source, Node node, PartiallyReceivedBlock prb, boolean 
fromStore, double closestLocation) {
         this.myKey = myKey;
@@ -44,8 +117,6 @@
         this.fromStore = fromStore;
         this.closestLocation = closestLocation;
         this.startTime = System.currentTimeMillis();
-        senderThreads = new LinkedList();
-        blockSenders = new LinkedList();
         Thread t = new Thread(this, "InsertSender for UID "+uid+" on 
"+node.portNumber+" at "+System.currentTimeMillis());
         t.setDaemon(true);
         t.start();
@@ -53,7 +124,8 @@

     // Constants
     static final int ACCEPTED_TIMEOUT = 10000;
-    static final int PUT_TIMEOUT = 120000;
+    static final int SEARCH_TIMEOUT = 60000;
+    static final int TRANSFER_COMPLETION_TIMEOUT = 120000;

     // Basics
     final NodeCHK myKey;
@@ -68,11 +140,25 @@
     private boolean receiveFailed = false;
     final double closestLocation;
     final long startTime;
-    private BlockTransmitter bt;
-    private final LinkedList senderThreads;
-    private final LinkedList blockSenders;
     private boolean sentRequest;

+    /** List of nodes we are waiting for either a transfer completion
+     * notice or a transfer completion from. */
+    private Vector nodesWaitingForCompletion;
+    
+    /** Have all transfers completed and all nodes reported completion status? 
*/
+    private boolean allTransfersCompleted = false;
+    
+    /** Has a transfer timed out, either directly or downstream? */
+    private boolean transferTimedOut = false;
+    
+    /** Runnable which waits for completion of all transfers */
+    private CompletionWaiter cw = null;
+
+    /** Time at which we set status to a value other than NOT_FINISHED */
+    private long setStatusTime = -1;
+    
+    
     private int status = -1;
     /** Still running */
     static final int NOT_FINISHED = -1;
@@ -223,7 +309,6 @@
             PartiallyReceivedBlock prbNow;
             prbNow = prb;
             dataInsert = DMT.createFNPDataInsert(uid, headers);
-            bt = new BlockTransmitter(node.usm, next, uid, prbNow);
             /** What are we waiting for now??:
              * - FNPRouteNotFound - couldn't exhaust HTL, but send us the 
              *   data anyway please
@@ -234,12 +319,12 @@
              *   inserting.
              */

-            MessageFilter mfInsertReply = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(PUT_TIMEOUT).setType(DMT.FNPInsertReply);
-            mfRejectedOverload.setTimeout(PUT_TIMEOUT);
+            MessageFilter mfInsertReply = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(SEARCH_TIMEOUT).setType(DMT.FNPInsertReply);
+            mfRejectedOverload.setTimeout(SEARCH_TIMEOUT);
             mfRejectedOverload.clearOr();
-            MessageFilter mfRouteNotFound = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(PUT_TIMEOUT).setType(DMT.FNPRouteNotFound);
-            MessageFilter mfDataInsertRejected = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(PUT_TIMEOUT).setType(DMT.FNPDataInsertRejected);
-            MessageFilter mfTimeout = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(PUT_TIMEOUT).setType(DMT.FNPRejectedTimeout);
+            MessageFilter mfRouteNotFound = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(SEARCH_TIMEOUT).setType(DMT.FNPRouteNotFound);
+            MessageFilter mfDataInsertRejected = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(SEARCH_TIMEOUT).setType(DMT.FNPDataInsertRejected);
+            MessageFilter mfTimeout = 
MessageFilter.create().setSource(next).setField(DMT.UID, 
uid).setTimeout(SEARCH_TIMEOUT).setType(DMT.FNPRejectedTimeout);

             mf = 
mfInsertReply.or(mfRouteNotFound.or(mfDataInsertRejected.or(mfTimeout.or(mfRejectedOverload))));

@@ -249,12 +334,11 @@

             Logger.minor(this, "Sending data");
             if(receiveFailed) return;
-            Sender s = new Sender(bt);
-            Thread senderThread = new Thread(s, "Sender for "+uid+" to 
"+next.getPeer());
-            senderThread.setDaemon(true);
-            senderThread.start();
-            senderThreads.add(senderThread);
-            blockSenders.add(bt);
+            AwaitingCompletion ac = new AwaitingCompletion(next, prbNow);
+            synchronized(nodesWaitingForCompletion) {
+               nodesWaitingForCompletion.add(ac);
+               nodesWaitingForCompletion.notifyAll();
+            }

             while (true) {

@@ -397,18 +481,9 @@
         if(status != NOT_FINISHED)
                throw new IllegalStateException("finish() called with "+code+" 
when was already "+status);

-        for(Iterator i = blockSenders.iterator();i.hasNext();) {
-               BlockTransmitter bt = (BlockTransmitter) i.next();
-               Logger.minor(this, "Waiting for "+bt);
-               bt.waitForComplete();
-               if(bt.failedDueToOverload() && (status == SUCCESS || status == 
ROUTE_NOT_FOUND)) {
-                       forwardRejectedOverload();
-                       ((PeerNode)bt.getDestination()).localRejectedOverload();
-                       break;
-               }
-        }
+        setStatusTime = System.currentTimeMillis();

-        if(code == ROUTE_NOT_FOUND && blockSenders.isEmpty())
+        if(code == ROUTE_NOT_FOUND && nodesWaitingForCompletion.isEmpty())
                code = ROUTE_REALLY_NOT_FOUND;

         status = code;
@@ -416,6 +491,24 @@
         synchronized(this) {
             notifyAll();
         }
+
+        Logger.minor(this, "Set status code: "+getStatusString());
+        
+        // Now wait for transfers, or for downstream transfer notifications.
+        
+        synchronized(this) {
+               while(!allTransfersCompleted) {
+                       try {
+                                       wait(10*1000);
+                               } catch (InterruptedException e) {
+                                       // Try again
+                               }
+               }
+        }
+        
+        synchronized(this) {
+            notifyAll();
+        }
         Logger.minor(this, "Returning from finish()");
     }

@@ -459,4 +552,149 @@
        public boolean sentRequest() {
                return sentRequest;
        }
+       
+       private synchronized void makeCompletionWaiter() {
+               if(cw != null) {
+                       cw = new CompletionWaiter();
+                       Thread t = new Thread(cw, "Completion waiter for "+uid);
+                       t.setDaemon(true);
+                       t.start();
+               }
+       }
+       
+       private class CompletionWaiter implements Runnable {
+               
+               public void run() {
+outer:         while(true) {                   
+                       AwaitingCompletion[] waiters;
+                       synchronized(nodesWaitingForCompletion) {
+                               waiters = new 
AwaitingCompletion[nodesWaitingForCompletion.size()];
+                               waiters = (AwaitingCompletion[]) 
nodesWaitingForCompletion.toArray(waiters);
+                       }
+                       
+                       // First calculate the timeout
+                       
+                       int timeout;
+                       boolean noTimeLeft = false;
+
+                       long now = System.currentTimeMillis();
+                       if(status == NOT_FINISHED) {
+                               // Wait 5 seconds, then try again
+                               timeout = 5000;
+                       } else {
+                               // Completed, wait for everything
+                               timeout = (int)Math.min(Integer.MAX_VALUE, 
(setStatusTime + TRANSFER_COMPLETION_TIMEOUT) - now);
+                       }
+                       if(timeout <= 0) {
+                               noTimeLeft = true;
+                               timeout = 1;
+                       }
+                       
+                       MessageFilter mf = null;
+                       for(int i=0;i<waiters.length;i++) {
+                               AwaitingCompletion awc = waiters[i];
+                               if(!awc.pn.isConnected()) {
+                                       Logger.normal(this, "Disconnected: 
"+awc.pn+" in "+InsertSender.this);
+                                       continue;
+                               }
+                               if(!awc.receivedCompletionNotice) {
+                                       MessageFilter m =
+                                               
MessageFilter.create().setField(DMT.UID, 
uid).setType(DMT.FNPInsertTransfersCompleted).setSource(awc.pn).setTimeout(timeout);
+                                       if(mf == null)
+                                               mf = m;
+                                       else
+                                               mf = m.or(mf);
+                               }
+                       }
+                       
+                       if(mf == null) {
+                               if(status != NOT_FINISHED) {
+                                       if(noTimeLeft) {
+                                               // All done!
+                                               Logger.minor(this, "Completed, 
status="+getStatusString()+", nothing left to wait for.");
+                                               synchronized(InsertSender.this) 
{
+                                                       allTransfersCompleted = 
true;
+                                                       
InsertSender.this.notifyAll();
+                                               }
+                                               return;
+                                       }
+                               }
+                               synchronized(nodesWaitingForCompletion) {
+                                       try {
+                                               
nodesWaitingForCompletion.wait(timeout);
+                                       } catch (InterruptedException e) {
+                                               // Go back around the loop
+                                       }
+                               }
+                       } else {
+                               Message m;
+                               try {
+                                       m = node.usm.waitFor(mf);
+                               } catch (DisconnectedException e) {
+                                       // Which one? I have no idea.
+                                       // Go around the loop again.
+                                       continue;
+                               }
+                               if(m != null) {
+                                       // Process message
+                                       PeerNode pn = (PeerNode) m.getSource();
+                                       boolean processed = false;
+                                       for(int i=0;i<waiters.length;i++) {
+                                               PeerNode p = waiters[i].pn;
+                                               if(p == pn) {
+                                                       boolean anyTimedOut = 
m.getBoolean(DMT.ANY_TIMED_OUT);
+                                                       
waiters[i].completed(false, !anyTimedOut);
+                                                       if(anyTimedOut) {
+                                                               
synchronized(InsertSender.this) {
+                                                                       
transferTimedOut = true;
+                                                                       
InsertSender.this.notifyAll();
+                                                               }
+                                                       }
+                                                       processed = true;
+                                                       
if(waiters[i].completedTransfer) {
+                                                               
if(!waiters[i].transferSucceeded) {
+                                                                       
synchronized(InsertSender.this) {
+                                                                               
transferTimedOut = true;
+                                                                               
InsertSender.this.notifyAll();
+                                                                       }
+                                                               }
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                                       if(!processed) {
+                                               Logger.error(this, "Did not 
process message: "+m+" on "+this);
+                                       }
+                               } else {
+                                       if(nodesWaitingForCompletion.size() > 
waiters.length) {
+                                               // Added another one
+                                               Logger.minor(this, "Looping: 
waiters="+waiters.length+" but waiting="+nodesWaitingForCompletion.size());
+                                               continue;
+                                       }
+                                       if(noTimeLeft) {
+                                               Logger.minor(this, "Overall 
timeout on "+InsertSender.this);
+                                               for(int 
i=0;i<waiters.length;i++) {
+                                                       
if(!waiters[i].receivedCompletionNotice)
+                                                               
waiters[i].completed(false, false);
+                                               }
+                                               synchronized(InsertSender.this) 
{
+                                                       transferTimedOut = true;
+                                                       allTransfersCompleted = 
true;
+                                                       
InsertSender.this.notifyAll();
+                                               }
+                                               return;
+                                       }
+                               }
+                       }
+               }
+               }
+       }
+
+       public boolean completed() {
+               return allTransfersCompleted;
+       }
+
+       public boolean anyTransfersFailed() {
+               return transferTimedOut;
+       }
 }

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2005-12-03 20:38:15 UTC (rev 
7663)
+++ trunk/freenet/src/freenet/node/Node.java    2005-12-03 23:02:36 UTC (rev 
7664)
@@ -523,6 +523,7 @@
                     MAX_HTL, uid, null, headers, prb, false, 
lm.getLocation().getValue(), cache);
         }
         boolean hasForwardedRejectedOverload = false;
+        // Wait for status
         while(true) {
                synchronized(is) {
                        if(is.getStatus() == InsertSender.NOT_FINISHED) {
@@ -532,52 +533,74 @@
                                        // Ignore
                                }
                        }
-                       if((!hasForwardedRejectedOverload) && 
is.receivedRejectedOverload()) {
-                               insertThrottle.requestRejectedOverload();
-                       }
-                       if(is.getStatus() == InsertSender.NOT_FINISHED) 
continue;
+                       if(is.getStatus() != InsertSender.NOT_FINISHED) break;
                }
-               // Finished?
-               if(!hasForwardedRejectedOverload) {
-                       // Is it ours? Did we send a request?
-                       if(is.sentRequest() && is.uid == uid && (is.getStatus() 
== InsertSender.ROUTE_NOT_FOUND || is.getStatus() == InsertSender.SUCCESS)) {
-                               // It worked!
-                               long endTime = System.currentTimeMillis();
-                               long len = endTime - startTime;
-                               insertThrottle.requestCompleted(len);
-                       }
+               if((!hasForwardedRejectedOverload) && 
is.receivedRejectedOverload()) {
+                       hasForwardedRejectedOverload = true;
+                       insertThrottle.requestRejectedOverload();
+               }
+        }
+        
+        // Wait for completion
+        while(true) {
+               synchronized(is) {
+                       if(is.completed()) break;
+                       try {
+                                       is.wait(10*1000);
+                               } catch (InterruptedException e) {
+                                       // Go around again
+                               }
                }
-               if(is.getStatus() == InsertSender.SUCCESS) {
-                       Logger.normal(this, "Succeeded inserting "+block);
-                       return;
-               } else {
-                       int status = is.getStatus();
-                       String msg = "Failed inserting "+block+" : 
"+is.getStatusString();
-                       if(status == InsertSender.ROUTE_NOT_FOUND)
-                               msg += " - this is normal on small networks; 
the data will still be propagated, but it can't find the 20+ nodes needed for 
full success";
-                       if(is.getStatus() != InsertSender.ROUTE_NOT_FOUND)
-                               Logger.error(this, msg);
-                       else
-                               Logger.normal(this, msg);
-                       switch(is.getStatus()) {
-                       case InsertSender.NOT_FINISHED:
-                               Logger.error(this, "IS still running in 
putCHK!: "+is);
-                               throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
-                       case InsertSender.GENERATED_REJECTED_OVERLOAD:
-                       case InsertSender.TIMED_OUT:
-                               throw new 
LowLevelPutException(LowLevelPutException.REJECTED_OVERLOAD);
-                       case InsertSender.ROUTE_NOT_FOUND:
-                               throw new 
LowLevelPutException(LowLevelPutException.ROUTE_NOT_FOUND);
-                       case InsertSender.ROUTE_REALLY_NOT_FOUND:
-                               throw new 
LowLevelPutException(LowLevelPutException.ROUTE_REALLY_NOT_FOUND);
-                       case InsertSender.INTERNAL_ERROR:
-                               throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
-                       default:
-                               Logger.error(this, "Unknown InsertSender code 
in putCHK: "+is.getStatus()+" on "+is);
-                               throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
-                       }
+               if(is.anyTransfersFailed() && (!hasForwardedRejectedOverload)) {
+                       hasForwardedRejectedOverload = true; // not strictly 
true but same effect
+                       insertThrottle.requestRejectedOverload();
+               }                       
+        }
+        
+        Logger.minor(this, "Completed "+uid+" 
overload="+hasForwardedRejectedOverload+" "+is.getStatusString());
+        
+        // Finished?
+        if(!hasForwardedRejectedOverload) {
+               // Is it ours? Did we send a request?
+               if(is.sentRequest() && is.uid == uid && (is.getStatus() == 
InsertSender.ROUTE_NOT_FOUND 
+                               || is.getStatus() == InsertSender.SUCCESS)) {
+                       // It worked!
+                       long endTime = System.currentTimeMillis();
+                       long len = endTime - startTime;
+                       insertThrottle.requestCompleted(len);
                }
         }
+        
+        if(is.getStatus() == InsertSender.SUCCESS) {
+               Logger.normal(this, "Succeeded inserting "+block);
+               return;
+        } else {
+               int status = is.getStatus();
+               String msg = "Failed inserting "+block+" : 
"+is.getStatusString();
+               if(status == InsertSender.ROUTE_NOT_FOUND)
+                       msg += " - this is normal on small networks; the data 
will still be propagated, but it can't find the 20+ nodes needed for full 
success";
+               if(is.getStatus() != InsertSender.ROUTE_NOT_FOUND)
+                       Logger.error(this, msg);
+               else
+                       Logger.normal(this, msg);
+               switch(is.getStatus()) {
+               case InsertSender.NOT_FINISHED:
+                       Logger.error(this, "IS still running in putCHK!: "+is);
+                       throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
+               case InsertSender.GENERATED_REJECTED_OVERLOAD:
+               case InsertSender.TIMED_OUT:
+                       throw new 
LowLevelPutException(LowLevelPutException.REJECTED_OVERLOAD);
+               case InsertSender.ROUTE_NOT_FOUND:
+                       throw new 
LowLevelPutException(LowLevelPutException.ROUTE_NOT_FOUND);
+               case InsertSender.ROUTE_REALLY_NOT_FOUND:
+                       throw new 
LowLevelPutException(LowLevelPutException.ROUTE_REALLY_NOT_FOUND);
+               case InsertSender.INTERNAL_ERROR:
+                       throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
+               default:
+                       Logger.error(this, "Unknown InsertSender code in 
putCHK: "+is.getStatus()+" on "+is);
+                       throw new 
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
+               }
+        }
     }

     public boolean shouldRejectRequest() {

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2005-12-03 20:38:15 UTC (rev 
7663)
+++ trunk/freenet/src/freenet/node/Version.java 2005-12-03 23:02:36 UTC (rev 
7664)
@@ -20,10 +20,10 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       public static final int buildNumber = 267;
+       public static final int buildNumber = 268;

        /** Oldest build of Fred we will talk to */
-       public static final int lastGoodBuild = 267;
+       public static final int lastGoodBuild = 268;

        /** The highest reported build of fred */
        public static int highestSeenBuild = buildNumber;


Reply via email to