5 * Created by Riccardo Petrocco.
6 * Copyright 2009-2012 Delft University of Technology. All rights reserved.
13 using namespace swift;
15 #define HIGHPRIORITYWINDOW 45000; // initial high priority window in bin unit
16 #define MIDPRIORITYWINDOW 4; // proportion of the mid priority window compared to the high pri. one
18 /** Picks pieces in VoD fashion. The stream is divided in three priority
19 * sets based on the current playback position. In the high priority set
20 * bins are selected in order, while on the medium and low priority sets
21 * in a rarest fist fashion */
22 class VodPiecePicker : public PiecePicker {
24 binmap_t ack_hint_out_;
26 FileTransfer* transfer_;
30 int playback_pos_; // playback position in KB
35 VodPiecePicker (FileTransfer* file_to_pick_from) : ack_hint_out_(),
36 transfer_(file_to_pick_from), twist_(0), range_(bin_t::ALL)
38 avail_ = &(transfer_->availability());
39 binmap_t::copy(ack_hint_out_, file().ack_out());
41 high_pri_window_ = HIGHPRIORITYWINDOW;
44 virtual ~VodPiecePicker() {}
47 return transfer_->file();
50 virtual void Randomize (uint64_t twist) {
51 // Arno, 2012-03-21: After consulting with Riccardo, disable
52 // twisting for VOD PP. Randomization of peers over the bitmap
53 // is already guaranteed by the ack_hint_out_ (prevents double requesting)
57 virtual void LimitRange (bin_t range) {
62 bin_t getTopBin(bin_t bin, uint64_t start, uint64_t size)
64 while (bin.parent().base_length() <= size && bin.parent().base_left() >= bin_t(start))
72 bin_t pickUrgent (binmap_t& offer, uint64_t max_width, uint64_t size) {
74 bin_t curr = bin_t((playback_pos_+1)<<1); // the base bin will be indexed by the double of the value (bin(4) == bin(0,2))
75 bin_t hint = bin_t::NONE;
76 uint64_t examined = 0;
79 // report the first bin we find
80 while (hint.is_none() && examined < size)
82 curr = getTopBin(curr, (playback_pos_+1)<<1, size-examined);
83 if (!ack_hint_out_.is_filled(curr))
86 binmap_t::copy(binmap, ack_hint_out_, curr);
87 hint = binmap_t::find_complement(binmap, offer, twist_);
90 examined += curr.base_length();
91 curr = bin_t(0, curr.base_right().layer_offset()+1 );
95 while (hint.base_length()>max_width && !hint.is_base()) // Arno,2012-01-17: stop!
102 bin_t pickRarest (binmap_t& offer, uint64_t max_width, uint64_t start, uint64_t size) {
104 //fprintf(stderr,"%s #1 Picker -> choosing from mid/low priority \n",tintstr());
105 bin_t curr = bin_t(start<<1);
106 bin_t hint = bin_t::NONE;
107 uint64_t examined = 0;
108 //uint64_t size = end-start;
109 bin_t rarest_hint = bin_t::NONE;
113 // TODO.. this is the dummy version... put some logic in deciding what to DL
114 while (examined < size)
116 curr = getTopBin(curr, start<<1, size-examined);
118 if (!ack_hint_out_.is_filled(curr))
121 //binmap_t::copy(binmap, offer);
122 //binmap.reset(curr);
125 binmap_t::copy(binmap, ack_hint_out_, curr);
126 //hint = binmap_t::find_complement(ack_hint_out_, offer, curr, twist_);
127 hint = binmap_t::find_complement(binmap, offer, twist_);
134 rarest_hint = avail_->get(rarest_hint) < avail_->get(hint) ? rarest_hint : hint;
144 examined += curr.base_length();
145 curr = bin_t(0, curr.base_right().layer_offset()+1 );
149 if (!rarest_hint.is_none())
152 rarest_hint = avail_->getRarest(rarest_hint, max_width);
154 while (rarest_hint.base_length()>max_width && !rarest_hint.is_base()) // Arno,2012-01-17: stop!
155 rarest_hint.to_left();
162 virtual bin_t Pick (binmap_t& offer, uint64_t max_width, tint expires)
167 char set = 'X'; // TODO remove set var, only used for debug
169 // TODO check... the seconds should depend on previous speed of the peer
170 while (hint_out_.size() && hint_out_.front().time<NOW-TINT_SEC*3/2) { // FIXME sec
171 binmap_t::copy(ack_hint_out_, file().ack_out(), hint_out_.front().bin);
172 hint_out_.pop_front();
175 // get the first piece to estimate the size, whoever sends it first
176 if (!file().size()) {
182 uint64_t max_size = file().size_in_chunks() - playback_pos_ - 1;
183 max_size = high_pri_window_ < max_size ? high_pri_window_ : max_size;
185 // check the high priority window for data we r missing
186 hint = pickUrgent(offer, max_width, max_size);
188 // check the mid priority window
189 uint64_t start = (1 + playback_pos_) + HIGHPRIORITYWINDOW; // start in KB
190 if (hint.is_none() && start < file().size_in_chunks())
192 int mid = MIDPRIORITYWINDOW;
193 int size = mid * HIGHPRIORITYWINDOW; // size of window in KB
195 max_size = file().size_in_chunks() - start;
196 max_size = size < max_size ? size : max_size;
198 hint = pickRarest(offer, max_width, start, max_size);
202 if (hint.is_none() && start < file().size_in_chunks())
204 size = file().size_in_chunks() - start;
205 hint = pickRarest(offer, max_width, start, size);
214 // unhinted/late data
215 if (!file().ack_out().is_empty(hint)) {
216 binmap_t::copy(ack_hint_out_, file().ack_out(), hint);
225 if (hint.is_none()) {
226 // TODO, control if we want: check for missing hints (before playback pos.)
227 hint = binmap_t::find_complement(ack_hint_out_, offer, twist_);
228 // TODO: end-game mode
232 while (hint.base_length()>max_width && !hint.is_base()) // Arno,2012-01-17: stop!
238 assert(ack_hint_out_.is_empty(hint));
239 ack_hint_out_.set(hint);
240 hint_out_.push_back(tintbin(NOW,hint));
243 // TODO clean ... printing percentage of completeness for the priority sets
246 //fprintf(stderr,"%s #1 Picker -> picked %s\t from %c set\t max width %lu \n",tintstr(), hint.str(tmp), set, max_width );
247 //if (avail_->size())
252 void updatePlaybackPos(int size = 1)
255 if (size< file().size_in_chunks() - playback_pos_ - 2)
256 playback_pos_ += size;
263 int x = HIGHPRIORITYWINDOW;
264 int y = MIDPRIORITYWINDOW;
265 int i = playback_pos_ + 1;
266 int end_high = (x+playback_pos_)<<1;
267 int end_mid = ((x*y)+x+playback_pos_)<<1;
273 if (!file().ack_out().is_empty(bin_t(i)))
278 t = t*100/((x<<1)-1);
279 fprintf(stderr, "low %u, ", t);
283 if (!file().ack_out().is_empty(bin_t(i)))
288 t = t*100/((x*y)<<1);
289 fprintf(stderr, "mid %u, ", t);
291 while (i<=file().size_in_chunks()<<1)
293 if (!file().ack_out().is_empty(bin_t(i)))
298 t = t*100/((file().size_in_chunks()-(x*y+playback_pos_))<<1);
299 fprintf(stderr, "low %u -> in total: %i\t pp: %i\n", t, total, playback_pos_);