clean data_out_
authorvictor <victor@e16421f0-f15b-0410-abcd-98678b794739>
Fri, 20 Nov 2009 14:14:53 +0000 (14:14 +0000)
committervictor <victor@e16421f0-f15b-0410-abcd-98678b794739>
Fri, 20 Nov 2009 14:14:53 +0000 (14:14 +0000)
git-svn-id: https://ttuki.vtt.fi/svn/p2p-next/TUD/p2tp/trunk@609 e16421f0-f15b-0410-abcd-98678b794739

bins.cpp
bins.h
do_tests.sh
exec/bingrep.cpp [new file with mode: 0644]
p2tp.h
sendrecv.cpp
tests/binstest2.cpp

index cfca3a2..3641138 100644 (file)
--- a/bins.cpp
+++ b/bins.cpp
@@ -259,7 +259,7 @@ uint16_t bins::get (bin64_t bin) {
     //    i.towards(bin);
     //printf("at %i ",i.half);
     //dump("get made");
-    return *i; // deep cell is never 0xffff or 0x0000
+    return *i; // deep cell is never 0xffff or 0x0000; FIXME: API caveat
 }
 
 
@@ -422,13 +422,13 @@ uint64_t    bins::seq_length () {
 }
 
 
-bool        bins::is_empty (bin64_t range)  {
+bool        bins::is_solid (bin64_t range, fill_t val)  {
     if (range==bin64_t::ALL) 
-        return !deep(0) && !halves[0];
+        return !deep(0) && (is_mixed(val) || halves[0]==val);
     iterator i(this,range,false);
     while ( i.pos!=range && (i.deep() || !i.solid()) )
         i.towards(range);
-    return !i.deep() && *i==EMPTY;
+    return i.solid() && (is_mixed(val) || *i==val);
 }
 
 
diff --git a/bins.h b/bins.h
index 8275c73..5a8debd 100644 (file)
--- a/bins.h
+++ b/bins.h
@@ -14,7 +14,7 @@
 class bins {
     
 public:
-    typedef enum { FILLED=0xffff, EMPTY=0x0000 } fill_t;
+    typedef enum { FILLED=0xffff, EMPTY=0x0000, MIXED=0x5555 } fill_t;
     static const int NOJOIN;
     
     bins();
@@ -46,11 +46,14 @@ public:
 
     uint64_t    mass ();
     
-    bool        is_empty (bin64_t range=bin64_t::ALL) ;
+    bool        is_solid (bin64_t range=bin64_t::ALL, fill_t val=MIXED) ;
+    bool        is_empty (bin64_t range=bin64_t::ALL) { return is_solid(range,EMPTY); }
+    bool        is_filled (bin64_t range=bin64_t::ALL) { return is_solid(range,FILLED); }
 
     void        clear ();
     
     static bool is_mixed (uint16_t val) { return val!=EMPTY && val!=FILLED; }
+    static bool is_solid (uint16_t val) { return val==EMPTY || val==FILLED; }
 
     void        twist (uint64_t mask);
     
@@ -126,8 +129,7 @@ public:
     ~iterator();
     bool deep () { return host->deep(half); }
     bool solid () { 
-        return !deep() && (host->halves[half]==bins::FILLED || 
-                host->halves[half]==bins::EMPTY); 
+        return !deep() && bins::is_solid(host->halves[half]); 
     }
     void sibling () { half^=1; pos=pos.sibling(); }
     bool end () { return half==1; }
index d87ec38..f02a6cc 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-for tst in `ls tests/*test`; do
+for tst in `ls tests/*test | grep -v ledbat`; do
     if echo $tst; $tst > $tst.log; then
         echo $tst OK
     else
diff --git a/exec/bingrep.cpp b/exec/bingrep.cpp
new file mode 100644 (file)
index 0000000..7ed2c1c
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <string.h>
+#include "bin64.h"
+
+int main (int argn, char** args) {
+    int lr;
+    unsigned long long of;
+    sscanf(args[1],"%i,%lli",&lr,&of);
+    bin64_t target(lr,of);
+    char line[1024];
+    while (gets(line)) {
+        char* br = strchr(line,'(');
+        if (br && 2==sscanf(br,"(%i,%lli)",&lr,&of)) {
+            bin64_t found(lr,of);
+            if ( found.within(target) || target.within(found))
+                printf("%s\n",line);
+        }
+    }
+    return 0;
+}
diff --git a/p2tp.h b/p2tp.h
index ebef7bc..ce5d029 100644 (file)
--- a/p2tp.h
+++ b/p2tp.h
@@ -306,10 +306,9 @@ namespace p2tp {
         }
         /** Get a request for one packet from the queue of peer's requests. */
         bin64_t                DequeueHint();
-        void        ClearStaleDataOut ();
+        void        CleanDataOut (bin64_t acks_pos=bin64_t::NONE);
         void        CleanStaleHintOut();
         void        CleanHintOut(bin64_t pos);
-        void        CleanFulfilledDataOut(bin64_t pos);
         void        Schedule(tint send_time);
 
         static PeerSelector* peer_selector;
index da3fe14..bb62d37 100644 (file)
@@ -87,23 +87,6 @@ void Channel::AddHandshake (Datagram& dgram) {
 }
 
 
-void    Channel::ClearStaleDataOut() {
-    int oldsize = data_out_.size();
-    tint timeout = NOW - max( rtt_avg_-dev_avg_*4, 500*TINT_MSEC );
-    while ( data_out_.size() && data_out_.front().time < timeout &&
-            ack_in_.get(data_out_.front().bin)==bins::EMPTY ) {
-        dprintf("%s #%i Tdata %s\n",tintstr(),id,data_out_.front().bin.str());
-        data_out_.pop_front();
-    }
-    if (data_out_.size()!=oldsize) {
-        cc_->OnAckRcvd(bin64_t::NONE);
-        data_out_cap_ = bin64_t::ALL;
-    }
-    while (data_out_.size() && (data_out_.front()==tintbin() || ack_in_.get(data_out_.front().bin)==bins::FILLED))
-        data_out_.pop_front();
-}
-
-
 void   Channel::Send () {
     Datagram dgram(socket_,peer());
     dgram.Push32(peer_channel_id_);
@@ -114,7 +97,7 @@ void Channel::Send () {
         if (!file().is_complete())
             AddHint(dgram);
         AddPex(dgram);
-        ClearStaleDataOut();
+        CleanDataOut();
         data = AddData(dgram);
     } else {
         AddHandshake(dgram);
@@ -329,20 +312,54 @@ bin64_t Channel::OnData (Datagram& dgram) {
 }
 
 
-void    Channel::CleanFulfilledDataOut (bin64_t ackd_pos) {
-    for (int i=0; i<8 && i<data_out_.size(); i++) 
-        if (data_out_[i]!=tintbin() && data_out_[i].bin.within(ackd_pos)) {
-            tint rtt = NOW-data_out_[i].time;
-            rtt_avg_ = (rtt_avg_*7 + rtt) >> 3;
-            dev_avg_ = ( dev_avg_*3 + abs(rtt-rtt_avg_) ) >> 2;
-            dprintf("%s #%i rtt %lli dev %lli\n",
-                    tintstr(),id,rtt_avg_,dev_avg_);
-            cc_->OnAckRcvd(data_out_[i].bin);
-            data_out_[i]=tintbin();
+void    Channel::CleanDataOut (bin64_t ackd_pos) {
+    
+    int max_ack_off = 0;
+    
+    if (ackd_pos!=bin64_t::NONE) {
+        for (int i=0; i<8 && i<data_out_.size(); i++) {
+            if (data_out_[i]!=tintbin() && data_out_[i].bin.within(ackd_pos)) {
+                tint rtt = NOW-data_out_[i].time;
+                rtt_avg_ = (rtt_avg_*7 + rtt) >> 3;
+                dev_avg_ = ( dev_avg_*3 + abs(rtt-rtt_avg_) ) >> 2;
+                dprintf("%s #%i rtt %lli dev %lli\n",tintstr(),id,rtt_avg_,dev_avg_);
+                bin64_t pos = data_out_[i].bin;
+                cc_->OnAckRcvd(pos);
+                data_out_[i]=tintbin();
+                max_ack_off = i;
+                if (ackd_pos==pos)
+                    break;
+            }
+        }
+        while (!data_out_.empty() && data_out_.front().bin==bin64_t::NONE) {
+            data_out_.pop_front();
+            max_ack_off--;
+        }
+        static const int MAX_REORDERING = 2;  // the triple-ACK principle
+        if (max_ack_off>MAX_REORDERING) {
+            while (max_ack_off && ack_in_.is_filled(data_out_.front().bin)) {
+                data_out_.pop_front();
+                max_ack_off--;
+            }
+            while (max_ack_off>MAX_REORDERING) {
+                cc_->OnAckRcvd(bin64_t::NONE);
+                data_out_.pop_front();
+                max_ack_off--;
+                data_out_cap_ = bin64_t::ALL;
+                dprintf("%s #%i Rdata %s\n",tintstr(),id,data_out_.front().bin.str());
+            }
+        }
+    }
+    tint timeout = NOW - rtt_avg_ - 4*std::max(dev_avg_,TINT_MSEC*50);
+    while (!data_out_.empty() && data_out_.front().time<timeout) {
+        if (ack_in_.is_empty(data_out_.front().bin)) {
+            cc_->OnAckRcvd(bin64_t::NONE);
+            data_out_cap_ = bin64_t::ALL;
+            dprintf("%s #%i Tdata %s\n",tintstr(),id,data_out_.front().bin.str());
         }
-    while ( data_out_.size() && ( data_out_.front()==tintbin() ||
-                                 ack_in_.get(data_out_.front().bin)==bins::FILLED ) )
         data_out_.pop_front();
+    }
+
 }
 
 
@@ -354,7 +371,7 @@ void        Channel::OnAck (Datagram& dgram) {
     }
     dprintf("%s #%i -ack %s\n",tintstr(),id,ackd_pos.str());
     ack_in_.set(ackd_pos);
-    CleanFulfilledDataOut(ackd_pos);
+    CleanDataOut(ackd_pos);
 }
 
 
index 36149da..7d5d2c4 100755 (executable)
@@ -316,6 +316,39 @@ TEST(BinsTest,SeqLength) {
     EXPECT_EQ(11,b.seq_length());
 }
 
+TEST(BinsTest,EmptyFilled) {
+    // 1112 3312  2111 ....
+    bins b;
+    
+    EXPECT_TRUE(b.is_empty(bin64_t::ALL));
+    
+    b.set(bin64_t(1,0));
+    b.set(bin64_t(0,2));
+    b.set(bin64_t(0,6));
+    b.set(bin64_t(1,5));
+    b.set(bin64_t(0,9));
+    
+    EXPECT_FALSE(b.is_empty(bin64_t::ALL));
+    
+    EXPECT_TRUE(b.is_empty(bin64_t(2,3)));
+    EXPECT_FALSE(b.is_filled(bin64_t(2,3)));
+    EXPECT_TRUE(b.is_solid(bin64_t(2,3),bins::MIXED));
+    EXPECT_TRUE(b.is_filled(bin64_t(1,0)));
+    EXPECT_TRUE(b.is_filled(bin64_t(1,5)));
+    EXPECT_FALSE(b.is_filled(bin64_t(1,3)));
+    
+    b.set(bin64_t(0,3));
+    b.set(bin64_t(0,7));
+    b.set(bin64_t(0,8));
+    
+    EXPECT_TRUE(b.is_filled(bin64_t(2,0)));
+    EXPECT_TRUE(b.is_filled(bin64_t(2,2)));    
+    EXPECT_FALSE(b.is_filled(bin64_t(2,1)));    
+
+    b.set(bin64_t(1,2));
+    EXPECT_TRUE(b.is_filled(bin64_t(2,1)));    
+}
+
 TEST(BinheapTest,Eat) {
     
     binheap b;