Improvements and bug fixes

This commit is contained in:
bendikro 2013-01-14 22:55:06 +01:00
parent 5cd86aa5bc
commit 0f67dc168b
7 changed files with 138 additions and 138 deletions

View File

@ -427,12 +427,9 @@ class Core(component.Component):
for torrent_id in torrent_ids:
self.torrentmanager[torrent_id].resume()
def create_torrent_status(self, torrent_id, torrent_keys, plugin_keys, diff=False, update=True):
def create_torrent_status(self, torrent_id, torrent_keys, plugin_keys, diff=False, update=False):
try:
if update:
status = self.torrentmanager[torrent_id].get_status(torrent_keys, diff)
else:
status = self.torrentmanager[torrent_id].create_status_dict(torrent_keys, diff)
status = self.torrentmanager[torrent_id].get_status(torrent_keys, diff, update=update)
except KeyError:
import traceback
traceback.print_exc()

View File

@ -106,14 +106,14 @@ def tracker_error_filter(torrent_ids, values):
# If this is a tracker_host, then we need to filter on it
if values[0] != "Error":
for torrent_id in torrent_ids:
if values[0] == tm[torrent_id].create_status_dict(["tracker_host"])["tracker_host"]:
if values[0] == tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
filtered_torrent_ids.append(torrent_id)
return filtered_torrent_ids
# Check all the torrent's tracker_status for 'Error:' and only return torrent_ids
# that have this substring in their tracker_status
for torrent_id in torrent_ids:
if _("Error") + ":" in tm[torrent_id].create_status_dict(["tracker_host"])["tracker_host"]:
if _("Error") + ":" in tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
filtered_torrent_ids.append(torrent_id)
return filtered_torrent_ids
@ -192,7 +192,7 @@ class FilterManager(component.Component):
#leftover filter arguments:
#default filter on status fields.
for torrent_id in list(torrent_ids):
status = self.torrents[torrent_id].create_status_dict(filter_dict.keys()) #status={key:value}
status = self.torrents[torrent_id].get_status(filter_dict.keys()) #status={key:value}
for field, values in filter_dict.iteritems():
if (not status[field] in values) and torrent_id in torrent_ids:
torrent_ids.remove(torrent_id)
@ -213,7 +213,7 @@ class FilterManager(component.Component):
items = dict((field, self.tree_fields[field]()) for field in tree_keys)
for torrent_id in list(torrent_ids):
status = self.core.create_torrent_status(torrent_id, torrent_keys, plugin_keys, update=False) #status={key:value}
status = self.core.create_torrent_status(torrent_id, torrent_keys, plugin_keys) #status={key:value}
for field in tree_keys:
value = status[field]
items[field][value] = items[field].get(value, 0) + 1
@ -261,7 +261,7 @@ class FilterManager(component.Component):
def filter_state_active(self, torrent_ids):
for torrent_id in list(torrent_ids):
status = self.torrents[torrent_id].create_status_dict(["download_payload_rate", "upload_payload_rate"])
status = self.torrents[torrent_id].get_status(["download_payload_rate", "upload_payload_rate"])
if status["download_payload_rate"] or status["upload_payload_rate"]:
pass #ok
else:

View File

@ -224,6 +224,9 @@ class Torrent(object):
self.forcing_recheck = False
self.forcing_recheck_paused = False
self.update_status(self.handle.status())
self._create_status_funcs()
if log.isEnabledFor(logging.DEBUG):
log.debug("Torrent object created.")
@ -407,10 +410,9 @@ class Torrent(object):
self.update_state()
break
# Do we really need this?
#self.options["file_priorities"] = self.handle.file_priorities()
#if self.options["file_priorities"] != list(file_priorities):
# log.warning("File priorities were not set for this torrent")
# In case values in file_priorities were faulty (old state?)
# we make sure the stored options are in sync
self.options["file_priorities"] = self.handle.file_priorities()
# Set the first/last priorities if needed
if self.options["prioritize_first_last_pieces"]:
@ -489,12 +491,12 @@ class Torrent(object):
# This is an error'd torrent
self.state = "Error"
self.set_status_message(status.error)
if self.handle_is_paused:
if handle_is_paused:
self.handle.auto_managed(False)
return
if ltstate == LTSTATE["Queued"] or ltstate == LTSTATE["Checking"]:
if self.handle_is_paused:
if handle_is_paused:
self.state = "Paused"
else:
self.state = "Checking"
@ -668,7 +670,7 @@ class Torrent(object):
self.calculate_last_seen_complete()
return self._last_seen_complete
def get_status(self, keys, diff=False):
def get_status(self, keys, diff=False, update=False):
"""
Returns the status of the torrent based on the keys provided
@ -677,22 +679,62 @@ class Torrent(object):
:param diff: if True, will return a diff of the changes since the last
call to get_status based on the session_id
:type diff: bool
:param update: if True, the status will be updated from libtorrent
if False, the cached values will be returned
:type update: bool
:returns: a dictionary of the status keys and their values
:rtype: dict
"""
status = self.handle.status()
self.update_status(status)
return self.create_status_dict(keys)
if update:
self.update_status(self.handle.status())
if not keys:
keys = self.status_funcs.keys()
status_dict = {}
for key in keys:
status_dict[key] = self.status_funcs[key]()
if diff:
session_id = self.rpcserver.get_session_id()
if session_id in self.prev_status:
# We have a previous status dict, so lets make a diff
status_diff = {}
for key, value in status_dict.items():
if key in self.prev_status[session_id]:
if value != self.prev_status[session_id][key]:
status_diff[key] = value
else:
status_diff[key] = value
self.prev_status[session_id] = status_dict
return status_diff
self.prev_status[session_id] = status_dict
return status_dict
return status_dict
def update_status(self, status):
"""
Updates the cached status.
:param status: a libtorrent status
:type status: libtorrent.torrent_status
"""
#import datetime
#print datetime.datetime.now().strftime("%H:%M:%S.%f"),
#print " update_status"
self.status = status
if self.torrent_info is None and self.has_metadata():
self.torrent_info = self.handle.get_torrent_info()
if not self.status_funcs:
def _create_status_funcs(self):
#if you add a key here->add it to core.py STATUS_KEYS too.
self.status_funcs = {
"active_time": lambda: self.status.active_time,
@ -763,36 +805,6 @@ class Torrent(object):
"total_size": self.ti_total_size,
}
def create_status_dict(self, keys, diff=False):
# Create the desired status dictionary and return it
status_dict = {}
if not keys:
keys = self.status_funcs.keys()
for key in keys:
status_dict[key] = self.status_funcs[key]()
session_id = self.rpcserver.get_session_id()
if diff:
if session_id in self.prev_status:
# We have a previous status dict, so lets make a diff
status_diff = {}
for key, value in status_dict.items():
if key in self.prev_status[session_id]:
if value != self.prev_status[session_id][key]:
status_diff[key] = value
else:
status_diff[key] = value
self.prev_status[session_id] = status_dict
return status_diff
self.prev_status[session_id] = status_dict
return status_dict
return status_dict
def ti_comment(self):
if self.has_metadata():
try:

View File

@ -161,7 +161,7 @@ class TorrentManager(component.Component):
self.torrents_status_requests = []
self.status_dict = {}
self.state_update_alert_start = None
self.last_state_update_alert_ts = 0
# Register set functions
self.config.register_set_function("max_connections_per_torrent",
@ -207,7 +207,7 @@ class TorrentManager(component.Component):
self.alerts.register_handler("file_completed_alert",
self.on_alert_file_completed)
self.alerts.register_handler("state_update_alert",
self.state_update_alert)
self.on_alert_state_update)
def start(self):
# Get the pluginmanager reference
@ -666,9 +666,7 @@ class TorrentManager(component.Component):
for s in state.torrents:
setattr(s, attr, getattr(state_tmp, attr, None))
except Exception, e:
log.warning("Unable to update state file to a compatible version: %s", e)
import traceback
print traceback.format_exc()
log.exception("Unable to update state file to a compatible version: %s", e)
# Reorder the state.torrents list to add torrents in the correct queue
# order.
@ -1138,9 +1136,9 @@ class TorrentManager(component.Component):
torrent_keys = list(set(keys) - set(leftover_keys))
return torrent_keys, leftover_keys
def state_update_alert(self, alert):
self.state_update_alert_start = time.time()
def on_alert_state_update(self, alert):
log.debug("on_status_notification: %s", alert.message())
self.last_state_update_alert_ts = time.time()
for s in alert.status:
torrent_id = str(s.info_hash)
@ -1150,6 +1148,9 @@ class TorrentManager(component.Component):
self.handle_torrents_status_callback(self.torrents_status_requests.pop())
def handle_torrents_status_callback(self, status_request):
"""
Builds the status dictionary with the values from the Torrent.
"""
d, torrent_ids, keys, diff = status_request
status_dict = {}.fromkeys(torrent_ids)
torrent_keys, plugin_keys = self.separate_keys(keys, torrent_ids)
@ -1162,21 +1163,32 @@ class TorrentManager(component.Component):
print "Missing torrent id:", torrent_id
del status_dict[torrent_id]
else:
status_dict[torrent_id] = self.torrents[torrent_id].create_status_dict(torrent_keys, diff)
status_dict[torrent_id] = self.torrents[torrent_id].get_status(torrent_keys, diff)
self.status_dict = status_dict
d.callback((status_dict, plugin_keys))
def torrents_status_update(self, torrent_ids, keys, diff=False):
"""
returns all torrents , optionally filtered by filter_dict.
If the torrent states were updated recently (less than two seconds ago,
returns status dict for the supplied torrent_ids async
If the torrent states were updated recently (less than 1.5 seconds ago,
post_torrent_updates is not called. Instead the cached state is used.
:param torrent_ids: the torrent IDs to get the status on
:type torrent_ids: list of str
:param keys: the keys to get the status on
:type keys: list of str
:param diff: if True, will return a diff of the changes since the last
call to get_status based on the session_id
:type diff: bool
:returns: a status dictionary for the equested torrents.
:rtype: dict
"""
d = Deferred()
now = time.time()
# Less than two seconds since last time the torrent states were updated
if self.state_update_alert_start and \
(now - self.state_update_alert_start) < 2:
# If last update was recent, use cached data instead of request updates from libtorrent
if (now - self.last_state_update_alert_ts) < 1.5:
reactor.callLater(0, self.handle_torrents_status_callback, (d, torrent_ids, keys, diff))
else:
# Ask libtorrent for status update

View File

@ -202,8 +202,6 @@ class StatusBar(component.Component):
# Get some config values
client.core.get_config_values(["max_connections_global", "max_download_speed",
"max_upload_speed", "dht"]).addCallback(update_config_values)
# Called from update a few milliseconds later
#self.send_status_request()
def stop(self):
# When stopped, we just show the not connected thingy

View File

@ -176,8 +176,6 @@ class SystemTray(component.Component):
self._on_max_download_speed(configs["max_download_speed"])
self._on_max_upload_speed(configs["max_upload_speed"])
client.core.get_config_values(["max_download_speed", "max_upload_speed"]).addCallback(update_config_values)
# This is called from update a few milliseconds later, so this line can be deleted
#self.send_status_request()
def start(self):
self.__start()

View File

@ -47,10 +47,8 @@ class SessionProxy(component.Component):
The SessionProxy component is used to cache session information client-side
to reduce the number of RPCs needed to provide a rich user interface.
On start-up it will query the Core for a full status of all the torrents in
the session. After that point, it will query the Core for only changes in
the status of the torrents and will try to satisfy client requests from the
cache.
It will query the Core for only changes in the status of the torrents
and will try to satisfy client requests from the cache.
"""
def __init__(self):
@ -78,21 +76,6 @@ class SessionProxy(component.Component):
# so that upcoming queries or status updates don't throw errors.
self.torrents.setdefault(torrent_id, [time.time(), {}])
self.cache_times.setdefault(torrent_id, {})
# These initial keys are the ones used for the visible columns(by
# default) on the GTK UI torrent view. If either the console-ui
# or the web-ui needs additional keys, add them here;
# There's NO need to fetch every bit of status information from
# core if it's not going to be used. Additional status fields
# will be queried later, for example, when viewing the status tab
# of a torrent.
#inital_keys = [
# 'queue', 'state', 'name', 'total_wanted', 'progress', 'state',
# 'download_payload_rate', 'upload_payload_rate', 'eta', 'owner'
#]
#The the torrents status will be requested by torrentview, so this
#only causes a second request for the same data withing a few miliseconds
#self.get_torrents_status({'id': torrent_ids}, inital_keys)
return client.core.get_session_state().addCallback(on_get_session_state)
def stop(self):