factor out file progress tracking from the torrent class
This commit is contained in:
parent
2d1db68ea6
commit
e2784df13c
1
Jamfile
1
Jamfile
|
@ -684,6 +684,7 @@ SOURCES =
|
||||||
performance_counters
|
performance_counters
|
||||||
resolver
|
resolver
|
||||||
session_settings
|
session_settings
|
||||||
|
file_progress
|
||||||
|
|
||||||
# -- extensions --
|
# -- extensions --
|
||||||
metadata_transfer
|
metadata_transfer
|
||||||
|
|
|
@ -166,6 +166,7 @@ nobase_include_HEADERS = \
|
||||||
aux_/session_settings.hpp \
|
aux_/session_settings.hpp \
|
||||||
aux_/session_interface.hpp \
|
aux_/session_interface.hpp \
|
||||||
aux_/time.hpp \
|
aux_/time.hpp \
|
||||||
|
aux_/file_progress.hpp \
|
||||||
\
|
\
|
||||||
extensions/lt_trackers.hpp \
|
extensions/lt_trackers.hpp \
|
||||||
extensions/metadata_transfer.hpp \
|
extensions/metadata_transfer.hpp \
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TORRENT_FILE_PROGRESS_HPP_INCLUDE
|
||||||
|
#define TORRENT_FILE_PROGRESS_HPP_INCLUDE
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
class piece_picker;
|
||||||
|
class file_storage;
|
||||||
|
class alert_manager;
|
||||||
|
class torrent_handle;
|
||||||
|
|
||||||
|
namespace aux
|
||||||
|
{
|
||||||
|
struct file_progress
|
||||||
|
{
|
||||||
|
file_progress();
|
||||||
|
|
||||||
|
void init(piece_picker const& picker
|
||||||
|
, file_storage const& fs);
|
||||||
|
|
||||||
|
void export_progress(std::vector<boost::int64_t> &fp);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void update(file_storage const& fs, int index
|
||||||
|
, alert_manager* alerts, torrent_handle const& h);
|
||||||
|
|
||||||
|
#if TORRENT_USE_INVARIANT_CHECKS
|
||||||
|
void check_invariant(file_storage const& fs) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// this vector contains the number of bytes completely
|
||||||
|
// downloaded (as in passed-hash-check) in each file.
|
||||||
|
// this lets us trigger on individual files completing
|
||||||
|
// the vector is allocated lazily, when file progress
|
||||||
|
// is first queried by the client
|
||||||
|
std::vector<boost::uint64_t> m_file_progress;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -74,6 +74,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/vector_utils.hpp"
|
#include "libtorrent/vector_utils.hpp"
|
||||||
#include "libtorrent/linked_list.hpp"
|
#include "libtorrent/linked_list.hpp"
|
||||||
#include "libtorrent/debug.hpp"
|
#include "libtorrent/debug.hpp"
|
||||||
|
#include "libtorrent/aux_/file_progress.hpp"
|
||||||
|
|
||||||
#if TORRENT_COMPLETE_TYPES_REQUIRED
|
#if TORRENT_COMPLETE_TYPES_REQUIRED
|
||||||
#include "libtorrent/peer_connection.hpp"
|
#include "libtorrent/peer_connection.hpp"
|
||||||
|
@ -99,10 +100,6 @@ namespace libtorrent
|
||||||
struct listen_socket_t;
|
struct listen_socket_t;
|
||||||
|
|
||||||
|
|
||||||
TORRENT_EXTRA_EXPORT void initialize_file_progress(
|
|
||||||
std::vector<boost::uint64_t>& file_progress
|
|
||||||
, piece_picker const& picker, file_storage const& fs);
|
|
||||||
|
|
||||||
namespace aux
|
namespace aux
|
||||||
{
|
{
|
||||||
struct piece_checker_data;
|
struct piece_checker_data;
|
||||||
|
@ -1269,12 +1266,8 @@ namespace libtorrent
|
||||||
// TODO: this wastes 5 bits per file
|
// TODO: this wastes 5 bits per file
|
||||||
std::vector<boost::uint8_t> m_file_priority;
|
std::vector<boost::uint8_t> m_file_priority;
|
||||||
|
|
||||||
// this vector contains the number of bytes completely
|
// this object is used to track download progress of individual files
|
||||||
// downloaded (as in passed-hash-check) in each file.
|
aux::file_progress m_file_progress;
|
||||||
// this lets us trigger on individual files completing
|
|
||||||
// the vector is allocated lazily, when file progress
|
|
||||||
// is first queried by the client
|
|
||||||
std::vector<boost::uint64_t> m_file_progress;
|
|
||||||
|
|
||||||
// these are the pieces we're currently
|
// these are the pieces we're currently
|
||||||
// suggesting to peers.
|
// suggesting to peers.
|
||||||
|
|
|
@ -142,6 +142,7 @@ libtorrent_rasterbar_la_SOURCES = \
|
||||||
utp_stream.cpp \
|
utp_stream.cpp \
|
||||||
web_peer_connection.cpp \
|
web_peer_connection.cpp \
|
||||||
xml_parse.cpp \
|
xml_parse.cpp \
|
||||||
|
file_progress.cpp \
|
||||||
\
|
\
|
||||||
$(KADEMLIA_SOURCES) \
|
$(KADEMLIA_SOURCES) \
|
||||||
$(ASIO_OPENSSL_SOURCES)
|
$(ASIO_OPENSSL_SOURCES)
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libtorrent/piece_picker.hpp"
|
||||||
|
#include "libtorrent/file_storage.hpp"
|
||||||
|
#include "libtorrent/alert_manager.hpp"
|
||||||
|
#include "libtorrent/aux_/file_progress.hpp"
|
||||||
|
#include "libtorrent/alert_types.hpp"
|
||||||
|
|
||||||
|
namespace libtorrent { namespace aux
|
||||||
|
{
|
||||||
|
|
||||||
|
file_progress::file_progress()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_progress::init(piece_picker const& picker, file_storage const& fs)
|
||||||
|
{
|
||||||
|
if (!m_file_progress.empty()) return;
|
||||||
|
|
||||||
|
int num_pieces = fs.num_pieces();
|
||||||
|
int num_files = fs.num_files();
|
||||||
|
|
||||||
|
m_file_progress.resize(num_files, 0);
|
||||||
|
std::fill(m_file_progress.begin(), m_file_progress.end(), 0);
|
||||||
|
|
||||||
|
// initialize the progress of each file
|
||||||
|
|
||||||
|
const int piece_size = fs.piece_length();
|
||||||
|
boost::uint64_t off = 0;
|
||||||
|
boost::uint64_t total_size = fs.total_size();
|
||||||
|
int file_index = 0;
|
||||||
|
for (int piece = 0; piece < num_pieces; ++piece, off += piece_size)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(file_index < fs.num_files());
|
||||||
|
boost::int64_t file_offset = off - fs.file_offset(file_index);
|
||||||
|
TORRENT_ASSERT(file_offset >= 0);
|
||||||
|
while (file_offset >= fs.file_size(file_index))
|
||||||
|
{
|
||||||
|
++file_index;
|
||||||
|
TORRENT_ASSERT(file_index < fs.num_files());
|
||||||
|
file_offset = off - fs.file_offset(file_index);
|
||||||
|
TORRENT_ASSERT(file_offset >= 0);
|
||||||
|
}
|
||||||
|
TORRENT_ASSERT(file_offset <= fs.file_size(file_index));
|
||||||
|
|
||||||
|
if (!picker.have_piece(piece)) continue;
|
||||||
|
|
||||||
|
int size = (std::min)(boost::uint64_t(piece_size), total_size - off);
|
||||||
|
TORRENT_ASSERT(size >= 0);
|
||||||
|
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
int add = (std::min)(boost::int64_t(size), fs.file_size(file_index) - file_offset);
|
||||||
|
TORRENT_ASSERT(add >= 0);
|
||||||
|
m_file_progress[file_index] += add;
|
||||||
|
|
||||||
|
TORRENT_ASSERT(m_file_progress[file_index]
|
||||||
|
<= fs.file_size(file_index));
|
||||||
|
|
||||||
|
size -= add;
|
||||||
|
TORRENT_ASSERT(size >= 0);
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
++file_index;
|
||||||
|
TORRENT_ASSERT(file_index < fs.num_files());
|
||||||
|
file_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_progress::export_progress(std::vector<boost::int64_t> &fp)
|
||||||
|
{
|
||||||
|
fp.resize(m_file_progress.size(), 0);
|
||||||
|
std::copy(m_file_progress.begin(), m_file_progress.end(), fp.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_progress::clear()
|
||||||
|
{
|
||||||
|
std::vector<boost::uint64_t>().swap(m_file_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the file progress now that we just completed downloading piece
|
||||||
|
// 'index'
|
||||||
|
void file_progress::update(file_storage const& fs, int index
|
||||||
|
, alert_manager* alerts, torrent_handle const& h)
|
||||||
|
{
|
||||||
|
if (m_file_progress.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int piece_size = fs.piece_length();
|
||||||
|
boost::int64_t off = boost::int64_t(index) * piece_size;
|
||||||
|
int file_index = fs.file_index_at_offset(off);
|
||||||
|
int size = fs.piece_size(index);
|
||||||
|
for (; size > 0; ++file_index)
|
||||||
|
{
|
||||||
|
boost::int64_t file_offset = off - fs.file_offset(file_index);
|
||||||
|
TORRENT_ASSERT(file_index != fs.num_files());
|
||||||
|
TORRENT_ASSERT(file_offset <= fs.file_size(file_index));
|
||||||
|
int add = (std::min)(fs.file_size(file_index) - file_offset, (boost::int64_t)size);
|
||||||
|
m_file_progress[file_index] += add;
|
||||||
|
|
||||||
|
TORRENT_ASSERT(m_file_progress[file_index]
|
||||||
|
<= fs.file_size(file_index));
|
||||||
|
|
||||||
|
// TODO: it would be nice to not depend on alert_manager here
|
||||||
|
if (m_file_progress[file_index] >= fs.file_size(file_index) && alerts)
|
||||||
|
{
|
||||||
|
if (!fs.pad_file_at(file_index))
|
||||||
|
{
|
||||||
|
if (alerts->should_post<file_completed_alert>())
|
||||||
|
{
|
||||||
|
// this file just completed, post alert
|
||||||
|
alerts->emplace_alert<file_completed_alert>(h, file_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size -= add;
|
||||||
|
off += add;
|
||||||
|
TORRENT_ASSERT(size >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TORRENT_USE_INVARIANT_CHECKS
|
||||||
|
void file_progress::check_invariant(file_storage const& fs) const
|
||||||
|
{
|
||||||
|
if (!m_file_progress.empty())
|
||||||
|
{
|
||||||
|
for (std::vector<boost::uint64_t>::const_iterator i = m_file_progress.begin()
|
||||||
|
, end(m_file_progress.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
int index = i - m_file_progress.begin();
|
||||||
|
TORRENT_ASSERT(*i <= fs.file_size(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} }
|
||||||
|
|
||||||
|
|
129
src/torrent.cpp
129
src/torrent.cpp
|
@ -93,6 +93,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/resolver_interface.hpp"
|
#include "libtorrent/resolver_interface.hpp"
|
||||||
#include "libtorrent/alloca.hpp"
|
#include "libtorrent/alloca.hpp"
|
||||||
#include "libtorrent/resolve_links.hpp"
|
#include "libtorrent/resolve_links.hpp"
|
||||||
|
#include "libtorrent/aux_/file_progress.hpp"
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
#include "libtorrent/aux_/session_impl.hpp" // for tracker_logger
|
#include "libtorrent/aux_/session_impl.hpp" // for tracker_logger
|
||||||
|
@ -803,7 +804,7 @@ namespace libtorrent
|
||||||
|
|
||||||
update_gauge();
|
update_gauge();
|
||||||
|
|
||||||
std::vector<boost::uint64_t>().swap(m_file_progress);
|
m_file_progress.clear();
|
||||||
|
|
||||||
if (m_resume_data)
|
if (m_resume_data)
|
||||||
{
|
{
|
||||||
|
@ -2560,7 +2561,7 @@ namespace libtorrent
|
||||||
|
|
||||||
// file progress is allocated lazily, the first time the client
|
// file progress is allocated lazily, the first time the client
|
||||||
// asks for it
|
// asks for it
|
||||||
std::vector<boost::uint64_t>().swap(m_file_progress);
|
m_file_progress.clear();
|
||||||
|
|
||||||
// assume that we don't have anything
|
// assume that we don't have anything
|
||||||
m_files_checked = false;
|
m_files_checked = false;
|
||||||
|
@ -4196,41 +4197,8 @@ namespace libtorrent
|
||||||
m_ses.alerts().emplace_alert<piece_finished_alert>(get_handle(), index);
|
m_ses.alerts().emplace_alert<piece_finished_alert>(get_handle(), index);
|
||||||
|
|
||||||
// update m_file_progress (if we have one)
|
// update m_file_progress (if we have one)
|
||||||
if (!m_file_progress.empty())
|
m_file_progress.update(m_torrent_file->files(), index
|
||||||
{
|
, &m_ses.alerts(), get_handle());
|
||||||
const int piece_size = m_torrent_file->piece_length();
|
|
||||||
boost::int64_t off = boost::int64_t(index) * piece_size;
|
|
||||||
int file_index = m_torrent_file->files().file_index_at_offset(off);
|
|
||||||
int size = m_torrent_file->piece_size(index);
|
|
||||||
file_storage const& fs = m_torrent_file->files();
|
|
||||||
for (; size > 0; ++file_index)
|
|
||||||
{
|
|
||||||
boost::int64_t file_offset = off - fs.file_offset(file_index);
|
|
||||||
TORRENT_ASSERT(file_index != fs.num_files());
|
|
||||||
TORRENT_ASSERT(file_offset <= fs.file_size(file_index));
|
|
||||||
int add = (std::min)(fs.file_size(file_index) - file_offset, (boost::int64_t)size);
|
|
||||||
m_file_progress[file_index] += add;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(m_file_progress[file_index]
|
|
||||||
<= m_torrent_file->files().file_size(file_index));
|
|
||||||
|
|
||||||
if (m_file_progress[file_index] >= m_torrent_file->files().file_size(file_index))
|
|
||||||
{
|
|
||||||
if (!m_torrent_file->files().pad_file_at(file_index))
|
|
||||||
{
|
|
||||||
if (m_ses.alerts().should_post<file_completed_alert>())
|
|
||||||
{
|
|
||||||
// this file just completed, post alert
|
|
||||||
m_ses.alerts().emplace_alert<file_completed_alert>(get_handle()
|
|
||||||
, file_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size -= add;
|
|
||||||
off += add;
|
|
||||||
TORRENT_ASSERT(size >= 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_time_critical_piece(index, true);
|
remove_time_critical_piece(index, true);
|
||||||
|
|
||||||
|
@ -8299,7 +8267,8 @@ namespace libtorrent
|
||||||
m_became_seed = m_ses.session_time();
|
m_became_seed = m_ses.session_time();
|
||||||
|
|
||||||
// no need for this anymore
|
// no need for this anymore
|
||||||
std::vector<boost::uint64_t>().swap(m_file_progress);
|
m_file_progress.clear();
|
||||||
|
|
||||||
if (!m_announcing) return;
|
if (!m_announcing) return;
|
||||||
|
|
||||||
time_point now = aux::time_now();
|
time_point now = aux::time_now();
|
||||||
|
@ -8824,15 +8793,7 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(block_size() > 0);
|
TORRENT_ASSERT(block_size() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_file_progress.empty())
|
m_file_progress.check_invariant(m_torrent_file->files());
|
||||||
{
|
|
||||||
for (std::vector<boost::uint64_t>::const_iterator i = m_file_progress.begin()
|
|
||||||
, end(m_file_progress.end()); i != end; ++i)
|
|
||||||
{
|
|
||||||
int index = i - m_file_progress.begin();
|
|
||||||
TORRENT_ASSERT(*i <= m_torrent_file->files().file_size(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -11233,61 +11194,6 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void initialize_file_progress(std::vector<boost::uint64_t>& file_progress
|
|
||||||
, piece_picker const& picker, file_storage const& fs)
|
|
||||||
{
|
|
||||||
int num_pieces = fs.num_pieces();
|
|
||||||
int num_files = fs.num_files();
|
|
||||||
|
|
||||||
file_progress.resize(num_files, 0);
|
|
||||||
std::fill(file_progress.begin(), file_progress.end(), 0);
|
|
||||||
|
|
||||||
// initialize the progress of each file
|
|
||||||
|
|
||||||
const int piece_size = fs.piece_length();
|
|
||||||
boost::uint64_t off = 0;
|
|
||||||
boost::uint64_t total_size = fs.total_size();
|
|
||||||
int file_index = 0;
|
|
||||||
for (int piece = 0; piece < num_pieces; ++piece, off += piece_size)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(file_index < fs.num_files());
|
|
||||||
boost::int64_t file_offset = off - fs.file_offset(file_index);
|
|
||||||
TORRENT_ASSERT(file_offset >= 0);
|
|
||||||
while (file_offset >= fs.file_size(file_index))
|
|
||||||
{
|
|
||||||
++file_index;
|
|
||||||
TORRENT_ASSERT(file_index < fs.num_files());
|
|
||||||
file_offset = off - fs.file_offset(file_index);
|
|
||||||
TORRENT_ASSERT(file_offset >= 0);
|
|
||||||
}
|
|
||||||
TORRENT_ASSERT(file_offset <= fs.file_size(file_index));
|
|
||||||
|
|
||||||
if (!picker.have_piece(piece)) continue;
|
|
||||||
|
|
||||||
int size = (std::min)(boost::uint64_t(piece_size), total_size - off);
|
|
||||||
TORRENT_ASSERT(size >= 0);
|
|
||||||
|
|
||||||
while (size)
|
|
||||||
{
|
|
||||||
int add = (std::min)(boost::int64_t(size), fs.file_size(file_index) - file_offset);
|
|
||||||
TORRENT_ASSERT(add >= 0);
|
|
||||||
file_progress[file_index] += add;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(file_progress[file_index]
|
|
||||||
<= fs.file_size(file_index));
|
|
||||||
|
|
||||||
size -= add;
|
|
||||||
TORRENT_ASSERT(size >= 0);
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
++file_index;
|
|
||||||
TORRENT_ASSERT(file_index < fs.num_files());
|
|
||||||
file_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void torrent::file_progress(std::vector<boost::int64_t>& fp, int flags)
|
void torrent::file_progress(std::vector<boost::int64_t>& fp, int flags)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
|
@ -11320,21 +11226,14 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_files = m_torrent_file->num_files();
|
int num_files = m_torrent_file->num_files();
|
||||||
if (m_file_progress.empty())
|
// if this is the first time the client asks for file progress.
|
||||||
{
|
// allocate it and make sure it's up to date
|
||||||
// This is the first time the client asks for file progress.
|
|
||||||
// allocate it and make sure it's up to date
|
|
||||||
|
|
||||||
// we cover the case where we're a seed above
|
// we cover the case where we're a seed above
|
||||||
TORRENT_ASSERT(has_picker());
|
TORRENT_ASSERT(has_picker());
|
||||||
|
m_file_progress.init(picker(), m_torrent_file->files());
|
||||||
|
|
||||||
initialize_file_progress(m_file_progress
|
m_file_progress.export_progress(fp);
|
||||||
, picker(), m_torrent_file->files());
|
|
||||||
}
|
|
||||||
|
|
||||||
fp.resize(num_files, 0);
|
|
||||||
|
|
||||||
std::copy(m_file_progress.begin(), m_file_progress.end(), fp.begin());
|
|
||||||
|
|
||||||
if (flags & torrent_handle::piece_granularity)
|
if (flags & torrent_handle::piece_granularity)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -141,7 +141,8 @@ test-suite libtorrent :
|
||||||
test_peer_classes.cpp
|
test_peer_classes.cpp
|
||||||
test_settings_pack.cpp
|
test_settings_pack.cpp
|
||||||
test_fence.cpp
|
test_fence.cpp
|
||||||
test_dos_blocker.cpp ]
|
test_dos_blocker.cpp
|
||||||
|
test_file_progress.cpp ]
|
||||||
|
|
||||||
[ run test_storage.cpp ]
|
[ run test_storage.cpp ]
|
||||||
[ run test_session.cpp ]
|
[ run test_session.cpp ]
|
||||||
|
|
|
@ -32,7 +32,8 @@ test_programs = \
|
||||||
test_session \
|
test_session \
|
||||||
test_web_seed \
|
test_web_seed \
|
||||||
test_url_seed \
|
test_url_seed \
|
||||||
test_remap_files
|
test_remap_files \
|
||||||
|
test_file_progress
|
||||||
|
|
||||||
if ENABLE_TESTS
|
if ENABLE_TESTS
|
||||||
check_PROGRAMS = $(test_programs)
|
check_PROGRAMS = $(test_programs)
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_utils.hpp"
|
||||||
|
#include "libtorrent/aux_/file_progress.hpp"
|
||||||
|
#include "libtorrent/file_storage.hpp"
|
||||||
|
#include "libtorrent/piece_picker.hpp"
|
||||||
|
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
TORRENT_TEST(init)
|
||||||
|
{
|
||||||
|
// test the init function to make sure it assigns
|
||||||
|
// the correct number of bytes across the files
|
||||||
|
const int piece_size = 256;
|
||||||
|
|
||||||
|
file_storage fs;
|
||||||
|
fs.add_file("torrent/1", 0);
|
||||||
|
fs.add_file("torrent/2", 10);
|
||||||
|
fs.add_file("torrent/3", 20);
|
||||||
|
fs.add_file("torrent/4", 30);
|
||||||
|
fs.add_file("torrent/5", 40);
|
||||||
|
fs.add_file("torrent/6", 100000);
|
||||||
|
fs.add_file("torrent/7", 30);
|
||||||
|
fs.set_piece_length(piece_size);
|
||||||
|
fs.set_num_pieces((fs.total_size() + piece_size - 1) / piece_size);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < fs.num_pieces(); ++idx)
|
||||||
|
{
|
||||||
|
piece_picker picker;
|
||||||
|
picker.init(4, fs.total_size() % 4, fs.num_pieces());
|
||||||
|
picker.we_have(idx);
|
||||||
|
|
||||||
|
aux::file_progress fp;
|
||||||
|
fp.init(picker, fs);
|
||||||
|
|
||||||
|
std::vector<boost::int64_t> vec;
|
||||||
|
fp.export_progress(vec);
|
||||||
|
|
||||||
|
boost::uint64_t sum = 0;
|
||||||
|
for (int i = 0; i < int(vec.size()); ++i)
|
||||||
|
sum += vec[i];
|
||||||
|
|
||||||
|
TEST_EQUAL(sum, fs.piece_size(idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(init2)
|
||||||
|
{
|
||||||
|
// test the init function to make sure it assigns
|
||||||
|
// the correct number of bytes across the files
|
||||||
|
const int piece_size = 256;
|
||||||
|
|
||||||
|
file_storage fs;
|
||||||
|
fs.add_file("torrent/1", 100000);
|
||||||
|
fs.add_file("torrent/2", 10);
|
||||||
|
fs.set_piece_length(piece_size);
|
||||||
|
fs.set_num_pieces((fs.total_size() + piece_size - 1) / piece_size);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < fs.num_pieces(); ++idx)
|
||||||
|
{
|
||||||
|
piece_picker picker;
|
||||||
|
picker.init(4, fs.total_size() % 4, fs.num_pieces());
|
||||||
|
picker.we_have(idx);
|
||||||
|
|
||||||
|
std::vector<boost::int64_t> vec;
|
||||||
|
aux::file_progress fp;
|
||||||
|
|
||||||
|
fp.init(picker, fs);
|
||||||
|
fp.export_progress(vec);
|
||||||
|
|
||||||
|
boost::uint64_t sum = 0;
|
||||||
|
for (int i = 0; i < vec.size(); ++i)
|
||||||
|
sum += vec[i];
|
||||||
|
|
||||||
|
TEST_EQUAL(int(sum), fs.piece_size(idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test the update function too
|
||||||
|
|
|
@ -204,68 +204,6 @@ TORRENT_TEST(torrent)
|
||||||
test_running_torrent(info, 0);
|
test_running_torrent(info, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
// test the initialize_file_progress function to make sure it assigns
|
|
||||||
// the correct number of bytes across the files
|
|
||||||
const int piece_size = 256;
|
|
||||||
|
|
||||||
file_storage fs;
|
|
||||||
fs.add_file("torrent/1", 0);
|
|
||||||
fs.add_file("torrent/2", 10);
|
|
||||||
fs.add_file("torrent/3", 20);
|
|
||||||
fs.add_file("torrent/4", 30);
|
|
||||||
fs.add_file("torrent/5", 40);
|
|
||||||
fs.add_file("torrent/6", 100000);
|
|
||||||
fs.add_file("torrent/7", 30);
|
|
||||||
fs.set_piece_length(piece_size);
|
|
||||||
fs.set_num_pieces((fs.total_size() + piece_size - 1) / piece_size);
|
|
||||||
|
|
||||||
for (int idx = 0; idx < fs.num_pieces(); ++idx)
|
|
||||||
{
|
|
||||||
piece_picker picker;
|
|
||||||
picker.init(4, fs.total_size() % 4, fs.num_pieces());
|
|
||||||
picker.we_have(idx);
|
|
||||||
|
|
||||||
std::vector<boost::uint64_t> fp;
|
|
||||||
|
|
||||||
initialize_file_progress(fp, picker, fs);
|
|
||||||
|
|
||||||
boost::uint64_t sum = 0;
|
|
||||||
for (int i = 0; i < int(fp.size()); ++i)
|
|
||||||
sum += fp[i];
|
|
||||||
|
|
||||||
TEST_EQUAL(sum, fs.piece_size(idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// test the initialize_file_progress function to make sure it assigns
|
|
||||||
// the correct number of bytes across the files
|
|
||||||
const int piece_size = 256;
|
|
||||||
|
|
||||||
file_storage fs;
|
|
||||||
fs.add_file("torrent/1", 100000);
|
|
||||||
fs.add_file("torrent/2", 10);
|
|
||||||
fs.set_piece_length(piece_size);
|
|
||||||
fs.set_num_pieces((fs.total_size() + piece_size - 1) / piece_size);
|
|
||||||
|
|
||||||
for (int idx = 0; idx < fs.num_pieces(); ++idx)
|
|
||||||
{
|
|
||||||
piece_picker picker;
|
|
||||||
picker.init(4, fs.total_size() % 4, fs.num_pieces());
|
|
||||||
picker.we_have(idx);
|
|
||||||
|
|
||||||
std::vector<boost::uint64_t> fp;
|
|
||||||
|
|
||||||
initialize_file_progress(fp, picker, fs);
|
|
||||||
|
|
||||||
boost::uint64_t sum = 0;
|
|
||||||
for (int i = 0; i < fp.size(); ++i)
|
|
||||||
sum += fp[i];
|
|
||||||
|
|
||||||
TEST_EQUAL(int(sum), fs.piece_size(idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue