diff --git a/ChangeLog b/ChangeLog index fc147202f..ce6e267aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ * Add an error category to the tracker sidebar list * Add Find More Plugins button to Plugins preference page * Fix #518 remove header in add torrent dialog to save vertical space + * Add a Cache preferences page to adjust cache settings and examine cache status ==== ConsoleUI ==== * Changed to use curses for a more interactive client diff --git a/deluge/core/core.py b/deluge/core/core.py index fee3b9d48..f41a5a3bb 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -337,6 +337,35 @@ class Core(component.Component): return status + @export + def get_cache_status(self): + """ + Returns a dictionary of the session's cache status. + + :returns: a dict of the cache status + + """ + + status = self.session.get_cache_status() + cache = {} + for attr in dir(status): + if attr.startswith("_"): + continue + cache[attr] = getattr(status, attr) + + # Add in a couple ratios + try: + cache["write_hit_ratio"] = float((cache["blocks_written"] - cache["writes"])) / float(cache["blocks_written"]) + except ZeroDivisionError: + cache["write_hit_ratio"] = 0.0 + + try: + cache["read_hit_ratio"] = float(cache["blocks_read_hit"]) / float(cache["blocks_read"]) + except ZeroDivisionError: + cache["read_hit_ratio"] = 0.0 + + return cache + @export def force_reannounce(self, torrent_ids): log.debug("Forcing reannouncment to: %s", torrent_ids) diff --git a/deluge/core/preferencesmanager.py b/deluge/core/preferencesmanager.py index b2c0d193b..f249d5cc0 100644 --- a/deluge/core/preferencesmanager.py +++ b/deluge/core/preferencesmanager.py @@ -144,7 +144,9 @@ DEFAULT_PREFS = { "random_outgoing_ports": True, "peer_tos": "0x00", "rate_limit_ip_overhead": True, - "geoip_db_location": "/usr/share/GeoIP/GeoIP.dat" + "geoip_db_location": "/usr/share/GeoIP/GeoIP.dat", + "cache_size": 512, + "cache_expiry": 60 } class PreferencesManager(component.Component): @@ -227,6 +229,10 @@ class PreferencesManager(component.Component): self._on_rate_limit_ip_overhead) self.config.register_set_function("geoip_db_location", self._on_geoip_db_location) + self.config.register_set_function("cache_size", + self._on_cache_size) + self.config.register_set_function("cache_expiry", + self._on_cache_expiry) self.config.register_change_callback(self._on_config_value_change) @@ -516,3 +522,13 @@ class PreferencesManager(component.Component): except Exception, e: log.error("Unable to load geoip database!") log.exception(e) + + def _on_cache_size(self, key, value): + log.debug("%s: %s", key, value) + self.settings.cache_size = value + self.session.set_settings(self.settings) + + def _on_cache_expiry(self, key, value): + log.debug("%s: %s", key, value) + self.settings.cache_expiry = 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 964b6ee59..93203d504 100644 --- a/deluge/ui/gtkui/glade/preferences_dialog.glade +++ b/deluge/ui/gtkui/glade/preferences_dialog.glade @@ -4282,6 +4282,554 @@ HTTP W/ Auth tab + + + True + True + automatic + automatic + + + True + queue + none + + + True + vertical + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 10 + 10 + <b><i><big>Cache</big></i></b> + True + + + False + 0 + + + + + True + + + False + 1 + + + + + True + 12 + + + True + vertical + + + True + 0 + none + + + True + 5 + 12 + + + True + 2 + 2 + 5 + + + True + 0 + Cache Size (16 KiB blocks): + + + GTK_FILL + + + + + True + True + The number of seconds from the last cached write to a piece in the write cache, to when it's forcefully flushed to disk. Default is 60 seconds. + 0 + Cache Expiry (seconds): + + + 1 + 2 + GTK_FILL + + + + + True + True + + 1 + 512 0 99999 1 10 10 + True + if-valid + + + 1 + 2 + + + + + + True + True + 5 + + 5 + 1 + 60 1 32000 1 10 10 + + + 1 + 2 + 1 + 2 + + + + + + + + + + True + <b>Settings</b> + True + + + label_item + + + + + False + False + 5 + 0 + + + + + True + 0 + none + + + True + 5 + 12 + + + True + vertical + + + True + 0 + none + + + True + 12 + + + True + 3 + 2 + 5 + + + True + The total number of 16 KiB blocks written to disk since this session was started. + 0 + Blocks Written: + + + GTK_FILL + + + + + True + The total number of write operations performed since this session was started. + 0 + Writes: + + + 1 + 2 + GTK_FILL + + + + + True + The ratio (blocks_written - writes) / blocks_written represents the number of saved write operations per total write operations, i.e. a kind of cache hit ratio for the write cache. + 0 + Write Cache Hit Ratio: + + + 2 + 3 + GTK_FILL + + + + + True + 1 + + + 1 + 2 + + + + + + True + 1 + + + 1 + 2 + 1 + 2 + + + + + + True + 1 + + + 1 + 2 + 2 + 3 + + + + + + + + + + True + <b>Write</b> + True + + + label_item + + + + + 0 + + + + + True + 0 + none + + + True + 12 + + + True + 4 + 2 + 5 + + + True + The number of blocks that were requested from the bittorrent engine (from peers), that were served from disk or cache. + 0 + Blocks Read: + + + GTK_FILL + + + + + True + The number of blocks that were served from cache. + 0 + Blocks Read Hit: + + + 1 + 2 + GTK_FILL + + + + + True + The cache hit ratio for the read cache. + 0 + Read Cache Hit Ratio: + + + 3 + 4 + GTK_FILL + + + + + True + 1 + + + 1 + 2 + + + + + + True + 1 + + + 1 + 2 + 1 + 2 + + + + + + True + 1 + + + 1 + 2 + 3 + 4 + + + + + + True + True + The total number of read operations performed since this session was started. + 0 + Reads: + + + 2 + 3 + GTK_FILL + + + + + True + + + 1 + 2 + 2 + 3 + + + + + + + + + + True + <b>Read</b> + True + + + label_item + + + + + 1 + + + + + True + 0 + none + + + True + 12 + + + True + 2 + 2 + 5 + + + True + The number of 16 KiB blocks currently in the disk cache. This includes both read and write cache. + 0 + Cache Size: + + + GTK_FILL + + + + + True + 0 + Read Cache Size: + + + 1 + 2 + GTK_FILL + + + + + True + 1 + + + 1 + 2 + + + + + + True + 1 + + + 1 + 2 + 1 + 2 + + + + + + + + + + True + <b>Size</b> + True + + + label_item + + + + + 2 + + + + + True + start + + + gtk-refresh + True + True + True + True + + + + False + False + 0 + + + + + 3 + + + + + + + + + True + <b>Status</b> + True + + + label_item + + + + + False + False + 5 + 1 + + + + + + + 2 + + + + + + + + + 9 + + + + + + tab + + True @@ -4687,7 +5235,7 @@ HTTP W/ Auth - 9 + 10 @@ -4696,15 +5244,6 @@ HTTP W/ Auth tab - - - - - - - tab - - True diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py index b6e2328ff..e9f4f83c3 100644 --- a/deluge/ui/gtkui/preferences.py +++ b/deluge/ui/gtkui/preferences.py @@ -69,7 +69,8 @@ class Preferences(component.Component): # Add the default categories i = 0 for category in [_("Downloads"), _("Network"), _("Bandwidth"), _("Interface"), - _("Other"), _("Daemon"), _("Queue"), _("Proxy"), _("Notification"), _("Plugins")]: + _("Other"), _("Daemon"), _("Queue"), _("Proxy"), _("Notification"), + _("Cache"), _("Plugins")]: self.liststore.append([i, category]) i += 1 @@ -188,6 +189,10 @@ class Preferences(component.Component): def _on_get_listen_port(port): self.active_port = port + client.core.get_cache_status().addCallback(_on_get_cache_status) + + def _on_get_cache_status(status): + self.cache_status = status self._show() # This starts a series of client.core requests prior to showing the window @@ -281,6 +286,8 @@ class Preferences(component.Component): "chk_seed_ratio": ("active", self.core_config["stop_seed_at_ratio"]), "spin_share_ratio": ("value", self.core_config["stop_seed_ratio"]), "chk_remove_ratio": ("active", self.core_config["remove_seed_at_ratio"]), + "spin_cache_size": ("value", self.core_config["cache_size"]), + "spin_cache_expiry": ("value", self.core_config["cache_expiry"]) } # Add proxy stuff for t in ("peer", "web_seed", "tracker", "dht"): @@ -409,6 +416,8 @@ class Preferences(component.Component): "spin_share_ratio_limit", "spin_seed_time_ratio_limit", "spin_seed_time_limit", + "spin_cache_size", + "spin_cache_expiry" ] for t in ("peer", "web_seed", "tracker", "dht"): core_widget_list.append("spin_proxy_port_%s" % t) @@ -478,6 +487,9 @@ class Preferences(component.Component): elif self.gtkui_config["ntf_security"] == 'TLS': self.glade.get_widget("rad_ntf_tls").set_active(True) + ## Cache tab ## + self.__update_cache_status() + ## Plugins tab ## all_plugins = self.all_plugins enabled_plugins = self.enabled_plugins @@ -754,6 +766,25 @@ class Preferences(component.Component): def hide(self): self.pref_dialog.hide() + def __update_cache_status(self): + # Updates the cache status labels with the info in the dict + for widget in self.glade.get_widget_prefix("label_cache_"): + key = widget.get_name()[len("label_cache_"):] + value = self.cache_status[key] + if type(value) == float: + value = "%.2f" % value + else: + value = str(value) + + widget.set_text(value) + + def on_button_cache_refresh_clicked(self, widget): + def on_get_cache_status(status): + self.cache_status = status + self.__update_cache_status() + + client.core.get_cache_status().addCallback(on_get_cache_status) + def on_pref_dialog_delete_event(self, widget, event): self.hide() return True