• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdenetwork API Reference
  • KDE Home
  • Contact Us
 

kget

  • sources
  • kde-4.12
  • kdenetwork
  • kget
  • transfer-plugins
  • bittorrent
btchunkselector.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2 
3  Copyright (C) 2008 Lukas Appelhans <l.appelhans@gmx.de>
4  Copyright (C) 2005 Joris Guisson <joris.guisson@gmail.com>
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 */
11 
12 #include "btchunkselector.h"
13 
14 #include <stdlib.h>
15 #include <vector>
16 #include <algorithm>
17 #include <util/log.h>
18 #include <util/bitset.h>
19 #include <peer/chunkcounter.h>
20 #include <diskio/chunkmanager.h>
21 #include <interfaces/piecedownloader.h>
22 #include <peer/peer.h>
23 #include <peer/peermanager.h>
24 #include <download/downloader.h>
25 
26 using namespace bt;
27 
28 struct RareCmp
29 {
30  ChunkManager & cman;
31  ChunkCounter & cc;
32  bool warmup;
33 
34  RareCmp(ChunkManager & cman,ChunkCounter & cc,bool warmup) : cman(cman),cc(cc),warmup(warmup) {}
35 
36  bool operator()(Uint32 a,Uint32 b)
37  {
38  if (a >= cman.getNumChunks() || b >= cman.getNumChunks())
39  return false;
40  // the sorting is done on two criteria, priority and rareness
41  Priority pa = cman.getChunk(a)->getPriority();
42  Priority pb = cman.getChunk(b)->getPriority();
43  if (pa == pb)
44  return normalCmp(a,b); // if both have same priority compare on rareness
45  else if (pa > pb) // pa has priority over pb, so select pa
46  return true;
47  else // pb has priority over pa, so select pb
48  return false;
49  }
50 
51  bool normalCmp(Uint32 a,Uint32 b)
52  {
53  // during warmup mode choose most common chunks
54  if (!warmup)
55  return cc.get(a) < cc.get(b);
56  else
57  return cc.get(a) > cc.get(b);
58  }
59 };
60 
61 BTChunkSelector::BTChunkSelector(ChunkManager & cman,Downloader & downer,PeerManager & pman)
62 : ChunkSelectorInterface(cman,downer,pman)
63 {
64  std::vector<Uint32> tmp;
65  for (Uint32 i = 0;i < cman.getNumChunks();++i)
66  {
67  if (!cman.getBitSet().get(i))
68  {
69  tmp.push_back(i);
70  }
71  }
72  std::random_shuffle(tmp.begin(),tmp.end());
73  // std::list does not support random_shuffle so we use a vector as a temporary storage
74  // for the random_shuffle
75  chunks.insert(chunks.begin(),tmp.begin(),tmp.end());
76  sort_timer.update();
77 }
78 
79 
80 BTChunkSelector::~BTChunkSelector()
81 {
82 }
83 
84 Uint32 BTChunkSelector::leastPeers(const std::list<Uint32> & lp)
85 {
86  Uint32 sel = lp.front();
87  Uint32 cnt = downer.numDownloadersForChunk(sel);
88  std::list<Uint32>::const_iterator itEnd = lp.end();
89  for (std::list<Uint32>::const_iterator i = lp.begin();i != itEnd;++i)
90  {
91  Uint32 cnt_i = downer.numDownloadersForChunk(*i);
92  if (cnt_i < cnt)
93  {
94  sel = *i;
95  cnt = cnt_i;
96  }
97  }
98  return sel;
99 }
100 
101 bool BTChunkSelector::select(PieceDownloader* pd,Uint32 & chunk)
102 {
103  const BitSet & bs = cman.getBitSet();
104 
105  std::list<Uint32> preview;
106  std::list<Uint32> normal;
107  std::list<Uint32> first;
108  Uint32 sel = cman.getNumChunks() + 1;
109 
110  // sort the chunks every 2 seconds
111  if (sort_timer.getElapsedSinceUpdate() > 2000)
112  {
113  bool warmup = cman.getNumChunks() - cman.chunksLeft() <= 4;
114  chunks.sort(RareCmp(cman,pman.getChunkCounter(),warmup));
115  sort_timer.update();
116  }
117 
118  std::list<Uint32>::iterator itr;
119  std::list<Uint32>::iterator itrEnd = chunks.end();
120  for (itr = chunks.begin(); itr != itrEnd; )
121  {
122  const Uint32 i = *itr;
123  Chunk* c = cman.getChunk(i);
124 
125  // if we have the chunk remove it from the list
126  if (bs.get(i))
127  {
128  itr = chunks.erase(itr);
129  }
130  else
131  {
132  // pd has to have the selected chunk and it needs to be not excluded
133  if (pd->hasChunk(i) && !c->isExcluded() && !c->isExcludedForDownloading())
134  {
135  if (!downer.areWeDownloading(i))
136  {
137  // we have a chunk
138  sel = i;
139  break;
140  }
141 
142  switch (cman.getChunk(i)->getPriority())
143  {
144  case PREVIEW_PRIORITY:
145  preview.push_back(i);
146  break;
147  case FIRST_PRIORITY:
148  first.push_back(i);
149  break;
150  case NORMAL_PRIORITY:
151  normal.push_back(i);
152  break;
153  default:
154  break;
155  }
156  }
157  ++itr;
158  }
159  }
160 
161  if (sel >= cman.getNumChunks())
162  return false;
163 
164  // we have found one, now try to see if we cannot assign this PieceDownloader to a higher priority chunk
165  switch (cman.getChunk(sel)->getPriority())
166  {
167  case PREVIEW_PRIORITY:
168  chunk = sel;
169  return true;
170  case FIRST_PRIORITY:
171  if (preview.size() > 0)
172  {
173  chunk = leastPeers(preview);
174  return true;
175  }
176  else
177  {
178  chunk = sel;
179  return true;
180  }
181  break;
182  case NORMAL_PRIORITY:
183  if (preview.size() > 0)
184  {
185  chunk = leastPeers(preview);
186  return true;
187  }
188  else if (first.size() > 0)
189  {
190  chunk = leastPeers(first);
191  return true;
192  }
193  else
194  {
195  chunk = sel;
196  return true;
197  }
198  break;
199  case LAST_PRIORITY:
200  if (preview.size() > 0)
201  {
202  chunk = leastPeers(preview);
203  return true;
204  }
205  else if (first.size() > 0)
206  {
207  chunk = leastPeers(first);
208  return true;
209  }
210  else if (normal.size() > 0)
211  {
212  chunk = leastPeers(normal);
213  return true;
214  }
215  else
216  {
217  chunk = sel;
218  return true;
219  }
220  break;
221  default:
222  chunk = sel;
223  return true;
224  }
225 
226  return false;
227 }
228 
229 void BTChunkSelector::dataChecked(const BitSet & ok_chunks)
230 {
231  for (Uint32 i = 0;i < ok_chunks.getNumBits();++i)
232  {
233  bool in_chunks = std::find(chunks.begin(),chunks.end(),i) != chunks.end();
234  if (in_chunks && ok_chunks.get(i))
235  {
236  // if we have the chunk, remove it from the chunks list
237  chunks.remove(i);
238  }
239  else if (!in_chunks && !ok_chunks.get(i))
240  {
241  // if we don't have the chunk, add it to the list if it wasn't allrready in there
242  chunks.push_back(i);
243  }
244  }
245 }
246 
247 void BTChunkSelector::reincluded(Uint32 from, Uint32 to)
248 {
249 // lets do a safety check first
250  if (from >= cman.getNumChunks() || to >= cman.getNumChunks())
251  {
252  Out(SYS_DIO|LOG_NOTICE) << "Internal error in chunkselector" << endl;
253  return;
254  }
255 
256  for (Uint32 i = from;i <= to;++i)
257  {
258  bool in_chunks = std::find(chunks.begin(),chunks.end(),i) != chunks.end();
259  if (!in_chunks && cman.getChunk(i)->getStatus() != Chunk::ON_DISK)
260  {
261  // Out(SYS_DIO|LOG_DEBUG) << "BTChunkSelector::reIncluded " << i << endl;
262  chunks.push_back(i);
263  }
264  }
265 }
266 
267 void BTChunkSelector::reinsert(Uint32 chunk)
268 {
269  bool in_chunks = std::find(chunks.begin(),chunks.end(),chunk) != chunks.end();
270  if (!in_chunks)
271  chunks.push_back(chunk);
272 }
273 
274 void BTChunkSelector::excludeAll()
275 {
276  chunks.clear();
277 }
278 
279 void BTChunkSelector::exclude(Uint32 chunk)
280 {
281  bool in_chunks = std::find(chunks.begin(),chunks.end(),chunk) != chunks.end();
282  if (in_chunks)
283  chunks.remove(chunk);
284 }
285 
286 BTChunkSelectorFactory::BTChunkSelectorFactory()
287 {
288 }
289 
290 BTChunkSelectorFactory::~BTChunkSelectorFactory()
291 {
292 }
293 
294 bt::ChunkSelectorInterface* BTChunkSelectorFactory::createChunkSelector(bt::ChunkManager & cman, bt::Downloader & downer, bt::PeerManager & pman)
295 {
296  BTChunkSelector *selector = new BTChunkSelector(cman, downer, pman);
297  emit selectorAdded(selector);
298  return selector;
299 }
300 
301 #include "btchunkselector.moc"
BTChunkSelectorFactory::BTChunkSelectorFactory
BTChunkSelectorFactory()
Definition: btchunkselector.cpp:286
btchunkselector.h
BTChunkSelector
Definition: btchunkselector.h:29
BTChunkSelector::~BTChunkSelector
~BTChunkSelector()
Definition: btchunkselector.cpp:80
BTChunkSelector::exclude
virtual void exclude(bt::Uint32 chunk)
Definition: btchunkselector.cpp:279
BTChunkSelector::reinsert
virtual void reinsert(bt::Uint32 chunk)
Definition: btchunkselector.cpp:267
BTChunkSelector::reincluded
virtual void reincluded(bt::Uint32 from, bt::Uint32 to)
Definition: btchunkselector.cpp:247
BTChunkSelectorFactory::~BTChunkSelectorFactory
~BTChunkSelectorFactory()
Definition: btchunkselector.cpp:290
BTChunkSelector::excludeAll
virtual void excludeAll()
Definition: btchunkselector.cpp:274
BTChunkSelectorFactory::selectorAdded
void selectorAdded(BTChunkSelector *selector)
BTChunkSelector::dataChecked
virtual void dataChecked(const bt::BitSet &ok_chunks)
Definition: btchunkselector.cpp:229
BTChunkSelector::select
virtual bool select(bt::PieceDownloader *pd, bt::Uint32 &chunk)
Definition: btchunkselector.cpp:101
BTChunkSelectorFactory::createChunkSelector
bt::ChunkSelectorInterface * createChunkSelector(bt::ChunkManager &cman, bt::Downloader &downer, bt::PeerManager &pman)
Definition: btchunkselector.cpp:294
BTChunkSelector::BTChunkSelector
BTChunkSelector(bt::ChunkManager &cman, bt::Downloader &downer, bt::PeerManager &pman)
Definition: btchunkselector.cpp:61
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:53:17 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kget

Skip menu "kget"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdenetwork API Reference

Skip menu "kdenetwork API Reference"
  • kget
  • kopete
  •   kopete
  •   libkopete
  • krdc
  • krfb

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal