From 146c104eb390054446c3f71c74a60bee3241a842 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Sat, 27 May 2006 23:35:20 +0000 Subject: [PATCH] * Added "stop_on_ratio" option and display the ratio. Patch by Josef Drexler, public domain. * Made autogen.sh detect glibtoolize. * Don't resume torrents that are marked as completed yet the initial hash check returns failed chunks. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@704 e378c898-3ddf-0310-93e7-cc216c733640 --- autogen.sh | 16 +++++++++------ doc/rtorrent.1.xml | 26 ++++++++++++++++++++++++ doc/rtorrent.rc | 8 +++++++- src/core/download.cc | 2 ++ src/core/download.h | 1 + src/core/download_factory.cc | 3 +++ src/core/download_list.cc | 15 +++++++++----- src/display/client_info.h | 1 + src/display/utils.cc | 38 ++++++++++++++++++++---------------- src/main.cc | 1 + src/option_handler_rules.cc | 38 +++++++++++++++++++++++++++++++++++- src/ui/download_list.cc | 15 ++++++++++++++ src/ui/download_list.h | 2 ++ src/utils/variable.h | 4 ++-- 14 files changed, 138 insertions(+), 32 deletions(-) diff --git a/autogen.sh b/autogen.sh index ac61f632..bd7fc988 100755 --- a/autogen.sh +++ b/autogen.sh @@ -6,7 +6,7 @@ echo aclocal... exit 1 } -aclocal -I . -I ./scripts ${ACLOCAL_FLAGS} +aclocal -I ./scripts -I . ${ACLOCAL_FLAGS} echo autoheader... (autoheader --version) < /dev/null > /dev/null 2>&1 || { @@ -17,12 +17,16 @@ echo autoheader... autoheader echo libtoolize... -(libtoolize --version) < /dev/null > /dev/null 2>&1 || { - echo libtoolize not found - exit 1 -} +if ( (libtoolize --version) < /dev/null > /dev/null 2>&1 ) ; then + libtoolize --automake --copy --force -libtoolize --automake --copy --force +elif ( (glibtoolize --version) < /dev/null > /dev/null 2>&1 ); then + glibtoolize --automake --copy --force + +else + echo libtoolize nor glibtoolize not found + exit 1 +fi echo automake... (automake --version) < /dev/null > /dev/null 2>&1 || { diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml index 1eb5faba..f470acad 100644 --- a/doc/rtorrent.1.xml +++ b/doc/rtorrent.1.xml @@ -199,6 +199,13 @@ Close a torrent and its files. + + I + + Toggle whether torrent ignores ratio settings. + + + @@ -586,6 +593,25 @@ Close any active torrents on filesystems with less than + + stop_on_ratio = min_ratio + stop_on_ratio = min_ratio,min_upload + stop_on_ratio = min_ratio,min_upload,max_ratio + + +Stop torrents when they reach the given upload ratio +min_ratio in percent. If the optional +min_upload is given, require a total +upload amount of this many bytes as well. If the optional +max_ratio> is given, stop the torrent +when reaching this ratio regardless of the total upload +amount. Exclude certain torrent by pressing +Shift+I in the downlist list. +Use with schedule. + + + + load = file load_start = file diff --git a/doc/rtorrent.rc b/doc/rtorrent.rc index 42843f1d..d3b4a0fe 100644 --- a/doc/rtorrent.rc +++ b/doc/rtorrent.rc @@ -27,7 +27,13 @@ #schedule = untied_directory,5,5,stop_untied= # Close torrents when diskspace is low. -#schedule = untied_directory,5,60,close_low_diskspace=100M +#schedule = low_diskspace,5,60,close_low_diskspace=100M + +# Stop torrents when reaching upload ratio in percent, +# when also reaching total upload in bytes, or when +# reaching final upload ratio in percent. +# example: stop at ratio 2.0 with at least 200 MB uploaded, or else ratio 20.0 +#schedule = ratio,60,60,stop_on_ratio=200,200M,2000 # The ip address reported to the tracker. #ip = 127.0.0.1 diff --git a/src/core/download.cc b/src/core/download.cc index c98ff0c5..d2a4c6ea 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -100,6 +100,8 @@ Download::Download(download_type d) : rak::mem_fn(&m_download, &download_type::set_uploads_max))); m_variables.insert("priority", new utils::VariableValueSlot(rak::mem_fn(this, &Download::priority), rak::mem_fn(this, &Download::set_priority))); + + m_variables.insert("ignore_ratio", new utils::VariableObject(bencode(), "rtorrent", "ignore_ratio", torrent::Object::TYPE_VALUE)); } Download::~Download() { diff --git a/src/core/download.h b/src/core/download.h index c1f3f447..1482d053 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -67,6 +67,7 @@ public: bool is_active() const { return m_download.is_active(); } bool is_done() const { return m_download.chunks_done() == m_download.chunks_total(); } bool is_downloading() const { return is_active() && !is_done(); } + bool is_seeding() const { return is_active() && is_done(); } // FIXME: Fixed a bug in libtorrent that caused is_hash_checked to // return true when the torrent is closed. Remove this redundant diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index ae682907..783aad54 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -264,6 +264,9 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre if (rtorrent->has_key_value("total_uploaded")) download->download()->up_rate()->set_total(rtorrent->get_key("total_uploaded").as_value()); + + if (!rtorrent->has_key_value("ignore_ratio")) + rtorrent->insert_key("ignore_ratio", (int64_t)0); } } diff --git a/src/core/download_list.cc b/src/core/download_list.cc index 83d1cbe1..490b71c4 100644 --- a/src/core/download_list.cc +++ b/src/core/download_list.cc @@ -287,7 +287,7 @@ DownloadList::resume(Download* download) { // Set 'hashing' to started if hashing wasn't started, else keep // the old value. if (download->variable()->get_value("hashing") == Download::variable_hashing_stopped) - download->variable()->set("hashing", Download::variable_hashing_initial); + download->variable()->set("hashing", Download::variable_hashing_initial); std::for_each(slot_map_hash_queued().begin(), slot_map_hash_queued().end(), download_list_call(download)); return; @@ -401,11 +401,16 @@ DownloadList::hash_done(Download* download) { case Download::variable_hashing_rehash: // Normal re/hashing. - if (download->is_done()) - download->variable()->set("complete", (int64_t)1); - + // If the download was previously completed but the files were + // f.ex deleted, then we clear the state and complete. + if (!download->variable()->get_value("complete") && download->is_done()) { + download->variable()->set("state", (int64_t)0); + download->set_message("Download registered as completed, but hash check returned unfinished chunks."); + } + // Save resume data so we update time-stamps and priorities if - // they were invalid/changed when loading. + // they were invalid/changed while loading/hashing. + download->variable()->set("complete", (int64_t)download->is_done()); download->download()->hash_resume_save(); if (download->variable()->get_value("state") == 1) diff --git a/src/display/client_info.h b/src/display/client_info.h index f8f2dd5a..db96ab95 100644 --- a/src/display/client_info.h +++ b/src/display/client_info.h @@ -71,6 +71,7 @@ public: case TYPE_AZUREUS: return 2; case TYPE_COMPACT: return 1; case TYPE_MAINLINE: return 1; + default: case TYPE_MAXSIZE: return 0; } } diff --git a/src/display/utils.cc b/src/display/utils.cc index 6961d621..35fa96e8 100644 --- a/src/display/utils.cc +++ b/src/display/utils.cc @@ -132,13 +132,13 @@ print_download_info(char* first, char* last, core::Download* d) { first = print_buffer(first, last, "done %10.1f MB", (double)d->download()->bytes_total() / (double)(1 << 20)); else first = print_buffer(first, last, "%6.1f / %6.1f MB", - (double)d->download()->bytes_done() / (double)(1 << 20), - (double)d->download()->bytes_total() / (double)(1 << 20)); + (double)d->download()->bytes_done() / (double)(1 << 20), + (double)d->download()->bytes_total() / (double)(1 << 20)); first = print_buffer(first, last, " Rate: %5.1f / %5.1f KB Uploaded: %7.1f MB", - (double)d->download()->up_rate()->rate() / (1 << 10), - (double)d->download()->down_rate()->rate() / (1 << 10), - (double)d->download()->up_rate()->total() / (1 << 20)); + (double)d->download()->up_rate()->rate() / (1 << 10), + (double)d->download()->down_rate()->rate() / (1 << 10), + (double)d->download()->up_rate()->total() / (1 << 20)); if (d->download()->is_active() && !d->is_done()) { first = print_buffer(first, last, " "); @@ -150,6 +150,10 @@ print_download_info(char* first, char* last, core::Download* d) { first = print_buffer(first, last, " "); } + if (d->download()->bytes_done() > 0) + first = print_buffer(first, last, " R: %3.2f", + (double)(100 * d->download()->up_rate()->total() / d->download()->bytes_done()) / 100); + if (d->priority() != 2) first = print_buffer(first, last, " [%s]", core::Download::priority_to_string(d->priority())); @@ -166,13 +170,13 @@ print_download_status(char* first, char* last, core::Download* d) { if (d->is_hash_checking()) { first = print_buffer(first, last, "Checking hash [%2i%%]", - (d->download()->chunks_hashed() * 100) / d->download()->chunks_total()); + (d->download()->chunks_hashed() * 100) / d->download()->chunks_total()); } else if (d->tracker_list()->is_busy() && d->tracker_list()->focus() < d->tracker_list()->size()) { torrent::TrackerList* tl = d->tracker_list(); first = print_buffer(first, last, "Tracker[%i:%i]: Connecting to %s", - tl->get(tl->focus()).group(), tl->focus(), tl->get(tl->focus()).url().c_str()); + tl->get(tl->focus()).group(), tl->focus(), tl->get(tl->focus()).url().c_str()); } else if (!d->message().empty()) { first = print_buffer(first, last, "%s", d->message().c_str()); @@ -221,8 +225,8 @@ print_status_info(char* first, char* last) { first = print_buffer(first, last, "/%3i KB]", torrent::down_throttle() / 1024); first = print_buffer(first, last, " [Rate %5.1f/%5.1f KB]", - (double)torrent::up_rate()->rate() / 1024.0, - (double)torrent::down_rate()->rate() / 1024.0); + (double)torrent::up_rate()->rate() / 1024.0, + (double)torrent::down_rate()->rate() / 1024.0); first = print_buffer(first, last, " [Port: %i]", (unsigned int)torrent::connection_manager()->listen_port()); @@ -247,17 +251,17 @@ print_status_info(char* first, char* last) { char* print_status_extra(char* first, char* last, __UNUSED Control* c) { first = print_buffer(first, last, " [U %i/%i]", - torrent::currently_unchoked(), - torrent::max_unchoked()); + torrent::currently_unchoked(), + torrent::max_unchoked()); first = print_buffer(first, last, " [S %i/%i/%i]", - torrent::total_handshakes(), - torrent::open_sockets(), - torrent::max_open_sockets()); - + torrent::total_handshakes(), + torrent::open_sockets(), + torrent::max_open_sockets()); + first = print_buffer(first, last, " [F %i/%i]", - torrent::open_files(), - torrent::max_open_files()); + torrent::open_files(), + torrent::max_open_files()); return first; } diff --git a/src/main.cc b/src/main.cc index 5608b3f8..bbe04c98 100644 --- a/src/main.cc +++ b/src/main.cc @@ -325,6 +325,7 @@ print_help() { std::cout << " ^q Initiate shutdown or skip shutdown process" << std::endl; std::cout << " a,s,d,z,x,c Adjust upload throttle" << std::endl; std::cout << " A,S,D,Z,X,C Adjust download throttle" << std::endl; + std::cout << " I Toggle whether torrent ignores ratio settings" << std::endl; std::cout << " right View torrent" << std::endl; std::cout << std::endl; std::cout << "Download view keys:" << std::endl; diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 1aeb7ecd..db282993 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -181,6 +182,40 @@ apply_close_low_diskspace(Control* m, int64_t arg) { } } +void +apply_stop_on_ratio(Control* m, const std::string& arg) { + int64_t min_Ratio = 0; // first argument: minimum ratio to reach + int64_t min_Upload = 0; // second argument: minimum upload amount to reach [optional] + int64_t max_Ratio = 0; // third argument: maximum ratio to reach [optional] + + rak::split_iterator_t sitr = rak::split_iterator(arg, ','); + + utils::Variable::string_to_value_unit(rak::trim(*sitr).c_str(), &min_Ratio, 0, 1); + + if (++sitr != rak::split_iterator(arg)) + utils::Variable::string_to_value_unit(rak::trim(*sitr).c_str(), &min_Upload, 0, 1); + + if (++sitr != rak::split_iterator(arg)) + utils::Variable::string_to_value_unit(rak::trim(*sitr).c_str(), &max_Ratio, 0, 1); + + core::Manager::DListItr itr = m->core()->download_list()->begin(); + + while ((itr = std::find_if(itr, m->core()->download_list()->end(), + rak::equal(true, std::mem_fun(&core::Download::is_seeding)))) + != m->core()->download_list()->end()) { + int64_t totalUpload = (*itr)->download()->up_rate()->total(); + int64_t totalDone = (*itr)->download()->bytes_done(); + + if ((totalUpload >= min_Upload && totalUpload * 100 >= totalDone * min_Ratio) || + (max_Ratio > 0 && totalUpload * 100 > totalDone * max_Ratio)) { + if ((*itr)->variable()->get_value("ignore_ratio") <= 0) + m->core()->download_list()->stop(*itr); + } + + ++itr; + } +} + void apply_encoding_list(__UNUSED Control* m, const std::string& arg) { torrent::encoding_list()->push_back(arg); @@ -432,7 +467,8 @@ initialize_option_handler(Control* c) { variables->insert("stop_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_stop_untied, c))); variables->insert("close_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_close_untied, c))); variables->insert("remove_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_remove_untied, c))); - variables->insert("close_low_diskspace", new utils::VariableValueSlot(rak::value_fn(int64_t()), rak::bind_ptr_fn(&apply_close_low_diskspace, c))); + variables->insert("close_low_diskspace", new utils::VariableValueSlot(rak::value_fn(int64_t()), rak::bind_ptr_fn(&apply_close_low_diskspace, c))); + variables->insert("stop_on_ratio", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_stop_on_ratio, c))); variables->insert("enable_trackers", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_enable_trackers, c))); variables->insert("encoding_list", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_encoding_list, c))); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 09a43bde..4761bb2d 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -282,6 +282,20 @@ DownloadList::receive_check_hash() { m_control->core()->download_list()->check_hash(*m_view->focus()); } +void +DownloadList::receive_ignore_ratio() { + if (m_view->focus() == m_view->end_visible()) + return; + + if ((*m_view->focus())->variable()->get_value("ignore_ratio") > 0) { + (*m_view->focus())->variable()->set("ignore_ratio", (int64_t)0); + m_control->core()->push_log("Torrent set to stop when reaching upload ratio."); + } else { + (*m_view->focus())->variable()->set("ignore_ratio", (int64_t)1); + m_control->core()->push_log("Torrent set to no longer stop when reaching upload ratio."); + } +} + void DownloadList::receive_view_input(Input type) { if (m_windowTextInput->get_active()) @@ -411,6 +425,7 @@ DownloadList::setup_keys() { (*m_bindings)['\x12'] = sigc::mem_fun(*this, &DownloadList::receive_check_hash); (*m_bindings)['+'] = sigc::mem_fun(*this, &DownloadList::receive_next_priority); (*m_bindings)['-'] = sigc::mem_fun(*this, &DownloadList::receive_prev_priority); + (*m_bindings)['I'] = sigc::mem_fun(*this, &DownloadList::receive_ignore_ratio); (*m_bindings)['\x7f'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_view_input), INPUT_LOAD_DEFAULT); (*m_bindings)[KEY_BACKSPACE] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_view_input), INPUT_LOAD_DEFAULT); diff --git a/src/ui/download_list.h b/src/ui/download_list.h index 317049fa..e7ac2954 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -130,6 +130,8 @@ private: void receive_check_hash(); + void receive_ignore_ratio(); + void receive_view_input(Input type); void receive_exit_input(Input type); diff --git a/src/utils/variable.h b/src/utils/variable.h index dfd3f37b..e2130bc1 100644 --- a/src/utils/variable.h +++ b/src/utils/variable.h @@ -55,12 +55,12 @@ public: virtual const torrent::Object& get() = 0; virtual void set(const torrent::Object& arg) = 0; + static const char* string_to_value_unit(const char* pos, value_type* value, int base, int unit); + protected: Variable(const Variable&); void operator = (const Variable&); - static const char* string_to_value_unit(const char* pos, value_type* value, int base, int unit); - // Temporary hack, until torrent::Object is extended to allow // references so we can return a copy, not a const reference. static const torrent::Object m_emptyObject;