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

kget

btchunkselector.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002 
00003    Copyright (C) 2008 Lukas Appelhans <l.appelhans@gmx.de>
00004    Copyright (C) 2005 Joris Guisson <joris.guisson@gmail.com>
00005 
00006    This program is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
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         // the sorting is done on two criteria, priority and rareness
00041         Priority pa = cman.getChunk(a)->getPriority();
00042         Priority pb = cman.getChunk(b)->getPriority();
00043         if (pa == pb)
00044             return normalCmp(a,b); // if both have same priority compare on rareness
00045         else if (pa > pb) // pa has priority over pb, so select pa
00046             return true;
00047         else // pb has priority over pa, so select pb
00048             return false;
00049     }
00050 
00051     bool normalCmp(Uint32 a,Uint32 b)
00052     {
00053         // during warmup mode choose most common chunks
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     // std::list does not support random_shuffle so we use a vector as a temporary storage
00074     // for the random_shuffle
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     // sort the chunks every 2 seconds
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         // if we have the chunk remove it from the list
00124         if (bs.get(i))
00125         {
00126             std::list<Uint32>::iterator tmp = itr;
00127             itr++;
00128             chunks.erase(tmp);
00129         }
00130         else
00131         {
00132             // pd has to have the selected chunk and it needs to be not excluded
00133             if (pd->hasChunk(i) && !c->isExcluded() && !c->isExcludedForDownloading())
00134             {
00135                 if (!downer.areWeDownloading(i))
00136                 { 
00137                     // we have a chunk
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     // we have found one, now try to see if we cannot assign this PieceDownloader to a higher priority chunk
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             // if we have the chunk, remove it from the chunks list
00237             chunks.remove(i);
00238         }
00239         else if (!in_chunks && !ok_chunks.get(i))
00240         {
00241             // if we don't have the chunk, add it to the list if it wasn't allrready in there
00242             chunks.push_back(i);
00243         }
00244     }
00245 }
00246 
00247 void BTChunkSelector::reincluded(Uint32 from, Uint32 to)
00248 {
00249 // lets do a safety check first
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             //      Out(SYS_DIO|LOG_DEBUG) << "BTChunkSelector::reIncluded " << i << endl;
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"

kget

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

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal