[Neo-report] r2035 vincent - in /trunk/neo: connection.py tests/testConnection.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed Apr 28 15:27:54 CEST 2010
Author: vincent
Date: Wed Apr 28 15:27:51 2010
New Revision: 2035
Log:
Allow a handler to send requests.
When a handler sends a request, always queue the response for handling
within the same handler, possibly delaying further a pending handler
switch.
This is for example required to properly complete identification between
master nodes, as the connecting master node might exit election phase
before receiving peer's AnswerPrimary when peer happens to be the primary.
Modified:
trunk/neo/connection.py
trunk/neo/tests/testConnection.py
Modified: trunk/neo/connection.py
==============================================================================
--- trunk/neo/connection.py [iso-8859-1] (original)
+++ trunk/neo/connection.py [iso-8859-1] Wed Apr 28 15:27:51 2010
@@ -77,6 +77,7 @@
self._connection = connection
# pending handlers and related requests
self._pending = [[{}, handler]]
+ self._is_handling = False
def clear(self):
handler = self._pending[0][1]
@@ -92,8 +93,14 @@
def emit(self, request, timeout):
# register the request in the current handler
_pending = self._pending
- assert len(_pending) == 1 or _pending[0][0]
- (request_dict, _) = _pending[-1]
+ if self._is_handling:
+ # If this is called while handling a packet, the response is to
+ # be excpected for the current handler...
+ (request_dict, _) = _pending[0]
+ else:
+ # ...otherwise, queue for for the latest handler
+ assert len(_pending) == 1 or _pending[0][0]
+ (request_dict, _) = _pending[-1]
msg_id = request.getId()
answer_class = request.getAnswerClass()
assert answer_class is not None, "Not a request"
@@ -112,8 +119,16 @@
result = None
return result
- @profiler_decorator
def handle(self, packet):
+ assert not self._is_handling
+ self._is_handling = True
+ try:
+ self._handle(packet)
+ finally:
+ self._is_handling = False
+
+ @profiler_decorator
+ def _handle(self, packet):
assert len(self._pending) == 1 or self._pending[0][0]
PACKET_LOGGER.dispatch(self._connection, packet, 'from')
msg_id = packet.getId()
Modified: trunk/neo/tests/testConnection.py
==============================================================================
--- trunk/neo/tests/testConnection.py [iso-8859-1] (original)
+++ trunk/neo/tests/testConnection.py [iso-8859-1] Wed Apr 28 15:27:51 2010
@@ -851,10 +851,30 @@
self.assertFalse(self._handlers.isPending())
def testEmit(self):
+ # First case, emit is called outside of a handler
self.assertFalse(self._handlers.isPending())
request = self._makeRequest(1)
self._handlers.emit(request, 0)
self.assertTrue(self._handlers.isPending())
+ # Second case, emit is called from inside a handler with a pending
+ # handler change.
+ new_handler = self._makeHandler()
+ self._handlers.setHandler(new_handler)
+ self._checkCurrentHandler(self._handler)
+ call_tracker = []
+ def packetReceived(conn, packet):
+ self._handlers.emit(self._makeRequest(2), 0)
+ call_tracker.append(True)
+ self._handler.packetReceived = packetReceived
+ self._handlers.handle(self._makeAnswer(1))
+ self.assertEqual(call_tracker, [True])
+ # Effective handler must not have changed (new request is blocking
+ # it)
+ self._checkCurrentHandler(self._handler)
+ # Handling the next response will cause the handler to change
+ delattr(self._handler, 'packetReceived')
+ self._handlers.handle(self._makeAnswer(2))
+ self._checkCurrentHandler(new_handler)
def testHandleNotification(self):
# handle with current handler
More information about the Neo-report
mailing list