SF.net SVN: fclient: [40] trunk/fclient
Status: Pre-Alpha
Brought to you by:
jurner
From: <jU...@us...> - 2007-11-04 17:28:44
|
Revision: 40 http://fclient.svn.sourceforge.net/fclient/?rev=40&view=rev Author: jUrner Date: 2007-11-04 09:28:46 -0800 (Sun, 04 Nov 2007) Log Message: ----------- added support to handle multiple clients Added Paths: ----------- trunk/fclient/fclient_ui/ trunk/fclient/fclient_ui/__init__.py trunk/fclient/fclient_ui/fcp_client_manager.py Added: trunk/fclient/fclient_ui/__init__.py =================================================================== --- trunk/fclient/fclient_ui/__init__.py (rev 0) +++ trunk/fclient/fclient_ui/__init__.py 2007-11-04 17:28:46 UTC (rev 40) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient_ui/fcp_client_manager.py =================================================================== --- trunk/fclient/fclient_ui/fcp_client_manager.py (rev 0) +++ trunk/fclient/fclient_ui/fcp_client_manager.py 2007-11-04 17:28:46 UTC (rev 40) @@ -0,0 +1,299 @@ + + +from PyQt4 import QtCore +#************************************************************************************** +# +#************************************************************************************** +class Priority(object): + """Priority""" + __slots__ = ('name', 'value') + + + def __init__(self, name, value): + """ + @param name: (str) name of the priority + @param value: (int) value of the priority + """ + self.name = name + self.value = value + def __int__(self): return self.value + def __long__(self): return self.__int__() + +#************************************************************************************** +# +#************************************************************************************** +class Priorities(QtCore.QObject): + """Class handling poll priorities + + >>> p = Priorities(None) + >>> priority = p['Highest'] + >>> priority.name + 'Highest' + >>> int(priority) + 0 + + >>> p['Highest'] = 33 + >>> int(priority) + 33 + + >>> for translatedName, priority in p.listPriorityNames(): priority.name + 'Highest' + 'High' + 'Normal' + 'Low' + 'Lowest' + """ + + # cheat a bit to get dynamic translation working + def trUtf8(self, what): return what + + + def __init__(self, parent): + """ + @param parent: (QObject) parent or None + @note: supported priorities are: 'Highest', 'High', 'Normal', 'Low', 'Lowest' + """ + QtCore.QObject.__init__(self, parent) + + self._values = ( + Priority(self.trUtf8('Highest'), 0), + Priority(self.trUtf8('High'), 100), + Priority(self.trUtf8('Normal'), 300), + Priority(self.trUtf8('Low'), 600), + Priority(self.trUtf8('Lowest'), 1000), + ) + self._valuesDict = {} + for priority in self._values: + self._valuesDict[priority.name] = priority + + + def __getitem__(self, name): + """Returns the a priority given its name""" + return self._valuesDict[name] + + + def __setitem__(self, name, value): + """Sets the value of a priority + @param name: (str) name of the priority + @param value: (int) value in milisecomds + """ + self._valuesDict[name].value = value + + + def listPriorityNames(self): + """Returns a list containing all priorities + @return: (list) [(QString) translatedName, (Priority) priority] + """ + out = [] + for priority in self._values: + out.append( (QtCore.QObject.trUtf8(self, priority.name), priority) ) + return out + +#***************************************************************************** +# +#***************************************************************************** +class FcpClientManager(QtCore.QObject): + """Manager to handle multiple Fcp clients + """ + + + def __init__(self, parent): + """ + @param parent: (QObject) parent or None + @ivar fcpClients: dict mapping connection names to FcpClients + @ivar priorities: L{Priorities} the manager supports + """ + QtCore.QObject.__init__(self, parent) + + self.fcpClients = {} + self.priorities = Priorities(self) + + + def stopFcpClient(self, name): #TODO: name of client or client??? + """Stops a FcpClient + @name: (str) connection name of the client to stop + @note: the client is not closed in the call. To close the connection call FcpClient.close() + """ + handler = self.fcpClients.pop(name) + handler.stop() + + + def newFcpClient(self, + name, + eventConnectedHandler, + connectPriority=None, + pollPriority=None, + ): + """Creates a new Fcp client + @param name: (str) unique connection name + @param eventConnectedHandler: method that handles FcpClient.EventConnected + @param connectPriority: (L{Priority}) priority when establishing node connection + @param pollPriority: (L{Priority}) runtime priority + @return: (FcpClient) instance + + @note: the eventConnectedHandler handler passed is automatically connected + to FcpClient.EventConnected. No need to connect to receive events. + """ + if name in self.fcpClients: + raise ValueError('Fcp client already exists: %r' % name) + + # some magic here to determine the client version to use + from fclient_lib.fcp.fcp2_0 import FcpClient + fcpClient = FcpClient( + connectionName=name, + #verbosity=FcpClient.Verbosity.Debug, + ) + fcpClient.events.ClientConnected += eventConnectedHandler + handler = FcpClientHandler( + fcpClient, + self.handleFcpClientDisconnected, + connectPriority if connectPriority is not None else self.priorities['Normal'], + pollPriority if pollPriority is not None else self.priorities['Normal'], + ) + self.fcpClients[name] = handler + fcpClient.events.ClientDisconnected += handler.handleFcpClientDisconnected + handler.connect() + return fcpClient + + + def setPriority(self, name, connectPriority=None, pollPriority=None): + """Sets priorities of a FcpClient + @param connectPriority: (L{Priority}) priority when establishing node connection + @param pollPriority: (L{Priority}) runtime priority + """ + handler = self.fcpClients[name] + if connectPriority is not None: + handler.setConnectPriority(connectPriority) + if pollPriority is not None: + handler.setPollPriority(pollPriority) + + + def handleFcpClientDisconnected(self, handler, params): + """Handles FcpClient.EventDisconnect""" + + disconnectReason = params['DisconnectReason'] + fcpClient = handler.fcpClient + + # see how to handle the cases + if disconnectReason == fcpClient.DisconnectReason.Shutdown: + handler.stop() + + elif disconnectReason == fcpClient.DisconnectReason.SocketDied: + # 1. wait some time, cos more alerts may come in + # 2. inform user + # 3. reconnect if desired + pass + + elif disconnectReason == fcpClient.DisconnectReason.ConnectFailed: + # 1. wait some time, cos more alerts may come in + # 2. inform user + # 3. reconnect if desired + pass + + else: + raise ValueError('Unknown disconnect reason: %r' % disconnectReason) + + + +#************************************************************************************** +# +#************************************************************************************** +class FcpClientHandler(object): + """Handles one single FcpClient + """ + + + def __init__(self, fcpClient, handleFcpClientDisconnected, connectPriority, pollPriority): + """ + @param fcpClient: FcpClient to handle + @param handleFcpClientDisconnected: handler to call when the client disconnects + @param connectPriority: (L{Priority}) priority when establishing node connection + @param pollPriority: (L{Priority}) runtime priority + """ + self.fcpClient = fcpClient + self.handleFcpClientDisconnected = handleFcpClientDisconnected + self.connectMethod = fcpClient.connect() + + self.connectPriority = connectPriority + self.pollPriority = pollPriority + + self.connectTimer = QtCore.QTimer() + QtCore.QObject.connect( + self.connectTimer, + QtCore.SIGNAL('timeout()'), + self.handleConnect + ) + + self.pollTimer = QtCore.QTimer() + QtCore.QObject.connect( + self.pollTimer, + QtCore.SIGNAL('timeout()'), + self.fcpClient.next + ) + + + def connect(self): + """Establishes the connection from the client to the node""" + self.stop() + self.connectTimer.start(int(self.connectPriority)) + + + def start(self): + """Starts polling the FcpClient""" + self.pollTimer.start(int(self.pollPriority)) + + + def stop(self): + """Stops polling the FcpClient""" + self.connectTimer.stop() + self.pollTimer.stop() + + + def setPollPriority(self, priority): + """Adjusts the poll priority of the FcpClient + @param priority: L{Priority} + """ + isActive = self.pollTimer.isActive() + self.pollTimer.stop() + if isActive: + self.pollTimer.start(int(priority)) + self.pollPriority = priority + + + def setConnectPriority(self, priority): + """Adjusts the priority wich is used to establish a connection to the node + @param priority: L{Priority} + """ + isActive = self.connectTimer.isActive() + self.connectTimer.stop() + if isActive: + self.connectTimer.start(int(priority)) + self.connectPriority = priority + + + def handleFcpClientDisconnected(self, params): + """Handles FcpClient.EventDisconnect""" + self.stop() + self.handleFcpClientDisconnected(self, params) + + + def handleConnect(self): + """Handles establishing of the node connection""" + self.connectTimer.stop() + try: + result = self.connectMethod.next() + if result is not None: + self.nodeHello = result + self.pollTimer.start(int(self.pollPriority)) + return + except StopIteration: + return + self.connectTimer.start(int(self.connectPriority)) + +#****************************************************************************************** +# +#****************************************************************************************** +if __name__ == '__main__': + import doctest + doctest.testmod() + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |