Not convinced by _abandonedTickets:

1 new ticket
2 new ticket
3 new ticket
4 new ticket
2 times out
3 times out
space to send (1)
1-2 = -1 so we don't send
space to send (2)
4-2 = 2 so we do send 4

We could avoid this by using _packetSeq <= (_thisTicket-_abandonedTickets) ... 
but then it is only approximately ordered:

1 new ticket
2 new ticket
3 new ticket
4 new ticket
5 new ticket
3 times out
4 times out
space to send (1)
1-2 = -1, 2-2 = 0, both < 1, so we send either 1 or 2
space to send (2)
we send the other one

Obviously this will only happen if some packets have different timeouts. 
However this is unavoidable if we switch trackers when a node changes 
address. Apart from that (which is rare), we have a 5 minute timeout for bulk 
transmits (noderefs, UOM, node to node data transfer) and a 1 minute timeout 
for block transmits (CHK requests, CHK inserts). Meaning if we unexpectedly 
lose bandwidth for a short period, we will probably timeout block transfers 
but not bulk transfers...

Or we could explicitly track the packets to send. A DoublyLinkedList being the 
obvious option (not the java.util version, with the freenet.support version 
we get O(1) removes). A TreeMap would allow us to prioritise packets by their 
deadlines. Is this a good idea? Should I implement it?

On Friday 14 March 2008 19:41, robert at freenetproject.org wrote:
> Author: robert
> Date: 2008-03-14 19:41:34 +0000 (Fri, 14 Mar 2008)
> New Revision: 18536
> 
> Modified:
>    trunk/freenet/src/freenet/io/xfer/PacketThrottle.java
> Log:
> grab transmit window space in FIFO order (possibly prevent starvation)
> 
> 
> Modified: trunk/freenet/src/freenet/io/xfer/PacketThrottle.java
> ===================================================================
> --- trunk/freenet/src/freenet/io/xfer/PacketThrottle.java     2008-03-14 
18:13:46 UTC (rev 18535)
> +++ trunk/freenet/src/freenet/io/xfer/PacketThrottle.java     2008-03-14 
19:41:34 UTC (rev 18536)
> @@ -44,12 +44,17 @@
>       private boolean slowStart = true;
>       /** Total packets in flight, including waiting for bandwidth from the 
central throttle. */
>       private int _packetsInFlight;
> -     /** Incremented on each send */
> +     /** Incremented on each send; the sequence number of the packet last 
> added 
to the window/sent */
>       private long _packetSeq;
>       /** Last time (seqno) the window was full */
>       private long _packetSeqWindowFull;
>       /** Last time (seqno) we checked whether the window was full, or 
> dropped a 
packet. */
>       private long _packetSeqWindowFullChecked;
> +     /** Holds the next number to be used for fifo packet pre-sequence 
> numbers 
*/
> +     private long _packetTicketGenerator;
> +     /** The number of would-be packets which are no longer waiting in line 
> for 
the transmition window */
> +     private long _abandonedTickets;
> +     
>       private static boolean logMINOR;
>       private PacketThrottle _deprecatedFor;
>  
> @@ -144,9 +149,12 @@
>               long bootID = peer.getBootID();
>               synchronized(this) {
>                       logMINOR = Logger.shouldLog(Logger.MINOR, this);
> +                     long thisTicket=_packetTicketGenerator++;
>                       while(true) {
>                               int windowSize = (int) getWindowSize();
> -                             if(_packetsInFlight < windowSize) {
> +                             boolean 
> wereNext=(_packetSeq==(thisTicket-_abandonedTickets));
> +                             //If there is room for it in the window, break 
> and send it immeadiately
> +                             if(_packetsInFlight < windowSize && wereNext) {
>                                       _packetsInFlight++;
>                                       _packetSeq++;
>                                       if(windowSize == _packetsInFlight) {
> @@ -156,20 +164,24 @@
>                                       if(logMINOR) Logger.minor(this, 
> "Sending, window size 
now "+windowSize+" packets in flight "+_packetsInFlight+" for "+this);
>                                       break;
>                               }
> -                             if(logMINOR) Logger.minor(this, "Window size: 
> "+windowSize+" packets in 
flight "+_packetsInFlight+" for "+this);
> +                             long 
> waitingBehind=thisTicket-_abandonedTickets-_packetSeq;
> +                             if(logMINOR) Logger.minor(this, "Window size: 
> "+windowSize+" packets in 
flight "+_packetsInFlight+", "+waitingBehind+" in front of this thread 
for "+this);
>                               long now = System.currentTimeMillis();
>                               int waitFor = (int)Math.min(Integer.MAX_VALUE, 
> deadline - now);
>                               if(waitFor <= 0) {
>                                       // Double-check.
>                                       if(!peer.isConnected()) {
>                                               Logger.error(this, "Not 
> notified of disconnection before timeout");
> +                                             _abandonedTickets++;
>                                               throw new 
> NotConnectedException();
>                                       }
>                                       if(bootID != peer.getBootID()) {
>                                               Logger.error(this, "Not 
> notified of reconnection before timeout");
> +                                             _abandonedTickets++;
>                                               throw new 
> NotConnectedException();
>                                       }
>                                       Logger.error(this, "Unable to send 
> throttled message, 
waited "+(now-start)+"ms");
> +                                     _abandonedTickets++;
>                                       throw new WaitedTooLongException();
>                               }
>                               try {
> @@ -177,9 +189,16 @@
>                               } catch (InterruptedException e) {
>                                       // Ignore
>                               }
> -                             if(!peer.isConnected()) throw new 
> NotConnectedException();
> -                             if(bootID != peer.getBootID()) throw new 
> NotConnectedException();
> +                             if(!peer.isConnected()) {
> +                                     _abandonedTickets++;
> +                                     throw new NotConnectedException();
> +                             }
> +                             if(bootID != peer.getBootID()) {
> +                                     _abandonedTickets++;
> +                                     throw new NotConnectedException();
> +                             }
>                               if(_deprecatedFor != null) {
> +                                     _abandonedTickets++;
>                                       throw new 
> ThrottleDeprecatedException(_deprecatedFor);
>                               }
>                       }
> 
> _______________________________________________
> cvs mailing list
> cvs at freenetproject.org
> http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<https://emu.freenetproject.org/pipermail/cvs/attachments/20080315/7fb32dec/attachment.pgp>

Reply via email to