diff --git a/ChangeLog b/ChangeLog index fec9e0b21..92945e82f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * added a new torrent state, allocating + * added a new alert, metadata_failed_alert * changed the interface to session::add_torrent for soem speed optimizations. * greatly improved the command line control of the example client_test. * fixed bug where upload rate limit was not being applied. diff --git a/docs/manual.rst b/docs/manual.rst index d793172a3..0f5d2d6d8 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -1559,7 +1559,8 @@ It contains the following fields:: connecting_to_tracker, downloading, finished, - seeding + seeding, + allocating }; state_t state; @@ -1608,15 +1609,12 @@ current task is in the ``state`` member, it will be one of the following: |``queued_for_checking`` |The torrent is in the queue for being checked. But there | | |currently is another torrent that are being checked. | | |This torrent will wait for its turn. | -| | | +--------------------------+----------------------------------------------------------+ |``checking_files`` |The torrent has not started its download yet, and is | | |currently checking existing files. | -| | | +--------------------------+----------------------------------------------------------+ |``connecting_to_tracker`` |The torrent has sent a request to the tracker and is | | |currently waiting for a response | -| | | +--------------------------+----------------------------------------------------------+ |``downloading`` |The torrent is being downloaded. This is the state | | |most torrents will be in most of the time. The progress | @@ -1629,8 +1627,12 @@ current task is in the ``state`` member, it will be one of the following: +--------------------------+----------------------------------------------------------+ |``seeding`` |In this state the torrent has finished downloading and | | |is a pure seeder. | -| | | +--------------------------+----------------------------------------------------------+ +|``allocating`` |If the torrent was started in full allocation mode, this | +| |indicates that the (disk) storage for the torrent is | +| |allocated. | ++--------------------------+----------------------------------------------------------+ + When downloading, the progress is ``total_wanted_done`` / ``total_wanted``. @@ -2499,6 +2501,29 @@ torrent in question. This alert is generated as severity level ``info``. torrent_handle handle; }; + +metadata_failed_alert +--------------------- + +This alert is generated when the metadata has been completely received and the info-hash +failed to match it. i.e. the metadata that was received was corrupt. libtorrent will +automatically retry to fetch it in this case. This is only relevant when running a +torrent-less download, with the metadata extension provided by libtorrent. +It is generated at severity level ``info``. + +:: + + struct metadata_received_alert: alert + { + metadata_received_alert( + const torrent_handle& h + , const std::string& msg); + + virtual std::auto_ptr clone() const; + torrent_handle handle; + }; + + metadata_received_alert ----------------------- diff --git a/examples/client_test.cpp b/examples/client_test.cpp index c695a07ec..59b7e785f 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -280,6 +280,7 @@ void add_torrent(libtorrent::session& ses , std::vector& handles , char const* torrent , float preferred_ratio + , bool compact_mode , boost::filesystem::path const& save_path) { using namespace libtorrent; @@ -309,7 +310,7 @@ void add_torrent(libtorrent::session& ses TORRENT_CHECKPOINT("++ ses::add_torrent"); - handles.push_back(ses.add_torrent(t, save_path, resume_data, true, 16 * 1024)); + handles.push_back(ses.add_torrent(t, save_path, resume_data, compact_mode, 16 * 1024)); TORRENT_CHECKPOINT("-- ses::add_torrent"); handles.back().set_max_connections(60); @@ -328,6 +329,7 @@ int main(int ac, char* av[]) std::string save_path_str; std::string log_level; std::string ip_filter_file; + std::string allocation_mode; namespace po = boost::program_options; @@ -350,6 +352,9 @@ int main(int ac, char* av[]) ("ip-filter,f", po::value(&ip_filter_file)->default_value("") , "sets the path to the ip-filter file used to block access from certain " "ips. ") + ("allocation-mode,a", po::value(&allocation_mode)->default_value("compact") + , "sets mode used for allocating the downloaded files on disk. " + "Possible options are [full | compact]") ("input-file,i", po::value< std::vector >() , "adds an input .torrent file. At least one is required. arguments " "without any flag are implicitly an input file. To start a torrentless " @@ -378,6 +383,8 @@ int main(int ac, char* av[]) if (download_limit <= 0) download_limit = -1; if (upload_limit <= 0) upload_limit = -1; + bool compact_allocation_mode = (allocation_mode == "compact"); + using namespace libtorrent; std::vector const& input = vm["input-file"].as< std::vector >(); @@ -468,14 +475,16 @@ int main(int ac, char* av[]) { sha1_hash info_hash = boost::lexical_cast(what[1]); - handles.push_back(ses.add_torrent(std::string(what[2]).c_str(), info_hash, save_path)); + handles.push_back(ses.add_torrent(std::string(what[2]).c_str() + , info_hash, save_path, entry(), compact_allocation_mode)); handles.back().set_max_connections(60); handles.back().set_max_uploads(-1); handles.back().set_ratio(preferred_ratio); continue; } // if it's a torrent file, open it as usual - add_torrent(ses, handles, i->c_str(), preferred_ratio, save_path); + add_torrent(ses, handles, i->c_str(), preferred_ratio + , compact_allocation_mode, save_path); } catch (std::exception& e) { @@ -602,7 +611,7 @@ int main(int ac, char* av[]) { static char const* state_str[] = {"queued", "checking", "connecting", "downloading metadata" - , "downloading", "finished", "seeding"}; + , "downloading", "finished", "seeding", "allocating"}; out << state_str[s.state] << " "; } diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 74d49df87..c6d85f141 100755 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -223,6 +223,21 @@ namespace libtorrent torrent_handle handle; }; + struct metadata_failed_alert: alert + { + metadata_failed_alert( + const torrent_handle& h + , const std::string& msg) + : alert(alert::info, msg) + , handle(h) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new metadata_failed_alert(*this)); } + + torrent_handle handle; + }; + struct metadata_received_alert: alert { metadata_received_alert( diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index b9898e0be..c74496db0 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -128,6 +128,7 @@ namespace libtorrent void release_files(); + bool is_allocating() const; void allocate_slots(int num_slots); void mark_failed(int index); diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index d5af3857f..bf9907715 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -128,6 +128,10 @@ namespace libtorrent void abort(); bool is_aborted() const { return m_abort; } + // returns true if this torrent is being allocated + // by the checker thread. + bool is_allocating() const; + // is called every second by session. This will // caclulate the upload/download and number // of connections this torrent needs. And prepare diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 35e871de5..f5d7e93c3 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -104,7 +104,8 @@ namespace libtorrent downloading_metadata, downloading, finished, - seeding + seeding, + allocating }; state_t state; diff --git a/src/session.cpp b/src/session.cpp index 20d8247fc..731add3d5 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -1006,6 +1006,7 @@ namespace libtorrent { namespace detail for (connection_map::iterator i = m_connections.begin(); i != m_connections.end(); ++i) { + assert(i->second); if (i->second->can_write() != m_selector.is_writability_monitored(i->first) || i->second->can_read() != m_selector.is_readability_monitored(i->first)) { diff --git a/src/storage.cpp b/src/storage.cpp index f4691f843..f0eb83e5c 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -836,8 +836,6 @@ namespace libtorrent void export_piece_map(std::vector& p) const; - private: - // returns the slot currently associated with the given // piece or assigns the given piece_index to a free slot @@ -1018,6 +1016,12 @@ namespace libtorrent m_pimpl->mark_failed(index); } + bool piece_manager::is_allocating() const + { + return m_pimpl->m_state + == impl::state_allocating; + } + int piece_manager::slot_for_piece(int piece_index) const { return m_pimpl->slot_for_piece(piece_index); diff --git a/src/torrent.cpp b/src/torrent.cpp index 59f83bfff..27c1b5be5 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1332,6 +1332,9 @@ namespace libtorrent return m_tracker_address; } + bool torrent::is_allocating() const + { return m_storage.get() && m_storage->is_allocating(); } + std::vector const& torrent::metadata() const { if (m_metadata.empty()) @@ -1538,6 +1541,12 @@ namespace libtorrent , false); m_metadata_progress = 0; m_metadata_size = 0; + if (m_ses.m_alerts.should_post(alert::info)) + { + m_ses.m_alerts.post_alert(metadata_failed_alert( + get_handle(), "invalid metadata received from swarm")); + } + return false; } diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index e9041ecbd..9e675d4de 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -238,8 +238,10 @@ namespace libtorrent if (d->processing) { - // TODO: this could be both checking or allocating - st.state = torrent_status::checking_files; + if (d->torrent_ptr->is_allocating()) + st.state = torrent_status::allocating; + else + st.state = torrent_status::checking_files; } else st.state = torrent_status::queued_for_checking;