diff --git a/deluge/ui/client.py b/deluge/ui/client.py index 2abcd0a1e..4f86089e2 100644 --- a/deluge/ui/client.py +++ b/deluge/ui/client.py @@ -134,6 +134,9 @@ class DelugeRPCProtocol(Protocol): self.__buffer = None while data: + # Increase the byte counter + self.factory.bytes_recv += len(data) + dobj = zlib.decompressobj() try: request = rencode.loads(dobj.decompress(data)) @@ -196,7 +199,9 @@ class DelugeRPCProtocol(Protocol): self.__rpc_requests[request.request_id] = request #log.debug("Sending RPCRequest %s: %s", request.request_id, request) # Send the request in a tuple because multiple requests can be sent at once - self.transport.write(zlib.compress(rencode.dumps((request.format_message(),)))) + data = zlib.compress(rencode.dumps((request.format_message(),))) + self.factory.bytes_sent += len(data) + self.transport.write(data) class DelugeRPCClientFactory(ClientFactory): protocol = DelugeRPCProtocol @@ -204,6 +209,9 @@ class DelugeRPCClientFactory(ClientFactory): def __init__(self, daemon, event_handlers): self.daemon = daemon self.event_handlers = event_handlers + + self.bytes_recv = 0 + self.bytes_sent = 0 def startedConnecting(self, connector): log.info("Connecting to daemon at %s:%s..", connector.host, connector.port) @@ -315,7 +323,9 @@ class DaemonSSLProxy(DaemonProxy): Pops a Deffered object. This is generally called once we receive the reply we were waiting on from the server. - :param request_id: int, the request_id of the Deferred to pop + :param request_id: the request_id of the Deferred to pop + :type request_id: int + """ return self.__deferred.pop(request_id) @@ -324,10 +334,12 @@ class DaemonSSLProxy(DaemonProxy): Registers a handler function to be called when `:param:event` is received from the daemon. - :param event: str, the name of the event to handle - :param handler: function, the function to be called when `:param:event` + :param event: the name of the event to handle + :type event: str + :param handler: the function to be called when `:param:event` is emitted from the daemon - + :type handler: function + """ if event not in self.__factory.event_handlers: # This is a new event to handle, so we need to tell the daemon @@ -344,8 +356,10 @@ class DaemonSSLProxy(DaemonProxy): """ Deregisters a event handler. - :param event: str, the name of the event - :param handler: function, the function registered + :param event: the name of the event + :type event: str + :param handler: the function registered + :type handler: function """ if event in self.__factory.event_handlers and handler in self.__factory.event_handlers[event]: @@ -402,6 +416,12 @@ class DaemonSSLProxy(DaemonProxy): """ self.disconnect_callback = cb + def get_bytes_recv(self): + return self.__factory.bytes_recv + + def get_bytes_sent(self): + return self.__factory.bytes_sent + class DaemonClassicProxy(DaemonProxy): def __init__(self, event_handlers={}): import deluge.core.daemon @@ -437,10 +457,12 @@ class DaemonClassicProxy(DaemonProxy): Registers a handler function to be called when `:param:event` is received from the daemon. - :param event: str, the name of the event to handle - :param handler: function, the function to be called when `:param:event` + :param event: the name of the event to handle + :type event: str + :param handler: the function to be called when `:param:event` is emitted from the daemon - + :type handler: function + """ self.__daemon.core.eventmanager.register_event_handler(event, handler) @@ -448,8 +470,10 @@ class DaemonClassicProxy(DaemonProxy): """ Deregisters a event handler. - :param event: str, the name of the event - :param handler: function, the function registered + :param event: the name of the event + :type event: str + :param handler: the function registered + :type handler: function """ self.__daemon.core.eventmanager.deregister_event_handler(event, handler) @@ -648,5 +672,23 @@ class Client(object): if self.disconnect_callback: self.disconnect_callback() + def get_bytes_recv(self): + """ + Returns the number of bytes received from the daemon. + + :returns: the number of bytes received + :rtype: int + """ + return self._daemon_proxy.get_bytes_recv() + + def get_bytes_sent(self): + """ + Returns the number of bytes sent to the daemon. + + :returns: the number of bytes sent + :rtype: int + """ + return self._daemon_proxy.get_bytes_sent() + # This is the object clients will use client = Client() diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py index 255622afb..182ec8a02 100644 --- a/deluge/ui/gtkui/gtkui.py +++ b/deluge/ui/gtkui/gtkui.py @@ -32,8 +32,6 @@ # statement from all source files in the program, then also delete it here. # # - - from deluge.log import LOG as log # Install the twisted reactor @@ -160,6 +158,7 @@ DEFAULT_PREFS = { class GtkUI(object): def __init__(self, args): + self.daemon_bps = (0,0,0) # Setup signals try: import gnome.ui @@ -227,6 +226,10 @@ class GtkUI(object): # Show the connection manager self.connectionmanager = ConnectionManager() + from twisted.internet.task import LoopingCall + rpc_stats = LoopingCall(self.print_rpc_stats) + rpc_stats.start(10) + reactor.callWhenRunning(self._on_reactor_start) # Start the gtk main loop gtk.gdk.threads_enter() @@ -256,6 +259,25 @@ class GtkUI(object): # Make sure the config is saved. self.config.save() + def print_rpc_stats(self): + import time + try: + recv = client.get_bytes_recv() + sent = client.get_bytes_sent() + except AttributeError: + return + + log.debug("sent: %s recv: %s", deluge.common.fsize(sent), deluge.common.fsize(recv)) + t = time.time() + delta_time = t - self.daemon_bps[0] + delta_sent = sent - self.daemon_bps[1] + delta_recv = recv - self.daemon_bps[2] + + sent_rate = deluge.common.fspeed(float(delta_sent) / float(delta_time)) + recv_rate = deluge.common.fspeed(float(delta_recv) / float(delta_time)) + log.debug("sent rate: %s recv rate: %s", sent_rate, recv_rate) + self.daemon_bps = (t, sent, recv) + def _on_reactor_start(self): log.debug("_on_reactor_start") self.mainwindow.first_show()