📄 hash_torrent.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 "torrent/exceptions.h"#include "data/chunk_list.h"#include "hash_torrent.h"#include "hash_queue.h"namespace torrent {HashTorrent::HashTorrent(ChunkList* c) : m_position(0), m_outstanding(-1), m_chunkList(c), m_queue(NULL) {}boolHashTorrent::start(bool tryQuick) { if (m_position == m_chunkList->size()) return true; if (!is_checking()) { if (m_position > 0 || m_queue == NULL || m_chunkList == NULL || m_chunkList->empty()) throw internal_error("HashTorrent::start() call failed."); m_outstanding = 0; } // This doesn't really handle paused hashing properly... Do we set // m_outstanding to -1 when stopping? queue(tryQuick); return m_position == m_chunkList->size();}voidHashTorrent::clear() { m_outstanding = -1; m_position = 0;}boolHashTorrent::is_checked() { // When closed the chunk list is empty. Position can be equal to // chunk list for a short while as we have outstanding chunks, so // check the latter. return !m_chunkList->empty() && m_position == m_chunkList->size() && m_outstanding == -1;}// After all chunks are checked it won't show as is_checked until// after this function is called. This allows for the hash done signal// to be delayed.voidHashTorrent::confirm_checked() { if (m_outstanding != 0) throw internal_error("HashTorrent::confirm_checked() m_outstanding != 0."); m_outstanding = -1;}voidHashTorrent::receive_chunkdone() { if (m_outstanding == -1) throw internal_error("HashTorrent::receive_chunkdone() m_outstanding < 0."); // m_signalChunk will always point to // DownloadMain::receive_hash_done, so it will take care of cleanup. // // Make sure we call chunkdone before torrentDone has a chance to // trigger.// m_slotChunkDone(handle, hash); m_outstanding--; // Don't add more when we've stopped. Use some better condition than // m_outstanding. This code is ugly... needs a refactoring, a // seperate flag for active and allow pause or clearing the state. if (m_outstanding >= 0) queue(false);}voidHashTorrent::queue(bool quick) { if (!is_checking()) throw internal_error("HashTorrent::queue() called but it's not running."); while (m_position < m_chunkList->size()) { if (m_outstanding >= 30) return; // Not very efficient, but this is seldomly done. Ranges::iterator itr = m_ranges.find(m_position); if (itr == m_ranges.end()) { m_position = m_chunkList->size(); break; } else if (m_position < itr->first) { m_position = itr->first; } ChunkHandle handle = m_chunkList->get(m_position++, false); if (!handle.is_valid()) continue; // We're not actually interested in doing any hashing, nor should // be trigger any storage error. if (quick) return m_chunkList->release(&handle); // If the error number is not valid, then we've just encountered a // file that hasn't be created/resized. Which means we ignore it // when doing initial hashing. if (handle.error_number().is_valid()) { // The rest of the outstanding chunks get ignored by // DownloadWrapper::receive_hash_done. clear(); m_slotStorageError("Hash checker was unable to map chunk: " + std::string(handle.error_number().c_str())); rak::priority_queue_erase(&taskScheduler, &m_delayChecked); rak::priority_queue_insert(&taskScheduler, &m_delayChecked, cachedTime); return; } m_slotCheckChunk(handle); m_outstanding++; } if (m_outstanding == 0) { // Erase the scheduled item just to make sure that if hashing is // started again during the delay it won't cause an exception. rak::priority_queue_erase(&taskScheduler, &m_delayChecked); rak::priority_queue_insert(&taskScheduler, &m_delayChecked, cachedTime); }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -