kget
btchunkselector.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "btchunkselector.h"
00013
00014 #include <stdlib.h>
00015 #include <vector>
00016 #include <algorithm>
00017 #include <util/log.h>
00018 #include <util/bitset.h>
00019 #include <peer/chunkcounter.h>
00020 #include <diskio/chunkmanager.h>
00021 #include <interfaces/piecedownloader.h>
00022 #include <peer/peer.h>
00023 #include <peer/peermanager.h>
00024 #include <download/downloader.h>
00025
00026 using namespace bt;
00027
00028 struct RareCmp
00029 {
00030 ChunkManager & cman;
00031 ChunkCounter & cc;
00032 bool warmup;
00033
00034 RareCmp(ChunkManager & cman,ChunkCounter & cc,bool warmup) : cman(cman),cc(cc),warmup(warmup) {}
00035
00036 bool operator()(Uint32 a,Uint32 b)
00037 {
00038 if (a >= cman.getNumChunks() || b >= cman.getNumChunks())
00039 return false;
00040
00041 Priority pa = cman.getChunk(a)->getPriority();
00042 Priority pb = cman.getChunk(b)->getPriority();
00043 if (pa == pb)
00044 return normalCmp(a,b);
00045 else if (pa > pb)
00046 return true;
00047 else
00048 return false;
00049 }
00050
00051 bool normalCmp(Uint32 a,Uint32 b)
00052 {
00053
00054 if (!warmup)
00055 return cc.get(a) < cc.get(b);
00056 else
00057 return cc.get(a) > cc.get(b);
00058 }
00059 };
00060
00061 BTChunkSelector::BTChunkSelector(ChunkManager & cman,Downloader & downer,PeerManager & pman)
00062 : ChunkSelectorInterface(cman,downer,pman)
00063 {
00064 std::vector<Uint32> tmp;
00065 for (Uint32 i = 0;i < cman.getNumChunks();i++)
00066 {
00067 if (!cman.getBitSet().get(i))
00068 {
00069 tmp.push_back(i);
00070 }
00071 }
00072 std::random_shuffle(tmp.begin(),tmp.end());
00073
00074
00075 chunks.insert(chunks.begin(),tmp.begin(),tmp.end());
00076 sort_timer.update();
00077 }
00078
00079
00080 BTChunkSelector::~BTChunkSelector()
00081 {
00082 }
00083
00084 Uint32 BTChunkSelector::leastPeers(const std::list<Uint32> & lp)
00085 {
00086 Uint32 sel = lp.front();
00087 Uint32 cnt = downer.numDownloadersForChunk(sel);
00088 for (std::list<Uint32>::const_iterator i = lp.begin();i != lp.end();i++)
00089 {
00090 Uint32 cnt_i = downer.numDownloadersForChunk(*i);
00091 if (cnt_i < cnt)
00092 {
00093 sel = *i;
00094 cnt = cnt_i;
00095 }
00096 }
00097 return sel;
00098 }
00099
00100 bool BTChunkSelector::select(PieceDownloader* pd,Uint32 & chunk)
00101 {
00102 const BitSet & bs = cman.getBitSet();
00103
00104 std::list<Uint32> preview;
00105 std::list<Uint32> normal;
00106 std::list<Uint32> first;
00107 Uint32 sel = cman.getNumChunks() + 1;
00108
00109
00110 if (sort_timer.getElapsedSinceUpdate() > 2000)
00111 {
00112 bool warmup = cman.getNumChunks() - cman.chunksLeft() <= 4;
00113 chunks.sort(RareCmp(cman,pman.getChunkCounter(),warmup));
00114 sort_timer.update();
00115 }
00116
00117 std::list<Uint32>::iterator itr = chunks.begin();
00118 while (itr != chunks.end())
00119 {
00120 Uint32 i = *itr;
00121 Chunk* c = cman.getChunk(*itr);
00122
00123
00124 if (bs.get(i))
00125 {
00126 std::list<Uint32>::iterator tmp = itr;
00127 itr++;
00128 chunks.erase(tmp);
00129 }
00130 else
00131 {
00132
00133 if (pd->hasChunk(i) && !c->isExcluded() && !c->isExcludedForDownloading())
00134 {
00135 if (!downer.areWeDownloading(i))
00136 {
00137
00138 sel = i;
00139 break;
00140 }
00141
00142 switch (cman.getChunk(i)->getPriority())
00143 {
00144 case PREVIEW_PRIORITY:
00145 preview.push_back(i);
00146 break;
00147 case FIRST_PRIORITY:
00148 first.push_back(i);
00149 break;
00150 case NORMAL_PRIORITY:
00151 normal.push_back(i);
00152 break;
00153 default:
00154 break;
00155 }
00156 }
00157 itr++;
00158 }
00159 }
00160
00161 if (sel >= cman.getNumChunks())
00162 return false;
00163
00164
00165 switch (cman.getChunk(sel)->getPriority())
00166 {
00167 case PREVIEW_PRIORITY:
00168 chunk = sel;
00169 return true;
00170 case FIRST_PRIORITY:
00171 if (preview.size() > 0)
00172 {
00173 chunk = leastPeers(preview);
00174 return true;
00175 }
00176 else
00177 {
00178 chunk = sel;
00179 return true;
00180 }
00181 break;
00182 case NORMAL_PRIORITY:
00183 if (preview.size() > 0)
00184 {
00185 chunk = leastPeers(preview);
00186 return true;
00187 }
00188 else if (first.size() > 0)
00189 {
00190 chunk = leastPeers(first);
00191 return true;
00192 }
00193 else
00194 {
00195 chunk = sel;
00196 return true;
00197 }
00198 break;
00199 case LAST_PRIORITY:
00200 if (preview.size() > 0)
00201 {
00202 chunk = leastPeers(preview);
00203 return true;
00204 }
00205 else if (first.size() > 0)
00206 {
00207 chunk = leastPeers(first);
00208 return true;
00209 }
00210 else if (normal.size() > 0)
00211 {
00212 chunk = leastPeers(normal);
00213 return true;
00214 }
00215 else
00216 {
00217 chunk = sel;
00218 return true;
00219 }
00220 break;
00221 default:
00222 chunk = sel;
00223 return true;
00224 }
00225
00226 return false;
00227 }
00228
00229 void BTChunkSelector::dataChecked(const BitSet & ok_chunks)
00230 {
00231 for (Uint32 i = 0;i < ok_chunks.getNumBits();i++)
00232 {
00233 bool in_chunks = std::find(chunks.begin(),chunks.end(),i) != chunks.end();
00234 if (in_chunks && ok_chunks.get(i))
00235 {
00236
00237 chunks.remove(i);
00238 }
00239 else if (!in_chunks && !ok_chunks.get(i))
00240 {
00241
00242 chunks.push_back(i);
00243 }
00244 }
00245 }
00246
00247 void BTChunkSelector::reincluded(Uint32 from, Uint32 to)
00248 {
00249
00250 if (from >= cman.getNumChunks() || to >= cman.getNumChunks())
00251 {
00252 Out(SYS_DIO|LOG_NOTICE) << "Internal error in chunkselector" << endl;
00253 return;
00254 }
00255
00256 for (Uint32 i = from;i <= to;i++)
00257 {
00258 bool in_chunks = std::find(chunks.begin(),chunks.end(),i) != chunks.end();
00259 if (!in_chunks && cman.getChunk(i)->getStatus() != Chunk::ON_DISK)
00260 {
00261
00262 chunks.push_back(i);
00263 }
00264 }
00265 }
00266
00267 void BTChunkSelector::reinsert(Uint32 chunk)
00268 {
00269 bool in_chunks = std::find(chunks.begin(),chunks.end(),chunk) != chunks.end();
00270 if (!in_chunks)
00271 chunks.push_back(chunk);
00272 }
00273
00274 void BTChunkSelector::excludeAll()
00275 {
00276 chunks.clear();
00277 }
00278
00279 void BTChunkSelector::exclude(Uint32 chunk)
00280 {
00281 bool in_chunks = std::find(chunks.begin(),chunks.end(),chunk) != chunks.end();
00282 if (in_chunks)
00283 chunks.remove(chunk);
00284 }
00285
00286 BTChunkSelectorFactory::BTChunkSelectorFactory()
00287 {
00288 }
00289
00290 BTChunkSelectorFactory::~BTChunkSelectorFactory()
00291 {
00292 }
00293
00294 bt::ChunkSelectorInterface* BTChunkSelectorFactory::createChunkSelector(bt::ChunkManager & cman, bt::Downloader & downer, bt::PeerManager & pman)
00295 {
00296 BTChunkSelector *selector = new BTChunkSelector(cman, downer, pman);
00297 emit selectorAdded(selector);
00298 return selector;
00299 }
00300
00301 #include "btchunkselector.moc"