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:
Arvid Norberg 2007-05-24 18:53:55 +00:00
parent 58b23a79e7
commit 510966f2a5
6 changed files with 64 additions and 27 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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());

View File

@ -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;
} }