📄 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_errno(0), 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; m_errno = 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; } // Need to do increment later if we're going to support resume // hashing a quick hashed torrent. ChunkHandle handle = m_chunkList->get(m_position++, false); if (quick) { // We're not actually interested in doing any hashing, so just // skip what we know is not possible to hash. // // If the file does not exist then no valid error number is // returned. if (m_outstanding != 0) throw internal_error("HashTorrent::queue() quick hashing but m_outstanding != 0."); if (handle.is_valid()) return m_chunkList->release(&handle); if (handle.error_number().is_valid()) return; continue; } else { // 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()) { if (handle.is_valid()) throw internal_error("HashTorrent::queue() error, but handle.is_valid()."); // We wait for all the outstanding chunks to be checked before // borking completely, else low-memory devices might not be able // to finish the hash check. if (m_outstanding != 0) { m_position--; return; } // The rest of the outstanding chunks get ignored by // DownloadWrapper::receive_hash_done. Obsolete. clear(); m_errno = handle.error_number().value(); rak::priority_queue_erase(&taskScheduler, &m_delayChecked); rak::priority_queue_insert(&taskScheduler, &m_delayChecked, cachedTime); return; } // Missing file, skip the hash check. if (!handle.is_valid()) continue; 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 + -