f6d4bbe5852fbef1919c5fd80d38fcf19e1d8299
[swift-upb.git] / ext / seq_picker.cpp
1 /*
2  *  seq_picker.cpp
3  *  swift
4  *
5  *  Created by Victor Grishchenko on 10/6/09.
6  *  Copyright 2009 Delft University of Technology. All rights reserved.
7  *
8  */
9
10 #include "swift.h"
11
12 using namespace swift;
13
14
15 /** Picks pieces nearly sequentialy; some local randomization (twisting)
16     is introduced to prevent synchronization among multiple channels. */
17 class SeqPiecePicker : public PiecePicker {
18     
19     binmap_t            ack_hint_out_;
20     tbqueue         hint_out_;
21     FileTransfer*   transfer_;
22     uint64_t        twist_;
23     
24 public:
25     
26     SeqPiecePicker (FileTransfer* file_to_pick_from) : 
27     transfer_(file_to_pick_from), ack_hint_out_(), twist_(0) {
28         ack_hint_out_.copy_range(file().ack_out(),bin64_t::ALL);
29     }
30     virtual ~SeqPiecePicker() {}
31     
32     HashTree& file() { 
33         return transfer_->file(); 
34     }
35     
36     virtual void Randomize (uint64_t twist) {
37         twist_ = twist;
38     }
39     
40     virtual bin64_t Pick (binmap_t& offer, uint64_t max_width, tint expires) {
41         while (hint_out_.size() && hint_out_.front().time<NOW-TINT_SEC*3/2) { // FIXME sec
42             ack_hint_out_.copy_range(file().ack_out(), hint_out_.front().bin);
43             hint_out_.pop_front();
44         }
45         if (!file().size()) {
46             return bin64_t(0,0); // whoever sends it first
47         }
48     retry:      // bite me
49         twist_ &= (file().peak(0)) & ((1<<6)-1);
50         if (twist_) {
51             offer.twist(twist_);
52             ack_hint_out_.twist(twist_);
53         }
54         bin64_t hint = offer.find_filtered (ack_hint_out_,bin64_t::ALL,binmap_t::FILLED);
55         if (twist_) {
56             hint = hint.twisted(twist_);
57             offer.twist(0);
58             ack_hint_out_.twist(0);
59         }
60         if (hint==bin64_t::NONE) {
61             return hint; // TODO: end-game mode
62         }
63         if (!file().ack_out().is_empty(hint)) { // unhinted/late data
64             ack_hint_out_.copy_range(file().ack_out(), hint);
65             goto retry;
66         }
67         while (hint.width()>max_width)
68             hint = hint.left();
69         assert(ack_hint_out_.get(hint)==binmap_t::EMPTY);
70         ack_hint_out_.set(hint);
71         hint_out_.push_back(tintbin(NOW,hint));
72         return hint;
73     }
74     
75 };