fix file progress calculation bug (with unit test)
This commit is contained in:
parent
aae56c991c
commit
77363ad93e
|
@ -107,6 +107,11 @@ namespace libtorrent
|
|||
class bt_peer_connection;
|
||||
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
|
||||
{
|
||||
struct piece_checker_data;
|
||||
|
|
|
@ -10876,7 +10876,54 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
void torrent::file_progress(std::vector<size_type>& fp, int flags)
|
||||
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);
|
||||
|
||||
// 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());
|
||||
size_type file_offset = off - fs.file_offset(file_index);
|
||||
while (file_offset >= fs.file_size(file_index))
|
||||
{
|
||||
++file_index;
|
||||
file_offset = off - fs.file_offset(file_index);
|
||||
}
|
||||
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);
|
||||
|
||||
while (size)
|
||||
{
|
||||
int add = (std::min)(boost::int64_t(size), fs.file_size(file_index) - file_offset);
|
||||
file_progress[file_index] += add;
|
||||
|
||||
TORRENT_ASSERT(file_progress[file_index]
|
||||
<= fs.file_size(file_index));
|
||||
|
||||
size -= add;
|
||||
if (size >= 0)
|
||||
{
|
||||
++file_index;
|
||||
file_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::file_progress(std::vector<boost::int64_t>& fp, int flags)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
if (!valid_metadata())
|
||||
|
@ -10889,7 +10936,7 @@ namespace libtorrent
|
|||
|
||||
// if we're a seed, we don't have an m_file_progress anyway
|
||||
// since we don't need one. We know we have all files
|
||||
if (is_seed())
|
||||
if (is_seed() || !has_picker())
|
||||
{
|
||||
fp.resize(m_torrent_file->num_files());
|
||||
file_storage const& fs = m_torrent_file->files();
|
||||
|
@ -10911,48 +10958,12 @@ namespace libtorrent
|
|||
{
|
||||
// This is the first time the client asks for file progress.
|
||||
// allocate it and make sure it's up to date
|
||||
m_file_progress.resize(num_files, 0);
|
||||
|
||||
int num_pieces = m_torrent_file->num_pieces();
|
||||
// we cover the case where we're a seed above
|
||||
TORRENT_ASSERT(has_picker());
|
||||
|
||||
// initialize the progress of each file
|
||||
|
||||
const int piece_size = m_torrent_file->piece_length();
|
||||
boost::uint64_t off = 0;
|
||||
boost::uint64_t total_size = m_torrent_file->total_size();
|
||||
int file_index = 0;
|
||||
file_storage const& fs = m_torrent_file->files();
|
||||
for (int piece = 0; piece < num_pieces; ++piece, off += piece_size)
|
||||
{
|
||||
TORRENT_ASSERT(file_index < fs.num_files());
|
||||
size_type file_offset = off - fs.file_offset(file_index);
|
||||
if (file_offset >= fs.file_size(file_index))
|
||||
{
|
||||
++file_index;
|
||||
continue;
|
||||
}
|
||||
TORRENT_ASSERT(file_offset <= fs.file_size(file_index));
|
||||
|
||||
if (!have_piece(piece)) continue;
|
||||
|
||||
int size = (std::min)(boost::uint64_t(piece_size), total_size - off);
|
||||
|
||||
while (size)
|
||||
{
|
||||
int add = (std::min)(boost::int64_t(size), fs.file_size(file_index) - file_offset);
|
||||
m_file_progress[file_index] += add;
|
||||
|
||||
TORRENT_ASSERT(m_file_progress[file_index]
|
||||
<= m_torrent_file->files().file_size(file_index));
|
||||
|
||||
size -= add;
|
||||
if (size > 0)
|
||||
{
|
||||
++file_index;
|
||||
file_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
initialize_file_progress(m_file_progress
|
||||
, picker(), m_torrent_file->files());
|
||||
}
|
||||
|
||||
fp.resize(num_files, 0);
|
||||
|
|
|
@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/create_torrent.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/thread.hpp"
|
||||
#include "libtorrent/torrent.hpp"
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <iostream>
|
||||
|
@ -210,6 +211,40 @@ int test_main()
|
|||
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 < fp.size(); ++i)
|
||||
sum += fp[i];
|
||||
|
||||
TEST_EQUAL(sum, fs.piece_size(idx));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue