Changeset 8

Show
Ignore:
Timestamp:
07/25/04 14:19:33 (8 years ago)
Author:
rakshasa
Message:

Throttle working, but needs fine-tuning and an API.

Fixed some incompatiblities with BSD..

Location:
trunk/libtorrent
Files:
25 modified

Legend:

Unmodified
Added
Removed
  • trunk/libtorrent/ChangeLog

    r6 r8  
     12004-07-25    <jaris@ifi.uio.no> 
     2 
     3        * torrent: Fixed bug that made it skip sending the stop message to the tracker when quiting. 
     4 
     5        * torrent: Changed stdint.h to inttypes.h and made it easy to disable execinfo.h in client. 
     6 
     7        * torrent: Added throttle with tree structure. Bandwidth delegation needs work. 
     8 
    192004-07-20    <jaris@ifi.uio.no> 
    210 
  • trunk/libtorrent/TODO

    r5 r8  
    3333Make configure do the peer id thingie automagically 
    3434 
    35 add unroll loops optimizing(?) 
    36  
    3735Add config for how often we unchoke unknown peers vs good uploaders 
    3836 
     
    4038 
    4139fix socketBase setAsync 
     40 
     41We're counting bytes we haven't downloaded, fixme. 
     42 
     43Recursively update the up/down rates in throttle. 
  • trunk/libtorrent/client/README

    r5 r8  
    11This is the test client for libtorrent. Dog food. Note that decreasing 
    2 max peers does not yet disconnect. Most of the stuff is in KiB. 
     2max peers does not yet disconnect them. 
     3 
     4This client is just something i've been throwing togheter as i 
     5finished implementing stuff in the library. When i'm finished with the 
     6important parts of the library the API will be rewritten to something 
     7more usable. I will also do a complete rewrite of the client. 
     8 
     9If your system doesn't have "execinfo.h", uncomment "#define 
     10USE_EXECINFO" in rtorrent.cc. This will be handled by an autoconf 
     11script later. 
    312 
    413Main: 
  • trunk/libtorrent/client/display.cc

    r5 r8  
    11#include "display.h" 
    22#include <ncurses.h> 
     3 
     4int loops = 0; 
    35 
    46Display::Display() { 
     
    7476  } 
    7577 
    76   mvprintw(maxY - 1, 0, "Port: %i Handshakes: %i", 
     78  mvprintw(maxY - 1, 0, "Port: %i Handshakes: %i Loops: %i", 
    7779           (int)torrent::get(torrent::LISTEN_PORT), 
    78            (int)torrent::get(torrent::HANDSHAKES_TOTAL)); 
     80           (int)torrent::get(torrent::HANDSHAKES_TOTAL), 
     81           loops); 
    7982 
    8083  refresh(); 
  • trunk/libtorrent/client/display.h

    r5 r8  
    33 
    44#include <torrent/torrent.h> 
     5 
     6extern int loops; 
    57 
    68class Display { 
  • trunk/libtorrent/client/rtorrent.cc

    r5 r8  
    22#include <fstream> 
    33#include <signal.h> 
    4 #include <execinfo.h> 
    54#include <ncurses.h> 
    6 #include <sys/select.h> 
    75#include <torrent/torrent.h> 
    86#include <torrent/exceptions.h> 
    97 
     8#include <unistd.h> 
     9//#include <sys/select.h> 
     10 
    1011#include "display.h" 
    1112#include "download.h" 
     13 
     14// Uncomment this if your system doesn't have execinfo.h 
     15#define USE_EXECINFO 
     16 
     17#ifdef USE_EXECINFO 
     18#include <execinfo.h> 
     19#endif 
    1220 
    1321std::list<std::string> log_entries; 
     
    3139  switch (signum) { 
    3240  case SIGINT: 
    33     std::cout << "Shuting down" << std::endl; 
     41    if (shutdown) { 
     42      torrent::cleanup(); 
     43      exit(0); 
     44    } 
    3445 
    3546    shutdown = true; 
     
    4657    called = true; 
    4758 
     59    std::cout << "Signal SEGFAULT recived, dumping stack:" << std::endl; 
     60 
     61#ifdef USE_EXECINFO 
    4862    // Print the stack and exit. 
    4963    stackSize = backtrace(stackPtrs, 50); 
     
    5468    display = NULL; 
    5569 
    56     std::cout << "Signal SEGFAULT recived, dumping stack:" << std::endl; 
    57  
    5870    for (int i = 0; i < stackSize; ++i) 
    5971      std::cout << i << ' ' << stackStrings[i] << std::endl; 
     72#endif 
    6073 
    6174    exit(-1); 
     
    7184  struct timeval timeout; 
    7285 
     86  display = new Display(); 
     87 
    7388  signal(SIGINT, signal_handler); 
    7489  signal(SIGSEGV, signal_handler); 
     
    7994  torrent::DList::const_iterator curDownload = torrent::downloads().end(); 
    8095 
    81   display = new Display(); 
    8296  Download download(curDownload); 
    8397 
     
    100114  int maxY, maxX; 
    101115 
    102   while (!shutdown) { 
     116  while (!shutdown || !torrent::get(torrent::SHUTDOWN_DONE)) { 
     117    loops++; 
     118 
    103119    if (lastDraw + 1000000 < torrent::get(torrent::TIME_CURRENT)) { 
    104120      lastDraw = torrent::get(torrent::TIME_CURRENT); 
  • trunk/libtorrent/torrent/download.cc

    r5 r8  
    132132          (*itr)->lastChoked() + state().settings().chokeGracePeriod < Timer::cache() && 
    133133           
    134           (g = (*itr)->down().c_rate().rate() * 16 + (*itr)->up().c_rate().rate()) <= f) { 
     134          (g = (*itr)->throttle().down().rate() * 16 + (*itr)->throttle().up().rate()) <= f) { 
    135135        f = g; 
    136136        p1 = *itr; 
     
    149149          (*itr)->down().c_interested() && 
    150150           
    151           (g = (*itr)->down().c_rate().rate()) >= f) { 
     151          (g = (*itr)->throttle().down().rate()) >= f) { 
    152152        f = g; 
    153153        p2 = *itr; 
  • trunk/libtorrent/torrent/download_state.cc

    r5 r8  
    77#include "peer_connection.h" 
    88#include "peer_handshake.h" 
     9#include "throttle_control.h" 
    910#include <algo/algo.h> 
    1011 
     
    2526 
    2627  m_files.closeAll(); 
    27 } 
    28  
    29 void DownloadState::removeConnection(PeerConnection* p) { 
    30   Connections::iterator itr = std::find(m_connections.begin(), m_connections.end(), p); 
    31  
    32   if (itr == m_connections.end()) 
    33     throw internal_error("Tried to remove peer connection from download that doesn't exist"); 
    34  
    35   delete *itr; 
    36   m_connections.erase(itr); 
    37  
    38   // TODO: Remove this when we're stable 
    39   if (std::find(m_connections.begin(), m_connections.end(), p) != m_connections.end()) 
    40     throw internal_error("Duplicate PeerConnections in Download"); 
    41  
    42   chokeBalance(); 
    43   connectPeers(); 
    4428} 
    4529 
     
    7559  // TODO: Optimize, do a single pass with a 's' sized list of (un)chokings. 
    7660  if (s > 0) { 
    77 //     while (s && itr != m_connections.end()) { 
    78 //       if ( 
    79  
    80     m_connections.sort(gt(call_member(call_member(&PeerConnection::down), 
    81                                       &PeerConnection::Sub::c_rate), 
    82                           call_member(call_member(&PeerConnection::down), 
    83                                       &PeerConnection::Sub::c_rate))); 
     61    m_connections.sort(gt(call_member(call_member(&PeerConnection::throttle), 
     62                                      &Throttle::down), 
     63                          call_member(call_member(&PeerConnection::throttle), 
     64                                      &Throttle::down))); 
    8465 
    8566    // unchoke peers. 
     
    9778    // Sort so we choke slow uploaders first. 
    9879    // TODO: Should we sort by unchoked too? 
    99     m_connections.sort(lt(call_member(call_member(&PeerConnection::down), 
    100                                       &PeerConnection::Sub::c_rate), 
    101                           call_member(call_member(&PeerConnection::down), 
    102                                       &PeerConnection::Sub::c_rate))); 
     80    m_connections.sort(lt(call_member(call_member(&PeerConnection::throttle), 
     81                                      &Throttle::down), 
     82                          call_member(call_member(&PeerConnection::throttle), 
     83                                      &Throttle::down))); 
    10384 
    10485    for (Connections::iterator itr = m_connections.begin(); 
     
    156137 
    157138  c->set(fd, p, this); 
     139 
     140  c->throttle().set_parent(&ThrottleControl::global().root()); 
     141  c->throttle().set_settings(ThrottleControl::global().settings(ThrottleControl::SETTINGS_PEER)); 
     142  c->throttle().set_socket(c); 
     143 
    158144  m_connections.push_back(c); 
    159145 
     
    162148  if (itr != m_availablePeers.end()) 
    163149    m_availablePeers.erase(itr); 
     150} 
     151 
     152void DownloadState::removeConnection(PeerConnection* p) { 
     153  Connections::iterator itr = std::find(m_connections.begin(), m_connections.end(), p); 
     154 
     155  if (itr == m_connections.end()) 
     156    throw internal_error("Tried to remove peer connection from download that doesn't exist"); 
     157 
     158  delete *itr; 
     159  m_connections.erase(itr); 
     160 
     161  // TODO: Remove this when we're stable 
     162  if (std::find(m_connections.begin(), m_connections.end(), p) != m_connections.end()) 
     163    throw internal_error("Duplicate PeerConnections in Download"); 
     164 
     165  chokeBalance(); 
     166  connectPeers(); 
    164167} 
    165168 
  • trunk/libtorrent/torrent/general.h

    r2 r8  
    33 
    44#include <string> 
    5 #include <stdint.h> 
    65#include <vector> 
    76 
  • trunk/libtorrent/torrent/peer_connection.cc

    r7 r8  
    269269    s = readChunk(); 
    270270 
    271     m_down.rate.add(m_down.pos - previous); 
     271    m_throttle.down().add(m_down.pos - previous); 
    272272    m_download->rateDown().add(m_down.pos - previous); 
    273273     
     
    304304                m_down.pos); 
    305305 
    306     m_down.rate.add(m_down.pos - previous); 
     306    m_throttle.down().add(m_down.pos - previous); 
    307307 
    308308    if (!s) 
     
    342342void PeerConnection::write() { 
    343343  bool s; 
    344   int previous; 
     344  int previous, maxBytes; 
    345345 
    346346  m_lastMsg = Timer::cache(); 
     
    410410 
    411411    previous = m_up.pos; 
    412     s = writeChunk(); 
    413  
    414     m_up.rate.add(m_up.pos - previous); 
     412    maxBytes = m_throttle.left(); 
     413     
     414    if (maxBytes == 0) { 
     415      removeWrite(); 
     416      return; 
     417    } 
     418 
     419    if (maxBytes < 0) 
     420      throw internal_error("PeerConnection::write() got maxBytes <= 0"); 
     421 
     422    s = writeChunk(maxBytes); 
     423 
     424    m_throttle.up().add(m_up.pos - previous); 
     425    m_throttle.spent(m_up.pos - previous); 
     426 
    415427    m_download->rateUp().add(m_up.pos - previous); 
    416428 
     
    513525      m_up.list.push_back(Piece(index, offset, length)); 
    514526      insertWrite(); 
     527 
     528      m_throttle.activate(); 
    515529 
    516530    } else if (rItr != m_up.list.end()) { 
     
    554568    m_sendChoked = false; 
    555569 
     570    if (m_up.choked) { 
     571      // Clear the request queue and mmaped chunk. 
     572      m_up.list.clear(); 
     573      m_up.data = Chunk(); 
     574 
     575      m_throttle.idle(); 
     576    } 
     577 
    556578    if ((Timer::cache() - m_lastChoked).seconds() < 10) { 
    557579      // Wait with the choke message. 
     
    564586       
    565587      m_lastChoked = Timer::cache(); 
    566        
    567       if (m_up.choked) { 
    568         // Clear the request queue and mmaped chunk. 
    569         m_up.list.clear(); 
    570         m_up.data = Chunk(); 
    571       } 
    572588    } 
    573589  } 
  • trunk/libtorrent/torrent/peer_connection.h

    r7 r8  
    99#include "piece.h" 
    1010#include "rate.h" 
     11#include "throttle.h" 
    1112 
    1213#include <vector> 
     
    7071  Sub& down() { return m_down; } 
    7172 
     73  Throttle& throttle() { return m_throttle; } 
     74 
    7275  virtual void read(); 
    7376  virtual void write(); 
     
    8689  }; 
    8790 
    88   bool writeChunk(); 
     91  bool writeChunk(int maxBytes); 
    8992  bool readChunk(); 
    9093 
     
    119122  Sub m_up; 
    120123  Sub m_down; 
     124 
     125  Throttle m_throttle; 
    121126}; 
    122127 
  • trunk/libtorrent/torrent/peer_connection_extra.cc

    r7 r8  
    5252} 
    5353 
    54 bool PeerConnection::writeChunk() { 
     54bool PeerConnection::writeChunk(int maxBytes) { 
    5555  Chunk::Part& part = m_up.data.get(m_up.list.front().offset() + m_up.pos); 
    5656 
     57  // Length between piece start and the end of the current part of the piece. 
     58  unsigned int length = std::min(part.first + part.second.length() - m_up.list.front().offset(), 
     59                                 m_up.list.front().length()); 
     60 
    5761  // TODO: Make this a while loop so we spit out as much of the piece as we can this work cycle. 
    58   if (!writeBuf(part.second.data() + m_up.list.front().offset() + m_up.pos - part.first, 
    59                 std::min(part.first + part.second.length() - m_up.list.front().offset(), 
    60                          m_up.list.front().length()), 
    61                 m_up.pos)) 
    62     return false; 
     62  writeBuf(part.second.data() + m_up.list.front().offset() + m_up.pos - part.first, 
     63           std::min(length, m_up.pos + maxBytes), 
     64           m_up.pos); 
    6365 
    6466  return m_up.pos == m_up.list.front().length(); 
  • trunk/libtorrent/torrent/peer_connection_sub.h

    r2 r8  
    1717  bool c_interested() const { return interested; } 
    1818 
    19   Rate& c_rate() { return rate; } 
    20  
    2119  PieceList& c_list() { return list; } 
    2220 
     
    3533  Chunk data; 
    3634  PieceList list; 
    37  
    38   Rate rate; 
    3935}; 
  • trunk/libtorrent/torrent/settings.cc

    r7 r8  
    2929 
    3030int ThrottleSettings::minPeriod = 500000; 
    31 int ThrottleSettings::wakeupPoint = 512; 
     31int ThrottleSettings::wakeupPoint = 2048; 
    3232int ThrottleSettings::minChunk = 512; 
    3333 
    3434ThrottleSettings::ThrottleSettings() : 
    35   unlimited(true), 
    36   constantRate(0) 
     35  constantRate(-1) 
    3736{} 
    3837 
  • trunk/libtorrent/torrent/settings.h

    r7 r8  
    4242  ThrottleSettings(); 
    4343 
    44   bool unlimited; 
    45  
    4644  int constantRate; 
    4745 
  • trunk/libtorrent/torrent/socket_base.cc

    r6 r8  
    77#include <arpa/inet.h> 
    88#include <netinet/ip.h> 
    9 #include <errno.h> 
    109#include <unistd.h> 
    1110#include <sstream> 
    1211#include <iostream> 
     12#include <cerrno> 
    1313#include <cstring> 
    1414 
     
    6767void SocketBase::setSocketAsync(int fd) { 
    6868  // Set Reuseaddr. 
    69   int opt = 1; 
     69  //int opt = 1; 
    7070 
    7171  // TODO: this doesn't belong here 
    72   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) 
    73     throw local_error("Error setting socket to SO_REUSEADDR"); 
     72  //if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) 
     73  //  throw local_error("Error setting socket to SO_REUSEADDR"); 
    7474 
    7575  // Set async. 
  • trunk/libtorrent/torrent/storage.h

    r2 r8  
    55#include <vector> 
    66#include <string> 
    7 #include <stdint.h> 
     7#include <inttypes.h> 
    88#include <sys/stat.h> 
    99 
  • trunk/libtorrent/torrent/throttle.cc

    r7 r8  
    77#include "socket_base.h" 
    88#include "throttle.h" 
     9#include <numeric> 
    910#include <algo/algo.h> 
    1011 
     
    2223 
    2324Throttle::~Throttle() { 
    24   idle(); 
     25  set_parent(NULL); 
    2526 
    2627  while (!m_active.empty()) 
    27     m_active.front()->idle(); 
     28    m_active.front()->set_parent(NULL); 
    2829} 
    2930 
    3031// Include in the calculation when parent delegates bandwidth. 
     32 
     33// TODO: active should allocate a resonable amount of bytes for immidiate download. 
     34// We can't do that in active, as it will be called regulary. 
    3135void Throttle::activate() { 
    3236  if (m_parent == NULL || m_activeItr != m_parent->m_active.end()) 
     
    4650   
    4751  m_activeItr = m_parent->m_active.end(); 
     52 
     53  m_left = 0; 
     54} 
     55 
     56int Throttle::left() { 
     57  if (m_left == UNLIMITED) 
     58    return std::numeric_limits<int>::max() / 2; 
     59 
     60  // TODO: Give chunks. 
     61  return m_left; 
    4862} 
    4963 
    5064void Throttle::spent(unsigned int bytes) { 
    51   if (m_left < 0) 
     65  if (m_left == UNLIMITED) 
    5266    return; 
    5367 
     
    6276void Throttle::update(float period, int bytes) { 
    6377  // Find out how much we are allowed. Int max if unlimited. 
    64   if (m_settings->unlimited) 
     78  if (m_settings->constantRate == UNLIMITED) 
    6579    m_left = bytes; 
    6680 
    6781  else 
    68     m_left = std::min<unsigned int>(bytes, 
    69                                     // TODO: Adjust quickly if we are behind 
    70                                     (unsigned int)(m_settings->constantRate * period)); 
     82    m_left = std::min((unsigned int)bytes, 
     83                      // TODO: Adjust quickly if we are behind 
     84                      (unsigned int)(m_settings->constantRate * period)); 
    7185 
    7286  // Not needed unless i fscked up something here. 
     
    8195 
    8296  // Divide the bandwidth amongst children if present. 
    83   for (Children::iterator itr = m_active.begin(); ++itr != m_active.end(); ++itr) { 
     97  for (Children::iterator itr = m_active.begin(); itr != m_active.end(); ++itr) { 
    8498    (*itr)->update(period, 
    8599                   m_left == UNLIMITED ? UNLIMITED : m_left / m_activeSize); 
     
    89103void Throttle::set_parent(Throttle* parent) { 
    90104  if (m_parent) { 
     105    idle(); 
     106 
    91107    m_parent->m_children.erase(m_childrenItr); 
    92108    m_parent->m_childrenSize--; 
     
    96112 
    97113  if (parent) { 
     114    m_parent->m_childrenSize++; 
     115 
    98116    m_childrenItr = m_parent->m_children.insert(m_parent->m_children.end(), this); 
    99     m_parent->m_childrenSize++; 
     117    m_activeItr = m_parent->m_active.end(); 
    100118  } 
    101119} 
     
    105123} 
    106124 
     125void Throttle::set_socket(SocketBase* socket) { 
     126  m_socket = socket; 
    107127} 
     128 
     129} 
  • trunk/libtorrent/torrent/throttle.h

    r7 r8  
    2929  Rate& down() { return m_down; } 
    3030   
    31   int left() { return m_left; } 
     31  int left(); 
    3232   
    3333  void spent(unsigned int bytes); 
  • trunk/libtorrent/torrent/throttle_control.cc

    r7 r8  
    33#endif 
    44 
     5#include "exceptions.h" 
    56#include "throttle_control.h" 
    67 
    78namespace torrent { 
    89 
     10ThrottleControl ThrottleControl::m_global; 
     11 
    912ThrottleControl::ThrottleControl() : 
    10   m_settings(1) { 
     13  m_settings(2) { 
    1114 
    1215  m_root.set_settings(&m_settings[SETTINGS_ROOT]); 
    1316 
    14   m_settings[SETTINGS_ROOT].unlimited = false; 
    15   m_settings[SETTINGS_ROOT].constantRate = 5000; 
     17  m_settings[SETTINGS_ROOT].constantRate = Throttle::UNLIMITED; 
     18 
     19  m_settings[SETTINGS_PEER].constantRate = Throttle::UNLIMITED; 
    1620} 
    1721 
    1822void ThrottleControl::service(int type) { 
    19   m_root.update(ThrottleSettings::minPeriod, Throttle::UNLIMITED); 
     23  m_root.update(ThrottleSettings::minPeriod / 1000000.0f, Throttle::UNLIMITED); 
     24 
     25  // TODO: Remove this later 
     26  if (inService(0)) 
     27    throw internal_error("Duplicate ThrottleService in service"); 
    2028 
    2129  // TODO: we lose some time, adjust. 
  • trunk/libtorrent/torrent/throttle_control.h

    r7 r8  
    1212 public: 
    1313  typedef enum { 
    14     SETTINGS_ROOT 
     14    SETTINGS_ROOT, 
     15    SETTINGS_PEER 
    1516  } SettingsType; 
    1617 
     
    2526  void service(int type); 
    2627 
     28  static ThrottleControl& global() { return m_global; } 
     29 
    2730 private: 
     31  static ThrottleControl m_global; 
     32 
    2833  Throttle m_root; 
    2934 
  • trunk/libtorrent/torrent/timer.h

    r2 r8  
    22#define LIBTORRENT_TIMER_H 
    33 
    4 #include <stdint.h> 
     4#include <inttypes.h> 
    55#include <sys/time.h> 
    66 
  • trunk/libtorrent/torrent/torrent.cc

    r7 r8  
    2727std::list<std::string> caughtExceptions; 
    2828 
    29 ThrottleControl throttleControl; 
    30  
    3129struct add_socket { 
    3230  add_socket(fd_set* s) : fd(0), fds(s) {} 
     
    6361  Listen::open(beginPort, endPort); 
    6462 
    65   throttleControl.insertService(Timer::current(), 0); 
     63  ThrottleControl::global().insertService(Timer::current(), 0); 
    6664} 
    6765 
     
    7977  Listen::close(); 
    8078 
    81   throttleControl.removeService(); 
     79  ThrottleControl::global().removeService(); 
    8280 
    8381  for_each<true>(Download::downloads().begin(), Download::downloads().end(), 
     
    208206  case SHUTDOWN_DONE: 
    209207    return std::find_if(Download::downloads().begin(), Download::downloads().end(), 
    210                         call_member(&Download::isStopped)) 
     208                        bool_not(call_member(&Download::isStopped))) 
    211209      == Download::downloads().end(); 
    212210 
     
    262260 
    263261int64_t get(DList::const_iterator d, DValue t) { 
    264 //   if (d == Download::downloads().end()) 
    265 //     throw internal_error("torrent::get(DList::const_iterator, DValue) called on an invalid iterator"); 
    266262  Timer::update(); 
    267263  uint64_t a; 
     
    380376 
    381377  case PEER_RATE_DOWN: 
    382     return (*p)->down().c_rate().rate(true); 
     378    return (*p)->throttle().down().rate(true); 
    383379 
    384380  case PEER_RATE_UP: 
    385     return (*p)->up().c_rate().rate(true); 
     381    return (*p)->throttle().up().rate(true); 
    386382 
    387383  case PEER_PORT: 
  • trunk/libtorrent/torrent/torrent.h

    r2 r8  
    44#include <list> 
    55#include <string> 
    6 #include <stdint.h> 
     6#include <inttypes.h> 
    77#include <sys/types.h> 
    88 
  • trunk/libtorrent/torrent/tracker_query.h

    r2 r8  
    44#include <map> 
    55#include <iosfwd> 
    6 #include <stdint.h> 
     6#include <inttypes.h> 
    77#include "peer.h" 
    88#include "socket_base.h"