⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 request_list.cc

📁 一个BT下载库. 支持DHT. 采用底层的网络通讯提速.
💻 CC
字号:
// libTorrent - BitTorrent library// Copyright (C) 2005-2006, Jari Sundell//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA//// In addition, as a special exception, the copyright holders give// permission to link the code of portions of this program with the// OpenSSL library under certain conditions as described in each// individual source file, and distribute linked combinations// including the two.//// You must obey the GNU General Public License in all respects for// all of the code used other than OpenSSL.  If you modify file(s)// with this exception, you may extend this exception to your version// of the file(s), but you are not obligated to do so.  If you do not// wish to do so, delete this exception statement from your version.// If you delete this exception statement from all source files in the// program, then also delete it here.//// Contact:  Jari Sundell <jaris@ifi.uio.no>////           Skomakerveien 33//           3185 Skoppum, NORWAY#include "config.h"#include <functional>#include <inttypes.h>#include <rak/functional.h>#include "torrent/block.h"#include "torrent/block_list.h"#include "torrent/exceptions.h"#include "download/delegator.h"#include "peer_chunks.h"#include "request_list.h"namespace torrent {// It is assumed invalid transfers have been removed.struct request_list_same_piece {  request_list_same_piece(const Piece& p) : m_piece(p) {}  bool operator () (const BlockTransfer* d) {    return      m_piece.index() == d->const_block()->piece().index() &&      m_piece.offset() == d->const_block()->piece().offset();  }  Piece m_piece;};const Piece*RequestList::delegate() {  BlockTransfer* r = m_delegator->delegate(m_peerChunks, m_affinity);  if (r) {    m_affinity = r->block()->index();    m_queued.push_back(r);    return &r->block()->piece();  } else {    return NULL;  }}// Replace m_canceled with m_queued and set them to stalled.voidRequestList::cancel() {  std::for_each(m_canceled.begin(), m_canceled.end(), std::ptr_fun(&Block::release));  m_canceled.clear();  std::for_each(m_queued.begin(), m_queued.end(), std::ptr_fun(&Block::stalled));  m_canceled.swap(m_queued);}voidRequestList::stall() {  if (m_transfer != NULL)    Block::stalled(m_transfer);  std::for_each(m_queued.begin(), m_queued.end(), std::ptr_fun(&Block::stalled));}voidRequestList::clear() {  if (is_downloading())    skipped();  std::for_each(m_queued.begin(), m_queued.end(), std::ptr_fun(&Block::release));  m_queued.clear();  std::for_each(m_canceled.begin(), m_canceled.end(), std::ptr_fun(&Block::release));  m_canceled.clear();}boolRequestList::downloading(const Piece& piece) {  if (m_transfer != NULL)    throw internal_error("RequestList::downloading(...) m_transfer != NULL.");  // Consider doing this on cancel_range.  remove_invalid();  ReserveeList::iterator itr = std::find_if(m_queued.begin(), m_queued.end(), request_list_same_piece(piece));  if (itr == m_queued.end()) {    itr = std::find_if(m_canceled.begin(), m_canceled.end(), request_list_same_piece(piece));    if (itr == m_canceled.end()) {      // Create a dummy BlockTransfer object to hold the piece      // information.      m_transfer = new BlockTransfer();      m_transfer->create_dummy(m_peerChunks->peer_info(), piece);      return false;    }    // Remove all up to and including itr.    m_transfer = *itr;    m_canceled.erase(itr);  } else {    m_transfer = *itr;    cancel_range(itr);    m_queued.pop_front();  }    // We received an invalid piece length, propably zero length due to  // the peer not being able to transfer the requested piece.  //  // We need to replace the current BlockTransfer so Block can keep  // the unmodified BlockTransfer.  if (piece.length() != m_transfer->piece().length()) {    if (piece.length() != 0)      throw network_error("Peer sent a piece with wrong, non-zero, length.");    Block::release(m_transfer);    m_transfer = new BlockTransfer();    m_transfer->create_dummy(m_peerChunks->peer_info(), piece);    return false;  }  // Check if piece isn't wanted anymore. Do this after the length  // check to ensure we return a correct BlockTransfer.  if (!m_transfer->is_valid())    return false;  m_transfer->block()->transfering(m_transfer);  return true;}// Must clear the downloading piece.voidRequestList::finished() {  if (!is_downloading())    throw internal_error("RequestList::finished() called but no transfer is in progress.");  if (!m_transfer->is_valid())    throw internal_error("RequestList::finished() called but transfer is invalid.");  BlockTransfer* transfer = m_transfer;  m_transfer = NULL;  m_delegator->transfer_list()->finished(transfer);}voidRequestList::skipped() {  if (!is_downloading())    throw internal_error("RequestList::skip() called but no transfer is in progress.");  Block::release(m_transfer);  m_transfer = NULL;}// Data downloaded by this non-leading transfer does not match what we// already have.voidRequestList::transfer_dissimilar() {  if (!is_downloading())    throw internal_error("RequestList::transfer_dissimilar() called but no transfer is in progress.");  BlockTransfer* dummy = new BlockTransfer();  dummy->create_dummy(m_peerChunks->peer_info(), m_transfer->piece());  dummy->set_position(m_transfer->position());  m_transfer->block()->transfer_dissimilar(m_transfer);  m_transfer = dummy;}struct equals_reservee : public std::binary_function<BlockTransfer*, uint32_t, bool> {  bool operator () (BlockTransfer* r, uint32_t index) const {    return r->is_valid() && index == r->block()->index();  }};boolRequestList::is_interested_in_active() const {  for (TransferList::const_iterator itr = m_delegator->transfer_list()->begin(), last = m_delegator->transfer_list()->end(); itr != last; ++itr)    if (m_peerChunks->bitfield()->get((*itr)->index()))      return true;  return false;}boolRequestList::has_index(uint32_t index) {  return std::find_if(m_queued.begin(), m_queued.end(), std::bind2nd(equals_reservee(), index)) != m_queued.end();}voidRequestList::cancel_range(ReserveeList::iterator end) {  while (m_queued.begin() != end) {    Block::stalled(m_queued.front());        m_canceled.push_back(m_queued.front());    m_queued.pop_front();  }}uint32_tRequestList::remove_invalid() {  uint32_t count = 0;  ReserveeList::iterator itr;  // Could be more efficient, but rarely do we find any.  while ((itr = std::find_if(m_queued.begin(), m_queued.end(),  std::not1(std::mem_fun(&BlockTransfer::is_valid)))) != m_queued.end()) {    count++;    Block::release(*itr);    m_queued.erase(itr);  }  // Don't count m_canceled that are invalid.  while ((itr = std::find_if(m_canceled.begin(), m_canceled.end(), std::not1(std::mem_fun(&BlockTransfer::is_valid)))) != m_canceled.end()) {    Block::release(*itr);    m_canceled.erase(itr);  }  return count;}uint32_tRequestList::calculate_pipe_size(uint32_t rate) {  // Change into KB.  rate /= 1024;  // Request enough to have enough for 16 seconds at fast rates.  if (!m_delegator->get_aggressive()) {    uint32_t queueKB = std::min(rate * 30, (uint32_t)16 << 10);      return (queueKB / (Delegator::block_size / 1024)) + 2;  } else {    uint32_t queueKB = std::min(rate * 16, (uint32_t)16 << 10);      return (queueKB / (Delegator::block_size / 1024)) + 1;  }}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -