forked from premiere/premiere-libtorrent
fixed fast resume data bug when using full allocation mode, and moved parts of resume data generation to the storage
This commit is contained in:
parent
58b23a79e7
commit
510966f2a5
|
@ -320,6 +320,12 @@ namespace libtorrent
|
||||||
// when they are destructed.
|
// when they are destructed.
|
||||||
file_pool m_files;
|
file_pool m_files;
|
||||||
|
|
||||||
|
// this is a list of half-open tcp connections
|
||||||
|
// (only outgoing connections)
|
||||||
|
// this has to be one of the last
|
||||||
|
// members to be destructed
|
||||||
|
connection_queue m_half_open;
|
||||||
|
|
||||||
// the bandwidth manager is responsible for
|
// the bandwidth manager is responsible for
|
||||||
// handing out bandwidth to connections that
|
// handing out bandwidth to connections that
|
||||||
// asks for it, it can also throttle the
|
// asks for it, it can also throttle the
|
||||||
|
@ -335,10 +341,6 @@ namespace libtorrent
|
||||||
// peers.
|
// peers.
|
||||||
connection_map m_connections;
|
connection_map m_connections;
|
||||||
|
|
||||||
// this is a list of half-open tcp connections
|
|
||||||
// (only outgoing connections)
|
|
||||||
connection_queue m_half_open;
|
|
||||||
|
|
||||||
// filters incoming connections
|
// filters incoming connections
|
||||||
ip_filter m_ip_filter;
|
ip_filter m_ip_filter;
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ namespace libtorrent
|
||||||
torrent_info const& t
|
torrent_info const& t
|
||||||
, boost::filesystem::path p
|
, boost::filesystem::path p
|
||||||
, std::vector<std::pair<size_type, std::time_t> > const& sizes
|
, std::vector<std::pair<size_type, std::time_t> > const& sizes
|
||||||
|
, bool compact_mode
|
||||||
, std::string* error = 0);
|
, std::string* error = 0);
|
||||||
|
|
||||||
struct TORRENT_EXPORT file_allocation_failed: std::exception
|
struct TORRENT_EXPORT file_allocation_failed: std::exception
|
||||||
|
@ -104,8 +105,12 @@ namespace libtorrent
|
||||||
|
|
||||||
virtual bool move_storage(boost::filesystem::path save_path) = 0;
|
virtual bool move_storage(boost::filesystem::path save_path) = 0;
|
||||||
|
|
||||||
|
// verify storage dependent fast resume entries
|
||||||
virtual bool verify_resume_data(entry& rd, std::string& error) = 0;
|
virtual bool verify_resume_data(entry& rd, std::string& error) = 0;
|
||||||
|
|
||||||
|
// write storage dependent fast resume entries
|
||||||
|
virtual void write_resume_data(entry& rd) const = 0;
|
||||||
|
|
||||||
// moves (or copies) the content in src_slot to dst_slot
|
// moves (or copies) the content in src_slot to dst_slot
|
||||||
virtual void move_slot(int src_slot, int dst_slot) = 0;
|
virtual void move_slot(int src_slot, int dst_slot) = 0;
|
||||||
|
|
||||||
|
@ -153,6 +158,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void release_files();
|
void release_files();
|
||||||
|
|
||||||
|
void write_resume_data(entry& rd) const;
|
||||||
bool verify_resume_data(entry& rd, std::string& error);
|
bool verify_resume_data(entry& rd, std::string& error);
|
||||||
|
|
||||||
bool is_allocating() const;
|
bool is_allocating() const;
|
||||||
|
|
|
@ -478,10 +478,10 @@ namespace libtorrent { namespace detail
|
||||||
, char const* listen_interface)
|
, char const* listen_interface)
|
||||||
: m_strand(m_io_service)
|
: m_strand(m_io_service)
|
||||||
, m_files(40)
|
, m_files(40)
|
||||||
|
, m_half_open(m_io_service)
|
||||||
, m_dl_bandwidth_manager(m_io_service, peer_connection::download_channel)
|
, m_dl_bandwidth_manager(m_io_service, peer_connection::download_channel)
|
||||||
, m_ul_bandwidth_manager(m_io_service, peer_connection::upload_channel)
|
, m_ul_bandwidth_manager(m_io_service, peer_connection::upload_channel)
|
||||||
, m_tracker_manager(m_settings, m_tracker_proxy)
|
, m_tracker_manager(m_settings, m_tracker_proxy)
|
||||||
, m_half_open(m_io_service)
|
|
||||||
, m_listen_port_range(listen_port_range)
|
, m_listen_port_range(listen_port_range)
|
||||||
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
|
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
|
||||||
, m_external_listen_port(0)
|
, m_external_listen_port(0)
|
||||||
|
@ -2026,7 +2026,6 @@ namespace libtorrent { namespace detail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify file sizes
|
|
||||||
if (!torrent_ptr->verify_resume_data(rd, error))
|
if (!torrent_ptr->verify_resume_data(rd, error))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -270,10 +270,17 @@ namespace libtorrent
|
||||||
return sizes;
|
return sizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// matches the sizes and timestamps of the files passed in
|
||||||
|
// in non-compact mode, actual file sizes and timestamps
|
||||||
|
// are allowed to be bigger and more recent than the fast
|
||||||
|
// resume data. This is because full allocation will not move
|
||||||
|
// pieces, so any older version of the resume data will
|
||||||
|
// still be a correct subset of the actual data on disk.
|
||||||
bool match_filesizes(
|
bool match_filesizes(
|
||||||
torrent_info const& t
|
torrent_info const& t
|
||||||
, path p
|
, path p
|
||||||
, std::vector<std::pair<size_type, std::time_t> > const& sizes
|
, std::vector<std::pair<size_type, std::time_t> > const& sizes
|
||||||
|
, bool compact_mode
|
||||||
, std::string* error)
|
, std::string* error)
|
||||||
{
|
{
|
||||||
if ((int)sizes.size() != t.num_files())
|
if ((int)sizes.size() != t.num_files())
|
||||||
|
@ -293,6 +300,7 @@ namespace libtorrent
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
path f = p / i->path;
|
path f = p / i->path;
|
||||||
|
std::cerr << f.string() << " ";
|
||||||
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400
|
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400
|
||||||
size = file_size_win(f);
|
size = file_size_win(f);
|
||||||
time = last_write_time_win(f);
|
time = last_write_time_win(f);
|
||||||
|
@ -302,19 +310,23 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch (std::exception&) {}
|
catch (std::exception&) {}
|
||||||
if (size != s->first)
|
if (size != s->first
|
||||||
|
|| (!compact_mode && size < s->first))
|
||||||
{
|
{
|
||||||
if (error) *error = "filesize mismatch for file '"
|
if (error) *error = "filesize mismatch for file '"
|
||||||
+ i->path.native_file_string()
|
+ i->path.native_file_string()
|
||||||
+ "', expected to be " + boost::lexical_cast<std::string>(s->first)
|
+ "', size: " + boost::lexical_cast<std::string>(size)
|
||||||
|
+ ", expected to be " + boost::lexical_cast<std::string>(s->first)
|
||||||
+ " bytes";
|
+ " bytes";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (time != s->second)
|
if (time != s->second
|
||||||
|
|| (!compact_mode && time < s->second))
|
||||||
{
|
{
|
||||||
if (error) *error = "timestamp mismatch for file '"
|
if (error) *error = "timestamp mismatch for file '"
|
||||||
+ i->path.native_file_string()
|
+ i->path.native_file_string()
|
||||||
+ "', expected to have modification date "
|
+ "', modification date: " + boost::lexical_cast<std::string>(time)
|
||||||
|
+ ", expected to have modification date "
|
||||||
+ boost::lexical_cast<std::string>(s->second);
|
+ boost::lexical_cast<std::string>(s->second);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -379,6 +391,7 @@ namespace libtorrent
|
||||||
void swap_slots(int slot1, int slot2);
|
void swap_slots(int slot1, int slot2);
|
||||||
void swap_slots3(int slot1, int slot2, int slot3);
|
void swap_slots3(int slot1, int slot2, int slot3);
|
||||||
bool verify_resume_data(entry& rd, std::string& error);
|
bool verify_resume_data(entry& rd, std::string& error);
|
||||||
|
void write_resume_data(entry& rd) const;
|
||||||
|
|
||||||
size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero);
|
size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero);
|
||||||
|
|
||||||
|
@ -442,6 +455,23 @@ namespace libtorrent
|
||||||
std::vector<char>().swap(m_scratch_buffer);
|
std::vector<char>().swap(m_scratch_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void storage::write_resume_data(entry& rd) const
|
||||||
|
{
|
||||||
|
std::vector<std::pair<size_type, std::time_t> > file_sizes
|
||||||
|
= get_filesizes(m_info, m_save_path);
|
||||||
|
|
||||||
|
rd["file sizes"] = entry::list_type();
|
||||||
|
entry::list_type& fl = rd["file sizes"].list();
|
||||||
|
for (std::vector<std::pair<size_type, std::time_t> >::iterator i
|
||||||
|
= file_sizes.begin(), end(file_sizes.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
entry::list_type p;
|
||||||
|
p.push_back(entry(i->first));
|
||||||
|
p.push_back(entry(i->second));
|
||||||
|
fl.push_back(entry(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool storage::verify_resume_data(entry& rd, std::string& error)
|
bool storage::verify_resume_data(entry& rd, std::string& error)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<size_type, std::time_t> > file_sizes;
|
std::vector<std::pair<size_type, std::time_t> > file_sizes;
|
||||||
|
@ -455,6 +485,12 @@ namespace libtorrent
|
||||||
, i->list().back().integer()));
|
, i->list().back().integer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file_sizes.empty())
|
||||||
|
{
|
||||||
|
error = "the number of files in resume data is 0";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
entry::list_type& slots = rd["slots"].list();
|
entry::list_type& slots = rd["slots"].list();
|
||||||
bool seed = int(slots.size()) == m_info.num_pieces()
|
bool seed = int(slots.size()) == m_info.num_pieces()
|
||||||
&& std::find_if(slots.begin(), slots.end()
|
&& std::find_if(slots.begin(), slots.end()
|
||||||
|
@ -497,9 +533,8 @@ namespace libtorrent
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full_allocation_mode) return true;
|
return match_filesizes(m_info, m_save_path, file_sizes
|
||||||
|
, !full_allocation_mode, &error);
|
||||||
return match_filesizes(m_info, m_save_path, file_sizes, &error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true on success
|
// returns true on success
|
||||||
|
@ -1149,6 +1184,11 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void piece_manager::write_resume_data(entry& rd) const
|
||||||
|
{
|
||||||
|
m_pimpl->m_storage->write_resume_data(rd);
|
||||||
|
}
|
||||||
|
|
||||||
bool piece_manager::verify_resume_data(entry& rd, std::string& error)
|
bool piece_manager::verify_resume_data(entry& rd, std::string& error)
|
||||||
{
|
{
|
||||||
return m_pimpl->m_storage->verify_resume_data(rd, error);
|
return m_pimpl->m_storage->verify_resume_data(rd, error);
|
||||||
|
|
|
@ -1702,9 +1702,11 @@ namespace libtorrent
|
||||||
assert(peerinfo);
|
assert(peerinfo);
|
||||||
assert(peerinfo->connection == 0);
|
assert(peerinfo->connection == 0);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
// this asserts that we don't have duplicates in the policy's peer list
|
||||||
peer_iterator i_ = m_connections.find(peerinfo->ip);
|
peer_iterator i_ = m_connections.find(peerinfo->ip);
|
||||||
assert(i_ == m_connections.end()
|
assert(i_ == m_connections.end()
|
||||||
|| (i_->second->is_disconnecting()));
|
|| i_->second->is_disconnecting()
|
||||||
|
|| dynamic_cast<bt_peer_connection*>(i_->second) == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(want_more_peers());
|
assert(want_more_peers());
|
||||||
|
|
|
@ -602,19 +602,7 @@ namespace libtorrent
|
||||||
peer_list.push_back(peer);
|
peer_list.push_back(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<size_type, std::time_t> > file_sizes
|
t->filesystem().write_resume_data(ret);
|
||||||
= get_filesizes(t->torrent_file(), t->save_path());
|
|
||||||
|
|
||||||
ret["file sizes"] = entry::list_type();
|
|
||||||
entry::list_type& fl = ret["file sizes"].list();
|
|
||||||
for (std::vector<std::pair<size_type, std::time_t> >::iterator i
|
|
||||||
= file_sizes.begin(), end(file_sizes.end()); i != end; ++i)
|
|
||||||
{
|
|
||||||
entry::list_type p;
|
|
||||||
p.push_back(entry(i->first));
|
|
||||||
p.push_back(entry(i->second));
|
|
||||||
fl.push_back(entry(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue