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

📄 transfer_list.cc

📁 linux federo 6下的bt软件的类库文件
💻 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 <algorithm>#include <functional>#include <set>#include <rak/functional.h>#include "data/chunk.h"#include "peer/peer_info.h"#include "block_failed.h"#include "block_transfer.h"#include "block_list.h"#include "exceptions.h"#include "piece.h"#include "transfer_list.h"namespace torrent {TransferList::iteratorTransferList::find(uint32_t index) {  return std::find_if(begin(), end(), rak::equal(index, std::mem_fun(&BlockList::index)));}TransferList::const_iteratorTransferList::find(uint32_t index) const {  return std::find_if(begin(), end(), rak::equal(index, std::mem_fun(&BlockList::index)));}voidTransferList::clear() {  std::for_each(begin(), end(), rak::on(std::mem_fun(&BlockList::index), m_slotCanceled));  std::for_each(begin(), end(), rak::call_delete<BlockList>());  base_type::clear();}voidTransferList::save_clear() {	for (iterator i = begin();i!=end();){		if(! (*i)->is_all_finished()){				m_signalCanceled( (*i)->index());				i = erase(i);		}		else{			i++;		}	}}TransferList::iteratorTransferList::insert(const Piece& piece, uint32_t blockSize) {  if (find(piece.index()) != end())    throw internal_error("Delegator::new_chunk(...) received an index that is already delegated.");  BlockList* blockList = new BlockList(piece, blockSize);    m_slotQueued(piece.index());  return base_type::insert(end(), blockList);}TransferList::iteratorTransferList::erase(iterator itr) {  if (itr == end())    throw internal_error("TransferList::erase(...) itr == m_chunks.end().");  delete *itr;  return base_type::erase(itr);}voidTransferList::finished(BlockTransfer* transfer) {  if (!transfer->is_valid())    throw internal_error("TransferList::finished(...) got transfer with wrong state.");  uint32_t index = transfer->block()->index();  // Marks the transfer as complete and erases it.  if (transfer->block()->completed(transfer))    m_slotCompleted(index);}voidTransferList::hash_succeded(uint32_t index) {  iterator blockListItr = find(index);  if ((Block::size_type)std::count_if((*blockListItr)->begin(), (*blockListItr)->end(), std::mem_fun_ref(&Block::is_finished)) != (*blockListItr)->size())    throw internal_error("TransferList::hash_succeded(...) Finished blocks does not match size.");  if ((*blockListItr)->failed() != 0)    mark_failed_peers(*blockListItr);  erase(blockListItr);}struct transfer_list_compare_data {  transfer_list_compare_data(Chunk* chunk, const Piece& p) : m_chunk(chunk), m_piece(p) { }  bool operator () (const BlockFailed::reference failed) {    return m_chunk->compare_buffer(failed.first, m_piece.offset(), m_piece.length());  }  Chunk* m_chunk;  Piece  m_piece;};voidTransferList::hash_failed(uint32_t index, Chunk* chunk) {  iterator blockListItr = find(index);  if (blockListItr == end())    throw internal_error("TransferList::hash_failed(...) Could not find index.");  if ((Block::size_type)std::count_if((*blockListItr)->begin(), (*blockListItr)->end(), std::mem_fun_ref(&Block::is_finished)) != (*blockListItr)->size())    throw internal_error("TransferList::hash_failed(...) Finished blocks does not match size.");  // Could propably also check promoted against size of the block  // list.  if ((*blockListItr)->attempt() == 0) {    unsigned int promoted = update_failed(*blockListItr, chunk);    if (promoted > 0 || promoted < (*blockListItr)->size()) {      // Retry with the most popular blocks.      (*blockListItr)->set_attempt(1);      retry_most_popular(*blockListItr, chunk);      // Also consider various other schemes, like using blocks from      // only/mainly one peer.      return;    }  }  // Should we check if there's any peers whom have sent us bad data  // before, and just clear those first?  // Re-download the blocks.  (*blockListItr)->clear_finished();  (*blockListItr)->set_attempt(0);  // Clear leaders when we want to redownload the chunk.  std::for_each((*blockListItr)->begin(), (*blockListItr)->end(), std::mem_fun_ref(&Block::failed_leader));}// update_failed(...) either increments the reference count of a// failed entry, or creates a new one if the data differs.unsigned intTransferList::update_failed(BlockList* blockList, Chunk* chunk) {  unsigned int promoted = 0;  blockList->inc_failed();  for (BlockList::iterator itr = blockList->begin(), last = blockList->end(); itr != last; ++itr) {        if (itr->failed_list() == NULL)      itr->set_failed_list(new BlockFailed());    BlockFailed::iterator failedItr = std::find_if(itr->failed_list()->begin(), itr->failed_list()->end(),                                                   transfer_list_compare_data(chunk, itr->piece()));    if (failedItr == itr->failed_list()->end()) {      // We've never encountered this data before, make a new entry.      char* buffer = new char[itr->piece().length()];      chunk->to_buffer(buffer, itr->piece().offset(), itr->piece().length());      itr->failed_list()->push_back(BlockFailed::value_type(buffer, 1));      // Count how many new data sets?    } else {      // Increment promoted when the entry's reference count becomes      // larger than others, but not if it previously was the largest.      BlockFailed::iterator maxItr = itr->failed_list()->max_element();      if (maxItr->second == failedItr->second && maxItr != --itr->failed_list()->reverse_max_element().base())        promoted++;      failedItr->second++;    }    itr->failed_list()->set_current(failedItr);    itr->leader()->set_failed_index(failedItr - itr->failed_list()->begin());  }  return promoted;}voidTransferList::mark_failed_peers(BlockList* blockList) {  std::set<PeerInfo*> badPeers;  for (BlockList::iterator itr = blockList->begin(), last = blockList->end(); itr != last; ++itr)    for (Block::transfer_list_type::const_iterator itr2 = itr->transfers()->begin(), last2 = itr->transfers()->end(); itr2 != last2; ++itr2)      if ((*itr2)->failed_index() != itr->failed_list()->current())        badPeers.insert((*itr2)->peer_info());  std::for_each(badPeers.begin(), badPeers.end(), m_slotCorrupt);}// Copy the stored data to the chunk from the failed entries with// largest reference counts.voidTransferList::retry_most_popular(BlockList* blockList, Chunk* chunk) {  for (BlockList::iterator itr = blockList->begin(), last = blockList->end(); itr != last; ++itr) {        BlockFailed::reverse_iterator failedItr = itr->failed_list()->reverse_max_element();    if (failedItr == itr->failed_list()->rend())      throw internal_error("TransferList::retry_most_popular(...) No failed list entry found.");    // The data is the same, so no need to copy.    if (failedItr == itr->failed_list()->current_reverse_iterator())      continue;    // Change the leader to the currently held buffer?    chunk->from_buffer(failedItr->first, itr->piece().offset(), itr->piece().length());    itr->failed_list()->set_current(failedItr);  }  m_slotCompleted(blockList->index());}}

⌨️ 快捷键说明

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