}
+void bins::clear () {
+ set(bin64_t(height,0),EMPTY);
+}
+
+
+uint64_t bins::mass () {
+ iterator i(this,bin64_t(0,0),false);
+ uint64_t ret = 0;
+ while (!i.solid())
+ i.left();
+ while (!i.end()) {
+ if (*i==bins::FILLED)
+ ret += i.pos.width();
+ i.next(true);
+ }
+ return ret;
+}
+
+
void bins::set (bin64_t bin, fill_t val) {
assert(val==FILLED || val==EMPTY);
iterator i(this,bin,false);
uint32_t size() { return cells_allocated; }
bin64_t cover(bin64_t val);
+
+ uint64_t mass ();
- bool empty () const { return !deep(0) && !halves[0]; }
+ bool is_empty () const { return !deep(0) && !halves[0]; }
+
+ void clear ();
static bool is_mixed (uint16_t val) { return val!=EMPTY && val!=FILLED; }
ack_hint_out_.set(b,bins::FILLED);
}
- virtual void Expired (bin64_t b) {
- ack_hint_out_.copy_range(file_->ack_out(),b);
+ virtual void Expired (bins& b) {
+ ack_hint_out_.remove(b);
}
-};
\ No newline at end of file
+};
Channel::Channel (FileTransfer* file, int socket, Address peer_addr) :
file_(file), peer_(peer_addr), peer_channel_id_(0), pex_out_(0),
socket_(socket==-1?sockets[0]:socket), // FIXME
- own_id_mentioned_(false), next_send_time_(0)
+ own_id_mentioned_(false), next_send_time_(0), hint_out_rotate_(0)
{
if (peer_==Address())
peer_ = tracker;
class PiecePicker {
public:
virtual bin64_t Pick (bins& offered, uint8_t layer) = 0;
- virtual void Expired (bin64_t b) = 0;
+ virtual void Expired (bins& b) = 0;
virtual void Received (bin64_t b) = 0;
};
/** Transmit schedule: in most cases filled with the peer's hints */
binqueue hint_in_;
/** Hints sent (to detect and reschedule ignored hints). */
- tbqueue hint_out_;
+ bins hint_out_;
+ bins hint_out_old_;
+ tint hint_out_rotate_;
/** The congestion control strategy. */
CongestionController *cc_;
/** Types of messages the peer accepts. */
void Channel::AddHint (Datagram& dgram) {
- tint hint_timeout = Datagram::now - 2*TINT_SEC;
- while (!hint_out_.empty() && hint_out_.front().time<hint_timeout) {
- tintbin old_hint = hint_out_.front();
- file().picker().Expired(old_hint.bin);
- hint_out_.pop_front();
- }
- // FIXME weird weird weird
- uint16_t state;
- while ( !hint_out_.empty() && (state=file().ack_out().get(hint_out_.front().bin)) != bins::EMPTY ) {
- if (state==bins::FILLED) {
- hint_out_.pop_front();
- } else {
- tintbin old_hint = hint_out_.front();
- hint_out_.pop_front();
- old_hint.bin = old_hint.bin.right();
- hint_out_.push_front(old_hint);
- old_hint.bin = old_hint.bin.sibling();
- hint_out_.push_front(old_hint);
- }
+ if (hint_out_rotate_<Datagram::now-TINT_SEC) {
+ hint_out_rotate_ = Datagram::now;
+ if ( ! hint_out_old_.is_empty() )
+ file().picker().Expired(hint_out_old_);
+ swap(hint_out_,hint_out_old_);
+ hint_out_.clear();
}
- uint64_t hinted = 0;
- for(tbqueue::iterator i=hint_out_.begin(); i!=hint_out_.end(); i++)
- hinted+=i->bin.width();
+ uint64_t hinted = hint_out_.mass() + hint_out_old_.mass();
//float peer_cwnd = cc_->PeerBPS() * cc_->RoundTripTime() / TINT_SEC;
bin64_t hint = file().picker().Pick(ack_in_,layer);
if (hint!=bin64_t::NONE) {
- this->hint_out_.push_back(tintbin(hint));
+ hint_out_.set(hint);
dgram.Push8(P2TP_HINT);
dgram.Push32(hint);
dprintf("%s #%i +hint (%i,%lli)\n",Datagram::TimeStr(),id,hint.layer(),hint.offset());
bin64_t tosend = DequeueHint();
if (tosend==bin64_t::NONE)
return bin64_t::NONE;
- if (ack_in_.empty() && file().size())
+ if (ack_in_.is_empty() && file().size())
AddPeakHashes(dgram);
AddUncleHashes(dgram,tosend);
uint8_t buf[1024];
bool ok = file().OfferData(pos, data, length) ;
dprintf("%s #%i %cdata (%lli)\n",Datagram::TimeStr(),id,ok?'-':'!',pos.offset());
data_in_ = tintbin(Datagram::now,pos);
+ hint_out_.set(pos,bins::EMPTY);
+ hint_out_old_.set(pos,bins::EMPTY);
return ok ? pos : bin64_t::none();
}
}
- */
\ No newline at end of file
+ */
EXPECT_EQ(bins::FILLED,data.get(bin64_t(1,7)));
}
+TEST(BinsTest, Mass) {
+ bins b;
+ b.set(bin64_t(6,0),bins::FILLED);
+ b.set(bin64_t(0,0),bins::EMPTY);
+ EXPECT_EQ(63,b.mass());
+ EXPECT_FALSE(b.is_empty());
+ b.clear();
+ EXPECT_TRUE(b.is_empty());
+ EXPECT_EQ(0,b.mass());
+
+ bins b50;
+ for(int i=0; i<50; i++)
+ b50.set(bin64_t(4,i*2));
+ EXPECT_EQ(50<<4,b50.mass());
+}
+
TEST(BinheapTest,Eat) {
binheap b;