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>
34 RareCmp(ChunkManager & cman,ChunkCounter & cc,
bool warmup) : cman(cman),cc(cc),warmup(warmup) {}
36 bool operator()(Uint32 a,Uint32 b)
38 if (a >= cman.getNumChunks() || b >= cman.getNumChunks())
41 Priority pa = cman.getChunk(a)->getPriority();
42 Priority pb = cman.getChunk(b)->getPriority();
44 return normalCmp(a,b);
51 bool normalCmp(Uint32 a,Uint32 b)
55 return cc.get(a) < cc.get(b);
57 return cc.get(a) > cc.get(b);
62 : ChunkSelectorInterface(cman,downer,pman)
64 std::vector<Uint32> tmp;
65 for (Uint32 i = 0;i < cman.getNumChunks();++i)
67 if (!cman.getBitSet().get(i))
72 std::random_shuffle(tmp.begin(),tmp.end());
75 chunks.insert(chunks.begin(),tmp.begin(),tmp.end());
84 Uint32 BTChunkSelector::leastPeers(
const std::list<Uint32> & lp)
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)
91 Uint32 cnt_i = downer.numDownloadersForChunk(*i);
103 const BitSet & bs = cman.getBitSet();
105 std::list<Uint32> preview;
106 std::list<Uint32> normal;
107 std::list<Uint32> first;
108 Uint32 sel = cman.getNumChunks() + 1;
111 if (sort_timer.getElapsedSinceUpdate() > 2000)
113 bool warmup = cman.getNumChunks() - cman.chunksLeft() <= 4;
114 chunks.sort(RareCmp(cman,pman.getChunkCounter(),warmup));
118 std::list<Uint32>::iterator itr;
119 std::list<Uint32>::iterator itrEnd = chunks.end();
120 for (itr = chunks.begin(); itr != itrEnd; )
122 const Uint32 i = *itr;
123 Chunk* c = cman.getChunk(i);
128 itr = chunks.erase(itr);
133 if (pd->hasChunk(i) && !c->isExcluded() && !c->isExcludedForDownloading())
135 if (!downer.areWeDownloading(i))
142 switch (cman.getChunk(i)->getPriority())
144 case PREVIEW_PRIORITY:
145 preview.push_back(i);
150 case NORMAL_PRIORITY:
161 if (sel >= cman.getNumChunks())
165 switch (cman.getChunk(sel)->getPriority())
167 case PREVIEW_PRIORITY:
171 if (preview.size() > 0)
173 chunk = leastPeers(preview);
182 case NORMAL_PRIORITY:
183 if (preview.size() > 0)
185 chunk = leastPeers(preview);
188 else if (first.size() > 0)
190 chunk = leastPeers(first);
200 if (preview.size() > 0)
202 chunk = leastPeers(preview);
205 else if (first.size() > 0)
207 chunk = leastPeers(first);
210 else if (normal.size() > 0)
212 chunk = leastPeers(normal);
231 for (Uint32 i = 0;i < ok_chunks.getNumBits();++i)
233 bool in_chunks = std::find(chunks.begin(),chunks.end(),i) != chunks.end();
234 if (in_chunks && ok_chunks.get(i))
239 else if (!in_chunks && !ok_chunks.get(i))
250 if (from >= cman.getNumChunks() || to >= cman.getNumChunks())
252 Out(SYS_DIO|LOG_NOTICE) <<
"Internal error in chunkselector" << endl;
256 for (Uint32 i = from;i <= to;++i)
258 bool in_chunks = std::find(chunks.begin(),chunks.end(),i) != chunks.end();
259 if (!in_chunks && cman.getChunk(i)->getStatus() != Chunk::ON_DISK)
269 bool in_chunks = std::find(chunks.begin(),chunks.end(),chunk) != chunks.end();
271 chunks.push_back(chunk);
281 bool in_chunks = std::find(chunks.begin(),chunks.end(),chunk) != chunks.end();
283 chunks.remove(chunk);
301 #include "btchunkselector.moc"
virtual void exclude(bt::Uint32 chunk)
virtual void reinsert(bt::Uint32 chunk)
virtual void reincluded(bt::Uint32 from, bt::Uint32 to)
~BTChunkSelectorFactory()
virtual void excludeAll()
void selectorAdded(BTChunkSelector *selector)
virtual void dataChecked(const bt::BitSet &ok_chunks)
virtual bool select(bt::PieceDownloader *pd, bt::Uint32 &chunk)
bt::ChunkSelectorInterface * createChunkSelector(bt::ChunkManager &cman, bt::Downloader &downer, bt::PeerManager &pman)
BTChunkSelector(bt::ChunkManager &cman, bt::Downloader &downer, bt::PeerManager &pman)