Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- # # Copyright (C) 2010 Andrew Resch <andrewresch@gmail.com> # # This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with # the additional special exception to link portions of this program with the OpenSSL library. # See LICENSE for more details. #
""" The SessionProxy component is used to cache session information client-side to reduce the number of RPCs needed to provide a rich user interface.
It will query the Core for only changes in the status of the torrents and will try to satisfy client requests from the cache.
"""
# Set the cache time in seconds # This is how long data will be valid before re-fetching from the core
# Hold the torrents' status.. {torrent_id: [time, {status_dict}], ...}
# Holds the time of the last key update.. {torrent_id: {key1, time, ...}, ...}
# Let's at least store the torrent ids with empty statuses # so that upcoming queries or status updates don't throw errors.
client.deregister_event_handler("TorrentStateChangedEvent", self.on_torrent_state_changed) client.deregister_event_handler("TorrentRemovedEvent", self.on_torrent_removed) client.deregister_event_handler("TorrentAddedEvent", self.on_torrent_added) self.torrents = {}
""" Creates a status dict from the cache.
:param torrent_ids: the torrent_ids :type torrent_ids: list of strings :param keys: the status keys :type keys: list of strings
:returns: a dict with the status information for the *torrent_ids* :rtype: dict
"""
# Have to remove the keys that weren't requested # If the number of keys are equal they are the same keys # so we use the cached diff of the keys we need to remove else: # Not the same keys so create a new diff # Update the cached diff
# Usually there are no keys to remove, so it's cheaper with # this if-test than a for-loop with no iterations. else: sd[torrent_id] = dict(self.torrents[torrent_id][1]) except KeyError: continue
""" Get a status dict for one torrent.
:param torrent_id: the torrent_id :type torrent_id: string :param keys: the status keys :type keys: list of strings
:returns: a dict of status information :rtype: dict
""" # Keep track of keys we need to request from the core
self.create_status_dict([torrent_id], keys)[torrent_id] ) else:
else: d = client.core.get_torrent_status(torrent_id, keys, True)
def on_status(result): if result: t = time.time() self.torrents[torrent_id] = (t, result) self.cache_times[torrent_id] = {} for key in result: self.cache_times[torrent_id][key] = t
return result return d.addCallback(on_status)
""" Get a dict of torrent statuses.
The filter can take 2 keys, *state* and *id*. The state filter can be one of the torrent states or the special one *Active*. The *id* key is simply a list of torrent_ids.
:param filter_dict: the filter used for this query :type filter_dict: dict :param keys: the status keys :type keys: list of strings
:returns: a dict of torrent_ids and their status dicts :rtype: dict
""" # Helper functions and callbacks --------------------------------------- # Update the internal torrent status dict with the update values except KeyError: # The torrent was removed continue
# Create the status dict torrent_ids = result.keys()
else: # We need to check if a key is expired
# -----------------------------------------------------------------------
# This means we want all the torrents status # We get a list of any torrent_ids with expired status dicts to_fetch = find_torrents_to_fetch(self.torrents.keys()) if to_fetch: d = client.core.get_torrents_status({"id": to_fetch}, keys, True) return d.addCallback(on_status, self.torrents.keys(), keys)
# Don't need to fetch anything return maybeDeferred(self.create_status_dict, self.torrents.keys(), keys)
# At this point we should have a filter with just "id" in it else: # Don't need to fetch anything, so just return data from the cache return maybeDeferred(self.create_status_dict, filter_dict["id"], keys) else: # This is a keyworded filter so lets just pass it onto the core # XXX: Add more caching here. d = client.core.get_torrents_status(filter_dict, keys, True) return d.addCallback(on_status, None, keys)
if torrent_id in self.torrents: self.torrents[torrent_id][1].setdefault("state", state) self.cache_times.setdefault(torrent_id, {}).update(state=time.time())
self.torrents[torrent_id] = [time.time() - self.cache_time - 1, {}] self.cache_times[torrent_id] = {}
def on_status(status): self.torrents[torrent_id][1].update(status) t = time.time() for key in status: self.cache_times[torrent_id][key] = t client.core.get_torrent_status(torrent_id, []).addCallback(on_status)
if torrent_id in self.torrents: del self.torrents[torrent_id] del self.cache_times[torrent_id] |