diff --git a/deluge/core/core.py b/deluge/core/core.py index af5835892..7c67ab057 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -92,7 +92,9 @@ DEFAULT_PREFS = { "autoadd_enable": False, "add_paused": False, "max_active_seeding": 5, - "max_active_downloading": 8, + "max_active_downloading": 3, + "max_active_limit": 8, + "dont_count_slow_torrents": False, "queue_new_to_top": False, "stop_seed_at_ratio": False, "remove_seed_at_ratio": False, @@ -251,6 +253,10 @@ class Core( self._on_set_max_active_downloading) self.config.register_set_function("max_active_seeding", self._on_set_max_active_seeding) + self.config.register_set_function("max_active_limit", + self._on_set_max_active_limit) + self.config.register_set_function("dont_count_slow_torrents", + self._on_set_dont_count_slow_torrents) self.config.register_change_callback(self._on_config_value_change) # Start the AlertManager @@ -792,3 +798,14 @@ class Core( self.settings.active_seeds = value self.session.set_settings(self.settings) + def _on_set_max_active_limit(self, key, value): + log.debug("%s set to %s..", key, value) + log.debug("active_limit: %s", self.settings.active_limit) + self.settings.active_limit = value + self.session.set_settings(self.settings) + + def _on_set_dont_count_slow_torrents(self, key, value): + log.debug("%s set to %s..", key, value) + self.settings.dont_count_slow_torrents = value + self.session.set_settings(self.settings) + diff --git a/deluge/ui/gtkui/glade/preferences_dialog.glade b/deluge/ui/gtkui/glade/preferences_dialog.glade index a01d3f042..48a6d6046 100644 --- a/deluge/ui/gtkui/glade/preferences_dialog.glade +++ b/deluge/ui/gtkui/glade/preferences_dialog.glade @@ -1,6 +1,6 @@ - + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -1158,40 +1158,71 @@ Disabled 2 15 - + True - True - The maximum upload slots for all torrents. Set -1 for unlimited. - 1 - -1 -1 9000 1 10 10 - 1 - True - True + The maximum upload speed for all torrents. Set -1 for unlimited. + 0 + Maximum Upload Speed (KiB/s): + + + 3 + 4 + GTK_FILL + + + + + True + The maximum number of connections allowed. Set -1 for unlimited. + 0 + Maximum Connections: + + + GTK_FILL + + + + + True + The maximum upload speed for all torrents. Set -1 for unlimited. + 0 + Maximum Upload Slots: - 1 - 2 1 2 GTK_FILL - + True True - The maximum upload speed for all torrents. Set -1 for unlimited. + The maximum number of connections allowed. Set -1 for unlimited. + 4 1 -1 -1 9000 1 10 10 1 - 1 + True True + GTK_UPDATE_IF_VALID 1 2 - 3 - 4 + GTK_FILL + + + + + True + The maximum download speed for all torrents. Set -1 for unlimited. + 0 + Maximum Download Speed (KiB/s): + + + 2 + 3 GTK_FILL @@ -1216,74 +1247,43 @@ Disabled - + True - The maximum download speed for all torrents. Set -1 for unlimited. - 0 - Maximum Download Speed (KiB/s): + True + The maximum upload speed for all torrents. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + 1 + True - 2 - 3 + 1 + 2 + 3 + 4 GTK_FILL - + True True - The maximum number of connections allowed. Set -1 for unlimited. - 4 + The maximum upload slots for all torrents. Set -1 for unlimited. 1 -1 -1 9000 1 10 10 1 True True - GTK_UPDATE_IF_VALID 1 2 - GTK_FILL - - - - - True - The maximum upload speed for all torrents. Set -1 for unlimited. - 0 - Maximum Upload Slots: - - 1 2 GTK_FILL - - - True - The maximum number of connections allowed. Set -1 for unlimited. - 0 - Maximum Connections: - - - GTK_FILL - - - - - True - The maximum upload speed for all torrents. Set -1 for unlimited. - 0 - Maximum Upload Speed (KiB/s): - - - 3 - 4 - GTK_FILL - - @@ -1327,85 +1327,18 @@ Disabled 2 15 - - True - True - The maximum upload slots per torrent. Set -1 for unlimited. - 1 - -1 -1 9000 1 10 10 - 1 - True - True - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - + True True The maximum number of connections per torrent. Set -1 for unlimited. 1 -1 -1 9000 1 10 10 - True + 1 True 1 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Maximum Connections: - - - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Maximum Upload Slots: - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Maximum Download Speed (KiB/s): - - - 2 - 3 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Maximum Upload Speed (KiB/s): - - 3 4 GTK_FILL @@ -1430,20 +1363,87 @@ Disabled - + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Upload Speed (KiB/s): + + + 3 + 4 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Download Speed (KiB/s): + + + 2 + 3 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Upload Slots: + + + 1 + 2 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Maximum Connections: + + + GTK_FILL + + + + True True The maximum number of connections per torrent. Set -1 for unlimited. 1 -1 -1 9000 1 10 10 - 1 + True True 1 2 - 3 - 4 + GTK_FILL + + + + + True + True + The maximum upload slots per torrent. Set -1 for unlimited. + 1 + -1 -1 9000 1 10 10 + 1 + True + True + + + 1 + 2 + 1 + 2 GTK_FILL @@ -2203,68 +2203,116 @@ Disabled 5 12 - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - 10 + 5 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Total active downloading: + 3 + 2 + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Total active downloading: + + + 1 + 2 + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0 -1 9999 1 10 10 + True + True + + + 1 + 2 + 1 + 2 + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Total active: + + + GTK_FILL + + + + + True + 0 + Total active seeding: + + + 2 + 3 + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0 -1 9999 1 10 10 + True + True + + + 1 + 2 + 2 + 3 + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0 -1 9999 1 10 10 + True + True + + + 1 + 2 + + + - - 1 - 2 - GTK_FILL - - + True True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 0 -1 9999 1 10 10 - True - True + Do not count slow torrents + 0 + True - 1 - 2 - 1 - 2 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Total active: - - - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 0 -1 9999 1 10 10 - True - True - - - 1 - 2 - + 1 @@ -2313,51 +2361,18 @@ Disabled 2 10 - - True - 0 - Share Ratio Limit: - - - GTK_FILL - - - - - True - 0 - Seed Time Ratio: - - - 1 - 2 - GTK_FILL - - - - - True - 0 - Seed Time (m): - - - 2 - 3 - GTK_FILL - - - - + True True 6 1 - 1.5 -1 100 0.10000000000000001 10 10 - 2 + 6 -1 100 1 10 10 1 2 + 2 + 3 @@ -2379,19 +2394,52 @@ Disabled - + True True 6 1 - 6 -1 100 1 10 10 + 1.5 -1 100 0.10000000000000001 10 10 + 2 1 2 + + + + + + True + 0 + Seed Time (m): + + 2 3 - + GTK_FILL + + + + + True + 0 + Seed Time Ratio: + + + 1 + 2 + GTK_FILL + + + + + True + 0 + Share Ratio Limit: + + + GTK_FILL diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py index f92e1d985..be2274db7 100644 --- a/deluge/ui/gtkui/preferences.py +++ b/deluge/ui/gtkui/preferences.py @@ -241,8 +241,10 @@ class Preferences(component.Component): ("value", self.core_config["daemon_port"]), "chk_allow_remote_connections": \ ("active", self.core_config["allow_remote"]), + "spin_active": ("value", self.core_config["max_active_limit"]), "spin_seeding": ("value", self.core_config["max_active_seeding"]), "spin_downloading": ("value", self.core_config["max_active_downloading"]), + "chk_dont_count_slow_torrents": ("active", self.core_config["dont_count_slow_torrents"]), "chk_queue_new_top": ("active", self.core_config["queue_new_to_top"]), "spin_share_ratio_limit": ("value", self.core_config["share_ratio_limit"]), "spin_seed_time_ratio_limit": \ @@ -345,6 +347,8 @@ class Preferences(component.Component): "chk_allow_remote_connections", "spin_seeding", "spin_downloading", + "spin_active", + "chk_dont_count_slow_torrents", "chk_queue_new_top", "chk_seed_ratio", "spin_share_ratio", @@ -532,6 +536,10 @@ class Preferences(component.Component): self.glade.get_widget("spin_seeding").get_value_as_int() new_core_config["max_active_downloading"] = \ self.glade.get_widget("spin_downloading").get_value_as_int() + new_core_config["max_active_limit"] = \ + self.glade.get_widget("spin_active").get_value_as_int() + new_core_config["dont_count_slow_torrents"] = \ + self.glade.get_widget("chk_dont_count_slow_torrents").get_active() new_core_config["stop_seed_at_ratio"] = \ self.glade.get_widget("chk_seed_ratio").get_active() new_core_config["remove_seed_at_ratio"] = \ diff --git a/libtorrent/bindings/python/src/session_settings.cpp b/libtorrent/bindings/python/src/session_settings.cpp index d697295b5..814c1ad58 100755 --- a/libtorrent/bindings/python/src/session_settings.cpp +++ b/libtorrent/bindings/python/src/session_settings.cpp @@ -36,6 +36,8 @@ void bind_session_settings() .def_readwrite("unchoke_interval", &session_settings::unchoke_interval) .def_readwrite("active_downloads", &session_settings::active_downloads) .def_readwrite("active_seeds", &session_settings::active_seeds) + .def_readwrite("active_limit", &session_settings::active_limit) + .def_readwrite("dont_count_slow_torrents", &session_settings::dont_count_slow_torrents) .def_readwrite("auto_manage_interval", &session_settings::auto_manage_interval) .def_readwrite("share_ratio_limit", &session_settings::share_ratio_limit) .def_readwrite("seed_time_ratio_limit", &session_settings::seed_time_ratio_limit) diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index 677bd8b84..8306fc101 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -126,6 +126,8 @@ namespace libtorrent , peer_tos(0) , active_downloads(8) , active_seeds(5) + , active_limit(15) + , dont_count_slow_torrents(true) , auto_manage_interval(30) , share_ratio_limit(2.f) , seed_time_ratio_limit(7.f) @@ -362,6 +364,12 @@ namespace libtorrent // some slots free up. int active_downloads; int active_seeds; + int active_limit; + + // if this is true, torrents that don't have any significant + // transfers are not counted as active when determining which + // auto managed torrents to pause and resume + bool dont_count_slow_torrents; // the number of seconds in between recalculating which // torrents to activate and which ones to queue diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp index 4b597071b..54e832c8a 100644 --- a/libtorrent/include/libtorrent/upnp.hpp +++ b/libtorrent/include/libtorrent/upnp.hpp @@ -69,9 +69,11 @@ class upnp : public intrusive_ptr_base public: upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters); + , portmap_callback_t const& cb, bool ignore_nonrouters, void* state = 0); ~upnp(); + void* drain_state(); + enum protocol_type { none = 0, udp = 1, tcp = 2 }; int add_mapping(protocol_type p, int external_port, int local_port); void delete_mapping(int mapping_index); @@ -226,6 +228,12 @@ private: { return url < rhs.url; } }; + struct upnp_state_t + { + std::vector mappings; + std::set devices; + }; + std::vector m_mappings; std::string const& m_user_agent; diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 342c9bcd4..09da8857c 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -1295,6 +1295,16 @@ namespace aux { } } + namespace + { + bool is_active(torrent* t, session_settings const& s) + { + return !(s.dont_count_slow_torrents + && t->statistics().upload_payload_rate() == 0.f + && t->statistics().download_payload_rate() == 0.f); + } + } + void session_impl::recalculate_auto_managed_torrents() { // these vectors are filled with auto managed torrents @@ -1307,6 +1317,7 @@ namespace aux { // of each kind we're allowed to have active int num_downloaders = settings().active_downloads; int num_seeds = settings().active_seeds; + int hard_limit = settings().active_limit; if (num_downloaders == -1) num_downloaders = (std::numeric_limits::max)(); @@ -1329,11 +1340,15 @@ namespace aux { } else if (!t->is_paused()) { - // this is not an auto managed torrent, - // if it's running, decrease the respective - // counters. - --num_downloaders; - --num_seeds; + --hard_limit; + if (is_active(t, settings())) + { + // this is not an auto managed torrent, + // if it's running and active, decrease the + // counters. + --num_downloaders; + --num_seeds; + } } } @@ -1357,10 +1372,17 @@ namespace aux { , end(downloaders.end()); i != end; ++i) { torrent* t = *i; - if (num_downloaders > 0) + if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0) { + --hard_limit; + continue; + } + + if (num_downloaders > 0 && hard_limit > 0) + { + --hard_limit; if (t->state() != torrent_status::queued_for_checking - && t->state() != torrent_status::checking_files) + && t->state() != torrent_status::checking_files) { --num_downloaders; --num_seeds; @@ -1377,8 +1399,15 @@ namespace aux { , end(seeds.end()); i != end; ++i) { torrent* t = *i; - if (num_seeds > 0) + if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0) { + --hard_limit; + continue; + } + + if (num_seeds > 0 && hard_limit > 0) + { + --hard_limit; --num_downloaders; --num_seeds; if (t->is_paused()) t->resume(); diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 871e31c42..7ab14e12c 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -3420,7 +3420,7 @@ namespace libtorrent session_impl::torrent_map& torrents = m_ses.m_torrents; if (p >= 0 && m_sequence_number == -1) { - int max_seq = 0; + int max_seq = -1; for (session_impl::torrent_map::iterator i = torrents.begin() , end(torrents.end()); i != end; ++i) { diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index b7e05963b..5de9bf156 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -61,7 +61,7 @@ using namespace libtorrent; upnp::upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters) + , portmap_callback_t const& cb, bool ignore_nonrouters, void* state) : m_user_agent(user_agent) , m_callback(cb) , m_retry_count(0) @@ -79,6 +79,26 @@ upnp::upnp(io_service& ios, connection_queue& cc m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc); #endif m_retry_count = 0; + + if (state) + { + upnp_state_t* s = (upnp_state_t*)s; + m_devices.swap(s->devices); + m_mappings.swap(s->mappings); + delete s; + } +} + +void* upnp::drain_state() +{ + upnp_state_t* s = new upnp_state_t; + s->mappings.swap(m_mappings); + + for (std::set::iterator i = m_devices.begin() + , end(m_devices.end()); i != end; ++i) + i->upnp_connection.reset(); + s->devices.swap(m_devices); + return s; } upnp::~upnp()