Update of /cvsroot/freenet/freenet/src/freenet/node/states/data
In directory sc8-pr-cvs1:/tmp/cvs-serv25857/src/freenet/node/states/data

Modified Files:
      Tag: stable
        DataState.java ReceiveData.java SendData.java 
Added Files:
      Tag: stable
        TrailerWriteCallbackMessage.java 
Log Message:
5029: Merge from unstable after months of work. MASSIVE changes.
Highlights:
* Next Generation Routing, massive related changes
* Major changes to handling of messages and connections (PeerHandler and related 
changes)
* Even more non-blocking I/O
* Documentation improvements
* Lots of new diagnostics and config options
* Lots of bug fixes and performance tweaking
* Probably lots of new bugs too!


--- NEW FILE: TrailerWriteCallbackMessage.java ---
package freenet.node.states.data;

import freenet.*;
import freenet.node.*;

/**
 * Message form of the TrailerWriteCallback. Used by states that need to do
 * expensive stuff e.g. blocking reads after the write succeeds.
 */
class TrailerWriteCallbackMessage extends EventMessageObject implements 
TrailerWriteCallback {
    boolean finished;
    boolean success;
    Node n;
    SendData st;
    public TrailerWriteCallbackMessage(long id, Node n, SendData st) {
        super(id, false); // Data states are internal, see DataStateInitiator
        this.n = n;
        this.st = st;
        reset();
    }
    
    public void reset() {
        finished = false;
        success = false;
    }
    
    public void closed() {
        success = false;
        finished = true;
        n.schedule(this);
    }
    
    public void written() {
        success = true;
        finished = true;
        n.schedule(this);
    }
    
    public String toString() {
        return getClass().getName() + ":" + finished + ":" + success;
    }
    
    public long bytesAvailable() {
        return st.bytesAvailable();
    }
}

Index: DataState.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/states/data/DataState.java,v
retrieving revision 1.1.1.1.6.1
retrieving revision 1.1.1.1.6.2
diff -u -w -r1.1.1.1.6.1 -r1.1.1.1.6.2
--- DataState.java      1 Jul 2003 02:27:16 -0000       1.1.1.1.6.1
+++ DataState.java      28 Oct 2003 20:20:43 -0000      1.1.1.1.6.2
@@ -48,7 +48,7 @@
     }
     
     public String toString() {
-       return getClass().getName()+": "+Long.toHexString(id)+"/"+
+       return super.toString()+": "+Long.toHexString(id)+"/"+
            Long.toHexString(parent);
     }
 }

Index: ReceiveData.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/states/data/ReceiveData.java,v
retrieving revision 1.17.6.3
retrieving revision 1.17.6.4
diff -u -w -r1.17.6.3 -r1.17.6.4
--- ReceiveData.java    3 Jul 2003 01:37:26 -0000       1.17.6.3
+++ ReceiveData.java    28 Oct 2003 20:20:43 -0000      1.17.6.4
@@ -59,7 +59,7 @@
     }
 
     public final void commit() throws IOException, KeyCollisionException {
-       if(Core.logger.shouldLog(Logger.DEBUG))
+       if(Core.logger.shouldLog(Logger.DEBUG,this))
           Core.logger.log(this, "Committing "+this, Core.logger.DEBUG);
           if (out != null)
           out.commit();
@@ -103,12 +103,15 @@
         byte[] buffer = new byte[Core.blockSize];
         long moved = 0;
         
-       boolean logDEBUG = n.logger.shouldLog(Logger.DEBUG);
+       boolean logDEBUG = n.logger.shouldLog(Logger.DEBUG,this);
        
         try {
             while (moved < length) {
                 inWrite = false;
                 int m = data.read(buffer, 0, (int) Math.min(length - moved, 
buffer.length));
+               if(logDEBUG)
+                   n.logger.log(this, "Read "+m+" bytes ("+this+")",
+                                Logger.DEBUG);
                 if (m < 0) {
                     throw new IOException("Could not read all the expected "+
                                          "data, read "+moved+" of "+length+
@@ -125,6 +128,9 @@
                
                 if (result != -1) throw new CancelledIOException();
                 out.write(buffer, 0, m);
+               if(logDEBUG)
+                   n.logger.log(this, "Written "+m+" bytes ("+this+")",
+                                Logger.DEBUG);
             }
            if(logDEBUG) n.logger.log(this, "Closing, moved "+moved+" of "+
                                      length+" bytes for "+Long.

Index: SendData.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/states/data/SendData.java,v
retrieving revision 1.13.6.2
retrieving revision 1.13.6.3
diff -u -w -r1.13.6.2 -r1.13.6.3
--- SendData.java       23 Aug 2003 12:04:42 -0000      1.13.6.2
+++ SendData.java       28 Oct 2003 20:20:43 -0000      1.13.6.3
@@ -7,6 +7,7 @@
 import freenet.support.*;
 import freenet.support.io.*;
 import java.io.*;
+import java.util.*;
 
 
 /**
@@ -23,28 +24,63 @@
 
 public class SendData extends DataState {
 
-    private final OutputStream send;
+    private final TrailerWriter send;
     private final KeyInputStream in;
+    private final TrailerWriteCallbackMessage myTWCM; // Use a message because of 
blocking I/O from store
     private boolean closedSend = false, closedIn = false;
     private final long length, partSize;
     private Exception abortedException = null;
     private volatile int result = -1;
     private boolean silent = false;
+    private boolean inPaddingMode = false;
+    private long paddingLength = 0;
+    private long sentPadding = 0;
+    private int lastPacketLength = 0;
+    private Node n;
+    boolean logDEBUG = true;
+    boolean inWrite = false;
+    long moved = 0;
+    byte[] buffer = null;
+    int bufferEndPtr = 0;
+    int m = 0;
+    private boolean hadDSI = false;
+    private boolean waitingForWriteNotify = false;
     
     
-    public SendData(long id, long parent, OutputStream send,
-                    KeyInputStream in, long length, long partSize) {
+    public SendData(long id, long parent, TrailerWriter send,
+                    KeyInputStream in, long length, long partSize,
+                   Node n) {
         super(id, parent);
         this.send     = send;
         this.in       = in;
+       if(in == null) throw new IllegalArgumentException("null in");
         this.length   = length;
         this.partSize = partSize;
+       this.n        = n;
+       myTWCM = new TrailerWriteCallbackMessage(id, n, this);
+       logDEBUG = n.logger.shouldLog(Logger.DEBUG,this);
+       if(logDEBUG)
+           n.logger.log(this, "Creating SendData("+this+")", Logger.DEBUG);
+    }
+    
+    public String toString() {
+       return super.toString()+": send="+send+", in="+in+", moved="+moved+"/"+
+           length+", partSize="+partSize+",result="+result+
+           ",lastPacketLength="+lastPacketLength+
+           (paddingLength != 0 ? (",sentPadding="+sentPadding+"/"+paddingLength) : 
"");
     }
     
     public final long length() {
        return length;
     }
     
+    public final long bytesAvailable() {
+       if(inPaddingMode)
+           return paddingLength - sentPadding;
+       else
+           return in.realLength() - moved;
+    }
+    
     public final String getName() {
         return "Sending Data";
     }
@@ -55,7 +91,7 @@
     public final void abort(int cb) {
         silent = true;
         result = cb;
-       if(Core.logger.shouldLog(Logger.DEBUG)) {
+       if(Core.logger.shouldLog(Logger.DEBUG,this)) {
            abortedException = new Exception("debug");
            Core.logger.log(this, "Aborted send for "+
                            Long.toHexString(parent)+" with cb="+
@@ -72,9 +108,7 @@
        try {
            if(!closedIn) in.close();
        } catch (IOException e) {};
-       try {
-           if(!closedSend) send.close();
-       } catch (IOException e) {};
+       if(send != null && !closedSend) send.close();
     }
 
     /** Sheesh!  We're too overworked to even try to write CB_ABORTED.
@@ -83,165 +117,390 @@
         try {
             in.close();
            closedIn = true;
-        }
-        catch (IOException e) {
+        } catch (IOException e) {
             n.logger.log(this, "I/O error closing KeyInputStream",
                          e, Logger.ERROR);
         }
-        try {
-            send.close();
+       if(send != null) send.close();
            closedSend = true;
         }
-        catch (IOException e) {
-            n.logger.log(this, "I/O error closing data send stream",
-                         e, Logger.MINOR);
-        }
-    }
 
-    boolean inWrite = false;
-    long moved = 0;
-    byte[] buffer = null;
-    int m = 0;
 
+    /* Async sending
+     *
+     * received(n, DataStateInitiator) ->
+     *  Reset buffer pointer
+     *  Read into buffer
+     *  Start write
+     *
+     * closed() ->
+     *  Set CB to CB_SEND_CONN_DIED
+     *  Run the block that used to be finally in received(..) to finish properly
+     *
+     * written() ->
+     *  Reset buffer pointer
+     *  Read into buffer
+     *  Start write
+     */
     public State received(Node n, MessageObject mo) throws BadStateException {
-        if (!(mo instanceof DataStateInitiator))
+               boolean isDSI = (mo instanceof DataStateInitiator);
+               if (hadDSI)
+                       isDSI = false;
+               boolean isTWCM = (mo == myTWCM);
+               if (!(isDSI || isTWCM))
             throw new BadStateException("expecting DataStateInitiator");
 
-        // if there is an IOException, this says
-        // whether it was while writing to the store
-        inWrite = false;
+               if (isDSI) {
+                       hadDSI = true;
         moved = 0;
        m = 0;
+               }
        
-       boolean logDEBUG = n.logger.shouldLog(Logger.DEBUG);
+               logDEBUG = n.logger.shouldLog(Logger.DEBUG, this);
        
-        try {
+               if (isTWCM) {
+                       waitingForWriteNotify = false;
+                       if (logDEBUG) n.logger.log(this, "Got " + myTWCM + " for " + 
this, Logger.DEBUG);
+                       if (!myTWCM.finished) {
+                               n.logger.log(this, "Got a TWCM that was not finished!: 
" + myTWCM + " for " + this, Logger.ERROR);
+                               return this;
+                       }
+                       if (!myTWCM.success) {
+                               result = Presentation.CB_SEND_CONN_DIED;
+                               if (handleThrowable(null, true) == null)
+                                       return null;
+                       } else {
+                               if (inPaddingMode)
+                                       sentPadding += lastPacketLength;
+                               else
+                                       moved += lastPacketLength;
+                       }
+               }
+
+               if (isDSI)
             buffer = new byte[Core.blockSize];
-            while (moved < length) {
-                inWrite = false;
-                if (result != -1) throw new CancelledIOException();
-                int m = in.read(buffer, 0, (int) Math.min(length - moved, 
buffer.length));
-                if (m == -1) {
-                   throw new IOException("Stopped short of full transfer");
+
+               if (!inPaddingMode) {
+                       try {
+                               bufferEndPtr = doRead();
+                               if (bufferEndPtr == -1)
+                                       throw new IOException("read failed: " + this);
+                       } catch (Throwable t) {
+                               return handleThrowable(t, false); // will do 
termination and failure code
                }
-               inWrite = true;
-               if(logDEBUG)
-                   n.logger.log(this, "Read "+(moved+m)+" of "+length+
-                                " bytes for "+Long.toHexString(parent)+" ("+in+")",
-                                Logger.DEBUG);
-                send.write(buffer, 0, m);
-                moved += m;
-               if(logDEBUG)
-                   n.logger.log(this, "Moved "+moved+" of "+length+" bytes for "+
-                                Long.toHexString(parent)+" ("+in+")",
-                                Logger.DEBUG);
             }
-            send.close();
-           closedSend = true;
-            result = Presentation.CB_OK;
+               try {
+                       if (inPaddingMode)
+                               sendWritePadding();
+                       else
+                               startWrite(bufferEndPtr);
+               } catch (Throwable t) {
+                       return handleThrowable(t, true);
         }
-        catch (CancelledIOException e) {
-           if(logDEBUG)
-               n.logger.log(this, "Cancelled IO: "+abortedException+" for "+
-                            Long.toHexString(parent), abortedException, 
-                            Logger.DEBUG);
-       }  // result already set
-        //catch (BadDataException e) {
-        //    result = e.getFailureCode();
-        //}
-        catch (IOException e) {
-            // if it was aborted we can expect the aborter to set the failure
-            // code.
-            result = (inWrite ? Presentation.CB_SEND_CONN_DIED
-                      : in.getFailureCode());
-            if (result == -1) // it broke some time between writing and reading
-               {
+               return finish(); // Must check whether we are actually finished!
+       }
+    
+    /**
+     * Read bytes from the store into the buffer, starting at the beginning.
+     * Return the number read.
+     * @throws IOException if something breaks
+     */
+    protected int doRead() throws IOException {
+       return in.read(buffer, 0, (int) Math.min(length - moved, buffer.length));
+    }
+    
+    /**
+     * Start to write some bytes to the connection
+     */
+    protected void startWrite(int bytes) throws UnknownTrailerSendIDException, 
TrailerSendFinishedException, AlreadySendingTrailerChunkException, IOException {
+       if(bytes <= 0) return;
+       myTWCM.reset();
+       lastPacketLength = bytes;
+       waitingForWriteNotify = true;
+       if(send != null) send.writeTrailing(buffer, 0, bytes, myTWCM);
+    }
+    
+    /**
+     * Handle a throwable thrown during I/O. We are expected to close the connection,
+     * etc.
+     * @param t the throwable causing the failure, can be null.
+     * @param inWrite whether we were writing at the time. false means we were 
reading.
+     */
+    protected State handleThrowable(Throwable t, boolean inWrite) {
+       if(logDEBUG) {
+           if(t == null)
+               n.logger.log(this, "SendData.handleThrowable(null,"+inWrite+
+                            ") on "+this, Logger.DEBUG);
+           else
+               n.logger.log(this, "SendData.handleThrowable("+t+","+inWrite+
+                            ") on "+this, t, Logger.DEBUG);
+       }
+       if(t == null) {
+           if(result == -1)
+               n.logger.log(this, "handleThrowable caller must set result if passing 
null Throwable!", new Exception("grrr"), Logger.ERROR);
+       } else if(t instanceof IOException) {
+           if(inWrite) result = Presentation.CB_SEND_CONN_DIED;
+           else {
+               int ifc = in.getFailureCode();
+               if(ifc == -1) {
                    if(logDEBUG) n.logger.log(this, "Cache failed between writing "+
-                                             "and reading for "+Long.toHexString(id),
-                                             e, Logger.DEBUG);
+                                             "and reading for 
"+Long.toHexString(id)+": "+
+                                             t, t, Logger.DEBUG);
                    result = Presentation.CB_CACHE_FAILED;
-               }
+               } else result = ifc;
             if (result == Presentation.CB_CACHE_FAILED) {
-                Core.logger.log(this, 
-                                "Cache failed signalled after exception " +
+                   Core.logger.log(this, "Cache failed signalled after exception " +
                                 "after " + moved + " of " + length 
-                                + " bytes: "+e+" for "+Long.toHexString(id)+
-                               " ("+Long.toHexString(parent)+".", e ,
+                                   + " bytes: "+t+" for "+Long.toHexString(id)+
+                                   " ("+Long.toHexString(parent)+".", t,
                                Logger.ERROR);
             }
-        } finally {
-           
-            n.diagnostics.occurrenceBinomial("sentData", 1, 
-                                             result == Presentation.CB_OK ?
-                                             1 : 0);
-           
-           if(result != Presentation.CB_OK) {
-               if(abortedException != null) {
-                   Core.logger.log(this, "Send aborted for "+Long.toHexString(id)+
-                                   " ("+Long.toHexString(parent)+" - result="+
-                                   Long.toHexString(result),
-                                   abortedException, Logger.MINOR);
-                   abortedException = null;
-               } else {
-                   Core.logger.log(this, "Send failed for "+Long.toHexString(id)+
-                                   " ("+Long.toHexString(parent)+" - result="+
-                                   Long.toHexString(result), Logger.MINOR);
                }
+       } else {
+           Core.logger.log(this, "Unexpected exception "+t+" in SendData "+
+                           this+" (inWrite="+inWrite+")", t, Logger.ERROR);
+           result = Presentation.CB_CACHE_FAILED; // well, sorta
            }
            
-           buffer = null;
-
+       n.diagnostics.occurrenceBinomial("sentData", 1, 0);
             try {
                 in.close();
                closedIn = true;
-            }
-            catch (IOException e) {
+       } catch (IOException e) {
                 n.logger.log(this, "I/O error closing KeyInputStream",
                              e, Logger.ERROR);
             }
-
-            if (moved < length && !inWrite) {
+       n.logger.log(this, "Send failed for "+Long.toHexString(id)+
+                    " ("+Long.toHexString(parent)+" - result="+
+                    Long.toHexString(result)+", cause: "+t, Logger.MINOR);
+       if(inWrite) {
+           if(send != null) send.close();
+           closedSend = true;
+       } else if(!inPaddingMode) {
+           if(moved == length) {
+               if(result == -1)
+                   n.logger.log(this, "WTF? moved = length in handleThrowable "+
+                                "for "+this, new Exception("debug"), 
+                                Logger.NORMAL);
+           } else {
                 try {
-                    // pad until end of part
-                    long tmpLen = partSize + Key.getControlLength();
-                    tmpLen = Math.min(tmpLen - moved % tmpLen, length - moved) - 1;
-                    
-                    byte[] zeroes = new byte[Core.blockSize];
-                    while (tmpLen > 0) {
-                        int m = (int) Math.min(tmpLen, zeroes.length);
-                        send.write(zeroes, 0, m);
-                        tmpLen -= m;
-                    }
-                    send.write(result == Presentation.CB_ABORTED ? 
Presentation.CB_ABORTED
-                                                                 : 
Presentation.CB_RESTARTED);
-                }
-                catch (IOException e) {
-                    // this is important b/c it lets the parent chain know that
-                    // it shouldn't try to get back in touch with the upstream
-                    result = Presentation.CB_SEND_CONN_DIED;
+                   startWritePadding();
+                   return this; 
+                   // don't send the DataSent until the padding has finished writing
+               } catch (IOException e) {
+                   // Failed
+                   t = e;
+               } catch (TrailerException e) {
+                   Core.logger.log(this, "Got "+e+" starting writing padding for 
"+this,
+                                   e, Logger.ERROR);
                 }
             }
-            
-            if (result != Presentation.CB_OK) {
-                try {
-                    send.close();
+           // Failed or already at end
+           if(send != null) send.close();
+           closedSend = true;
+       } else {
+           // Padding failed
+           if(send != null) send.close();
                    closedSend = true;
-                }
-                catch (IOException e) {
-                    n.logger.log(this, "I/O error closing data send stream",
-                                 e, Logger.MINOR);
-                }
             }
             
-            // we could be exiting with an uncaught exception or something..
-            if (result == -1) result = Presentation.CB_SEND_CONN_DIED;
+       buffer = null; // early GC
             
-            // had to wait around to see if we'd get a CB_SEND_CONN_DIED
-            // when padding the write
             if (!silent) n.schedule(new DataSent(this));
+       return null;
         }
         
-        return null;
+    protected void startWritePadding() throws UnknownTrailerSendIDException, 
TrailerSendFinishedException, AlreadySendingTrailerChunkException, IOException {
+       // Pad until end of part
+       inPaddingMode = true;
+       int controlLength = Key.getControlLength();
+       long tmpLen = partSize + controlLength;
+       paddingLength = Math.min(tmpLen - moved % tmpLen,
+                                length - moved);
+       // Either way, it includes the padding byte - and the part hash
+       
+       if(!waitingForWriteNotify)
+           sendWritePadding();
+    }
+    
+    protected void sendWritePadding() throws UnknownTrailerSendIDException, 
TrailerSendFinishedException, AlreadySendingTrailerChunkException, IOException {
+       byte[] stuffToSend;
+       long remainingPadding = paddingLength - sentPadding;
+       if(logDEBUG)
+           n.logger.log(this, "sendWritePadding(): paddingLength="+
+                        paddingLength+"/"+sentPadding+" ("+this+")",
+                        Logger.DEBUG);
+       if(remainingPadding <= 0) return; // we will get finished
+       if(remainingPadding < (Core.blockSize/*Key.getControlLength()*/)) {
+           // Last chunk, yay
+           stuffToSend = new byte[(int)remainingPadding];
+           Random r = new Random(Core.getRandSource().nextLong());
+           r.nextBytes(stuffToSend); // is this necessary? it used to be 0 padded
+           // FIXME: assumes getControlLength() == 1
+           stuffToSend[stuffToSend.length-1] = (byte)
+               ((result == Presentation.CB_ABORTED) ?
+                Presentation.CB_ABORTED : Presentation.CB_RESTARTED);
+           lastPacketLength = stuffToSend.length;
+       } else {
+           // Just another chunk
+           stuffToSend = new byte[Core.blockSize];
+           Random r = new Random(Core.getRandSource().nextLong());
+           r.nextBytes(stuffToSend); // is this necessary? it used to be 0 padded
+           lastPacketLength = Core.blockSize;
+       }
+       myTWCM.reset();
+       waitingForWriteNotify = true;
+       if(send != null) send.writeTrailing(stuffToSend, 0, 
+                                           stuffToSend.length, myTWCM);
+    }
+    
+    protected State finish() {
+               if (!(moved == length || (inPaddingMode && sentPadding >= 
paddingLength) || (result != -1 && !inPaddingMode))) {
+                       n.logger.log(this, "Not finishing because moved=" + moved + 
"/" + length + ", inPaddingMode=" + inPaddingMode + ", sentPadding=" + sentPadding + 
"/" + paddingLength + " (" + this +")", Logger.DEBUG);
+                       return this;
+               }
+               if (inPaddingMode && sentPadding > paddingLength)
+                       n.logger.log(this, "sentPadding=" + sentPadding + "/" + 
paddingLength + " (" + this +")", Logger.NORMAL);
+               if (result != -1) {
+                       // We were aborted
+                       return handleThrowable(null, false);
     }
+               if (send != null)
+                       send.close();
+               closedSend = true;
+               try {
+                       in.close();
+                       closedIn = true;
+               } catch (IOException e) {
+                       Core.logger.log(this, "Caught " + e + " closing input 
(successful): " + this, Logger.NORMAL);
+               }
+               if (moved == length)
+                       result = Presentation.CB_OK;
+               n.diagnostics.occurrenceBinomial("sentData", 1, result == 
Presentation.CB_OK ? 1 : 0);
+               if (!silent)
+                       n.schedule(new DataSent(this));
+               return null;
+       };
+
+//         try {
+//             while (moved < length) {
+//                 inWrite = false;
+//                 if (result != -1) throw new CancelledIOException();
+//                 int m = in.read(buffer, 0, (int) Math.min(length - moved, 
buffer.length));
+//                 if (m == -1) {
+//                 throw new IOException("Stopped short of full transfer");
+//             }
+//             inWrite = true;
+//             if(logDEBUG)
+//                 n.logger.log(this, "Read "+(moved+m)+" of "+length+
+//                              " bytes for "+Long.toHexString(parent)+" ("+in+")",
+//                              Logger.DEBUG);
+//                 send.write(buffer, 0, m);
+//                 moved += m;
+//             if(logDEBUG)
+//                 n.logger.log(this, "Moved "+moved+" of "+length+" bytes for "+
+//                              Long.toHexString(parent)+" ("+in+")",
+//                              Logger.DEBUG);
+//             }
+//             send.close();
+//         closedSend = true;
+//             result = Presentation.CB_OK;
+//         } catch (CancelledIOException e) {
+//         if(logDEBUG)
+//             n.logger.log(this, "Cancelled IO: "+abortedException+" for "+
+//                          Long.toHexString(parent), abortedException, 
+//                          Logger.DEBUG);
+//     } catch (IOException e) {
+//             // if it was aborted we can expect the aborter to set the failure
+//             // code.
+//             result = (inWrite ? Presentation.CB_SEND_CONN_DIED
+//                       : in.getFailureCode());
+//             if (result == -1) // it broke some time between writing and reading
+//             {
+//                 if(logDEBUG) n.logger.log(this, "Cache failed between writing "+
+//                                           "and reading for "+Long.toHexString(id),
+//                                           e, Logger.DEBUG);
+//                 result = Presentation.CB_CACHE_FAILED;
+//             }
+//             if (result == Presentation.CB_CACHE_FAILED) {
+//                 Core.logger.log(this, 
+//                                 "Cache failed signalled after exception " +
+//                                 "after " + moved + " of " + length 
+//                                 + " bytes: "+e+" for "+Long.toHexString(id)+
+//                             " ("+Long.toHexString(parent)+".", e ,
+//                             Logger.ERROR);
+//             }
+//         } finally {
+           
+//             n.diagnostics.occurrenceBinomial("sentData", 1, 
+//                                              result == Presentation.CB_OK ?
+//                                              1 : 0);
+           
+//         if(result != Presentation.CB_OK) {
+//             if(abortedException != null) {
+//                 Core.logger.log(this, "Send aborted for "+Long.toHexString(id)+
+//                                 " ("+Long.toHexString(parent)+" - result="+
+//                                 Long.toHexString(result),
+//                                 abortedException, Logger.MINOR);
+//                 abortedException = null;
+//             } else {
+//                 Core.logger.log(this, "Send failed for "+Long.toHexString(id)+
+//                                 " ("+Long.toHexString(parent)+" - result="+
+//                                 Long.toHexString(result), Logger.MINOR);
+//             }
+//         }
+           
+//         buffer = null;
+           
+//             try {
+//                 in.close();
+//             closedIn = true;
+//             } catch (IOException e) {
+//                 n.logger.log(this, "I/O error closing KeyInputStream",
+//                              e, Logger.ERROR);
+//             }
+           
+//             if (moved < length && !inWrite) {
+//                 try {
+//                     // pad until end of part
+//                     long tmpLen = partSize + Key.getControlLength();
+//                     tmpLen = Math.min(tmpLen - moved % tmpLen, length - moved) - 1;
+                    
+//                     byte[] zeroes = new byte[Core.blockSize];
+//                     while (tmpLen > 0) {
+//                         int m = (int) Math.min(tmpLen, zeroes.length);
+//                         send.write(zeroes, 0, m);
+//                         tmpLen -= m;
+//                     }
+//                     send.write(result == Presentation.CB_ABORTED ? 
Presentation.CB_ABORTED
+//                            : Presentation.CB_RESTARTED);
+//                 } catch (IOException e) {
+//                     // this is important b/c it lets the parent chain know that
+//                     // it shouldn't try to get back in touch with the upstream
+//                     result = Presentation.CB_SEND_CONN_DIED;
+//                 }
+//             }
+            
+//             if (result != Presentation.CB_OK) {
+//                 try {
+//                     send.close();
+//                 closedSend = true;
+//                 }
+//                 catch (IOException e) {
+//                     n.logger.log(this, "I/O error closing data send stream",
+//                                  e, Logger.MINOR);
+//                 }
+//             }
+            
+//             // we could be exiting with an uncaught exception or something..
+//             if (result == -1) result = Presentation.CB_SEND_CONN_DIED;
+            
+//             // had to wait around to see if we'd get a CB_SEND_CONN_DIED
+//             // when padding the write
+//             if (!silent) n.schedule(new DataSent(this));
+//         }
+        
+//         return null;
+//     }
 }
 

_______________________________________________
cvs mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to