1 /*
2  *  seq_picker.cpp
3  *  swift
4  *
5  *  Created by Victor Grishchenko on 10/6/09.
6  *  Copyright 2009-2016 TECHNISCHE UNIVERSITEIT DELFT. All rights reserved.
7  *
8  */
9 
10 #include "swift.h"
11 #include <cassert>
12 
13 using namespace swift;
14 
15 
16 /** Picks pieces nearly sequentialy; some local randomization (twisting)
17     is introduced to prevent synchronization among multiple channels. */
18 class SeqPiecePicker : public PiecePicker
19 {
20 
21     binmap_t        ack_hint_out_;
22     tbqueue         hint_out_;
23     FileTransfer*   transfer_;
24     uint64_t        twist_;
25     bin_t           range_;
26 
27 public:
28 
SeqPiecePicker(FileTransfer * file_to_pick_from)29     SeqPiecePicker(FileTransfer* file_to_pick_from) : ack_hint_out_(),
30         transfer_(file_to_pick_from), twist_(0), range_(bin_t::ALL) {
31         binmap_t::copy(ack_hint_out_, *(hashtree()->ack_out()));
32     }
~SeqPiecePicker()33     virtual ~SeqPiecePicker() {}
34 
hashtree()35     HashTree * hashtree() {
36         return transfer_->hashtree();
37     }
38 
Randomize(uint64_t twist)39     virtual void Randomize(uint64_t twist) {
40         twist_ = twist;
41     }
42 
LimitRange(bin_t range)43     virtual void LimitRange(bin_t range) {
44         range_ = range;
45     }
46 
Pick(binmap_t & offer,uint64_t max_width,tint expires,uint32_t channelid)47     virtual bin_t Pick(binmap_t& offer, uint64_t max_width, tint expires, uint32_t channelid) {
48         while (hint_out_.size() && hint_out_.front().time<NOW-TINT_SEC*PICKER_TIMEOUT) { // FIXME sec
49             binmap_t::copy(ack_hint_out_, *(hashtree()->ack_out()), hint_out_.front().bin);
50             hint_out_.pop_front();
51         }
52         if (!hashtree()->size()) {
53             return bin_t(0,0); // whoever sends it first
54             // Arno, 2011-06-28: Partial fix by Victor. exact_size_known() missing
55             //} else if (!hashtree()->exact_size_known()) {
56             //    return bin64_t(0,(hashtree()->size()>>10)-1); // dirty
57         }
58 retry:      // bite me
59         twist_ &= (hashtree()->peak(0).toUInt()) & ((1<<6)-1);
60 
61         bin_t hint = binmap_t::find_complement(ack_hint_out_, offer, twist_);
62 
63         if (hint.is_none()) {
64             return hint; // TODO: end-game mode
65         }
66 
67         if (!hashtree()->ack_out()->is_empty(hint)) { // unhinted/late data
68             binmap_t::copy(ack_hint_out_, *(hashtree()->ack_out()), hint);
69             goto retry;
70         }
71         while (hint.base_length()>max_width)
72             hint = hint.left();
73         assert(ack_hint_out_.is_empty(hint));
74         ack_hint_out_.set(hint);
75         hint_out_.push_back(tintbin(NOW,hint));
76         return hint;
77     }
78 
Seek(bin_t offbin,int whence)79     int Seek(bin_t offbin, int whence) {
80         return -1;
81     }
82 };
83