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

kget

advancedchokealgorithm.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Joris Guisson                                   *
00003  *   joris.guisson@gmail.com                                               *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
00019  ***************************************************************************/
00020 #include "advancedchokealgorithm.h"
00021 #include <util/functions.h>
00022 #include <interfaces/torrentinterface.h>
00023 #include <diskio/chunkmanager.h>
00024 #include <peer/peer.h>
00025 #include <peer/peermanager.h>
00026 #include <peer/packetwriter.h>
00027 #include <krandom.h>
00028 
00029 
00030 namespace bt
00031 {
00032     
00033     
00034     const Uint32 OPT_SEL_INTERVAL = 30*1000; // we switch optimistic peer each 30 seconds
00035     const double NEWBIE_BONUS = 1.0;
00036     const double SNUB_PENALTY = 10.0;
00037     const double ONE_MB = 1024*1024;
00038         
00039 
00040     AdvancedChokeAlgorithm::AdvancedChokeAlgorithm()
00041             : ChokeAlgorithm()
00042     {
00043         last_opt_sel_time = 0;
00044     }
00045 
00046 
00047     AdvancedChokeAlgorithm::~AdvancedChokeAlgorithm()
00048     {}
00049     
00050     bool AdvancedChokeAlgorithm::calcACAScore(Peer* p,ChunkManager & cman,const TorrentStats & stats)
00051     {
00052         const PeerInterface::Stats & s = p->getStats();
00053         if (p->isSeeder())
00054         {
00055             /*
00056             double bd = 0;
00057             if (stats.trk_bytes_downloaded > 0)
00058                 bd = s.bytes_downloaded / stats.trk_bytes_downloaded;
00059             double ds = 0;
00060             if (stats.download_rate > 0)
00061                 ds = s.download_rate/ stats.download_rate;
00062             p->setACAScore(5*bd + 5*ds);
00063             */
00064             p->setACAScore(0.0);
00065             return false;
00066         }
00067         
00068         bool should_be_interested = false;
00069         bool should_we_be_interested = false;
00070         // before we start calculating first check if we have piece that the peer doesn't have
00071         const BitSet & ours = cman.getBitSet();
00072         const BitSet & theirs = p->getBitSet();
00073         for (Uint32 i = 0;i < ours.getNumBits();i++)
00074         {
00075             if (ours.get(i) && !theirs.get(i))
00076             {
00077                 should_be_interested = true;
00078                 break;
00079             }
00080         }
00081         
00082         if (!should_be_interested || !p->isInterested())
00083         {
00084             // not interseted so it doesn't make sense to unchoke it
00085             p->setACAScore(-50.0);
00086             return false;
00087         }
00088 
00089                 
00090         
00091         double nb = 0.0; // newbie bonus
00092         double cp = 0.0; // choke penalty
00093         double sp = 0.0; // snubbing penalty
00094         double lb = s.local ? 10.0 : 0.0; // local peers get a bonus of 10
00095         double bd = s.bytes_downloaded; // bytes downloaded
00096         double tbd = stats.trk_bytes_downloaded; // total bytes downloaded
00097         double ds = s.download_rate; // current download rate
00098         double tds = stats.download_rate; // total download speed
00099         
00100         // if the peer has less than 1 MB or 0.5 % of the torrent it is a newbie
00101         if (p->percentAvailable() < 0.5 && stats.total_bytes * p->percentAvailable() < 1024*1024)
00102         {
00103             nb = NEWBIE_BONUS;
00104         }
00105         
00106         if (p->isChoked())
00107         {
00108             cp = NEWBIE_BONUS; // cp cancels out newbie bonus
00109         }
00110         
00111         // if the evil bit is on (!choked, snubbed and requests have timed out)
00112         if (s.evil)
00113         {
00114             sp = SNUB_PENALTY;
00115         }
00116         
00117         // NB + K * (BD/TBD) - CP - SP + L * (DS / TDS)
00118         double K = 5.0;
00119         double L = 5.0;
00120         double aca = lb + nb + (tbd > 0 ? K * (bd/tbd) : 0.0) + (tds > 0 ? L* (ds / tds) : 0.0) - cp - sp;
00121         
00122         p->setACAScore(aca);
00123         return true;
00124     }
00125     
00126     static int ACACmp(Peer* a,Peer* b)
00127     {
00128         if (a->getStats().aca_score < b->getStats().aca_score)
00129             return 1;
00130         else if (a->getStats().aca_score > b->getStats().aca_score)
00131             return -1;
00132         else
00133             return 0;
00134     }
00135     
00136 
00137     void AdvancedChokeAlgorithm::doChokingLeechingState(PeerManager & pman,ChunkManager & cman,const TorrentStats & stats)
00138     {
00139         PeerPtrList ppl;
00140         Uint32 np = pman.getNumConnectedPeers();
00141         // add all non seeders
00142         for (Uint32 i = 0;i < np;i++)
00143         {
00144             Peer* p = pman.getPeer(i);
00145             if (p)
00146             {
00147                 if (calcACAScore(p,cman,stats))
00148                     ppl.append(p);
00149                 else
00150                     // choke seeders they do not want to download from us anyway
00151                     p->choke();
00152             }
00153         }
00154         
00155         // sort list by ACA score
00156         ppl.setCompareFunc(ACACmp); 
00157         qSort(ppl.begin(), ppl.end());
00158         
00159         doUnchoking(ppl,updateOptimisticPeer(pman,ppl));
00160     }
00161     
00162     void AdvancedChokeAlgorithm::doUnchoking(PeerPtrList & ppl,Peer* poup)
00163     {
00164         // Get the number of upload slots
00165         Uint32 num_slots = Choker::getNumUploadSlots();
00166         // Do the choking and unchoking
00167         Uint32 num_unchoked = 0;
00168         for (Uint32 i = 0;i < ppl.count();i++)
00169         {
00170             Peer* p = ppl.at(i);
00171             if (!poup && num_unchoked < num_slots)
00172             {
00173                 p->getPacketWriter().sendUnchoke();
00174                 num_unchoked++;
00175             }
00176             else if (num_unchoked < num_slots -1 || p == poup)
00177             {
00178                 p->getPacketWriter().sendUnchoke();
00179                 if (p != poup)
00180                     num_unchoked++;
00181             }
00182             else
00183             {
00184                 p->choke();
00185             }
00186         }
00187     }
00188     
00189     static int UpRateCmp(Peer* a,Peer* b)
00190     {
00191         if (a->getStats().upload_rate < b->getStats().upload_rate)
00192             return -1;
00193         else if (a->getStats().upload_rate > b->getStats().upload_rate)
00194             return 1;
00195         else
00196             return 0;
00197     }
00198 
00199     void AdvancedChokeAlgorithm::doChokingSeedingState(PeerManager & pman,ChunkManager & cman,const TorrentStats & stats)
00200     {
00201         PeerPtrList ppl;
00202         Uint32 np = pman.getNumConnectedPeers();
00203         // add all non seeders
00204         for (Uint32 i = 0;i < np;i++)
00205         {
00206             Peer* p = pman.getPeer(i);
00207             if (p)
00208             {
00209                 // update the ACA score in the process
00210                 if (calcACAScore(p,cman,stats))
00211                     ppl.append(p);
00212                 else
00213                     // choke seeders they do not want to download from us anyway
00214                     p->choke();  
00215             }
00216         }
00217         
00218         ppl.setCompareFunc(UpRateCmp);
00219         qSort(ppl.begin(), ppl.end());
00220         
00221         doUnchoking(ppl,updateOptimisticPeer(pman,ppl));
00222     }
00223     
00224     static Uint32 FindPlannedOptimisticUnchokedPeer(PeerManager& pman,const PeerPtrList & ppl)
00225     {
00226         Uint32 num_peers = pman.getNumConnectedPeers();
00227         if (num_peers == 0)
00228             return UNDEFINED_ID;
00229             
00230         // find a random peer that is choked and interested
00231         Uint32 start = KRandom::random() % num_peers;
00232         Uint32 i = (start + 1) % num_peers;
00233         while (i != start)
00234         {
00235             Peer* p = pman.getPeer(i);
00236             if (p && p->isChoked() && p->isInterested() && !p->isSeeder() && ppl.contains(p))
00237                 return p->getID();
00238             i = (i + 1) % num_peers;
00239         }
00240         
00241         // we do not expect to have 4 billion peers
00242         return UNDEFINED_ID;
00243     }
00244     
00245     Peer* AdvancedChokeAlgorithm::updateOptimisticPeer(PeerManager & pman,const PeerPtrList & ppl)
00246     {
00247         // get the planned optimistic unchoked peer and change it if necessary
00248         Peer* poup = pman.findPeer(opt_unchoked_peer_id);
00249         TimeStamp now = GetCurrentTime();
00250         if (now - last_opt_sel_time > OPT_SEL_INTERVAL || !poup)
00251         {
00252             opt_unchoked_peer_id = FindPlannedOptimisticUnchokedPeer(pman,ppl);
00253             last_opt_sel_time = now;
00254             poup = pman.findPeer(opt_unchoked_peer_id);
00255         }
00256         return poup;
00257     }
00258 }

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