[Neo-report] r2222 vincent - in /trunk/neo: connection.py tests/testConnection.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Aug 24 18:02:19 CEST 2010
Author: vincent
Date: Tue Aug 24 18:02:19 2010
New Revision: 2222
Log:
Don't store connection on instances.
This causes garbage collection problems, as BaseConnection instances also
hold a reference to HandlerSwitcher instance. It is unclear why it fails,
as microbenchs show this should not be a problem for gc.
Also, move loggers out of HandlerSwitcher.setHandler to avoid passing a
connection parameter just for them.
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] Tue Aug 24 18:02:19 2010
@@ -84,8 +84,7 @@ class HandlerSwitcher(object):
_next_timeout_msg_id = None
_next_on_timeout = None
- def __init__(self, connection, handler):
- self._connection = connection
+ def __init__(self, handler):
# pending handlers and related requests
self._pending = [[{}, handler]]
self._is_handling = False
@@ -127,14 +126,14 @@ class HandlerSwitcher(object):
self._next_on_timeout = on_timeout
request_dict[msg_id] = (answer_class, timeout, on_timeout)
- def checkTimeout(self, t):
+ def checkTimeout(self, connection, t):
next_timeout = self._next_timeout
if next_timeout is not None and next_timeout < t:
msg_id = self._next_timeout_msg_id
if self._next_on_timeout is None:
result = msg_id
else:
- if self._next_on_timeout(self._connection, msg_id):
+ if self._next_on_timeout(connection, msg_id):
# Don't notify that a timeout occured, and forget about
# this answer.
for (request_dict, _) in self._pending:
@@ -148,39 +147,39 @@ class HandlerSwitcher(object):
result = None
return result
- def handle(self, packet):
+ def handle(self, connection, packet):
assert not self._is_handling
self._is_handling = True
try:
- self._handle(packet)
+ self._handle(connection, packet)
finally:
self._is_handling = False
@profiler_decorator
- def _handle(self, packet):
+ def _handle(self, connection, packet):
assert len(self._pending) == 1 or self._pending[0][0]
- PACKET_LOGGER.dispatch(self._connection, packet, 'from')
+ PACKET_LOGGER.dispatch(connection, packet, 'from')
msg_id = packet.getId()
(request_dict, handler) = self._pending[0]
# notifications are not expected
if not packet.isResponse():
- handler.packetReceived(self._connection, packet)
+ handler.packetReceived(connection, packet)
return
# checkout the expected answer class
(klass, timeout, _) = request_dict.pop(msg_id, (None, None, None))
if klass and isinstance(packet, klass) or packet.isError():
- handler.packetReceived(self._connection, packet)
+ handler.packetReceived(connection, packet)
else:
- logging.error('Unexpected answer %r in %r', packet, self._connection)
+ logging.error('Unexpected answer %r in %r', packet, connection)
notification = Packets.Notify('Unexpected answer: %r' % packet)
- self._connection.notify(notification)
- self._connection.abort()
- handler.peerBroken(self._connection)
+ connection.notify(notification)
+ connection.abort()
+ handler.peerBroken(connection)
# apply a pending handler if no more answers are pending
while len(self._pending) > 1 and not self._pending[0][0]:
del self._pending[0]
logging.debug('Apply handler %r on %r', self._pending[0][1],
- self._connection)
+ connection)
if timeout == self._next_timeout:
self._updateNextTimeout()
@@ -202,14 +201,14 @@ class HandlerSwitcher(object):
@profiler_decorator
def setHandler(self, handler):
- if len(self._pending) == 1 and not self._pending[0][0]:
+ can_apply = len(self._pending) == 1 and not self._pending[0][0]
+ if can_apply:
# nothing is pending, change immediately
- logging.debug('Set handler %r on %r', handler, self._connection)
self._pending[0][1] = handler
else:
# put the next handler in queue
- logging.debug('Delay handler %r on %r', handler, self._connection)
self._pending.append([{}, handler])
+ return can_apply
class Timeout(object):
@@ -265,14 +264,14 @@ class BaseConnection(object):
self.em = event_manager
self.connector = connector
self.addr = addr
- self._handlers = HandlerSwitcher(self, handler)
+ self._handlers = HandlerSwitcher(handler)
self._timeout = Timeout()
event_manager.register(self)
def checkTimeout(self, t):
handlers = self._handlers
if handlers.isPending():
- msg_id = handlers.checkTimeout(t)
+ msg_id = handlers.checkTimeout(self, t)
if msg_id is not None:
logging.info('timeout for %r with %r', msg_id, self)
self.close()
@@ -332,7 +331,10 @@ class BaseConnection(object):
return self._handlers.getHandler()
def setHandler(self, handler):
- self._handlers.setHandler(handler)
+ if self._handlers.setHandler(handler):
+ logging.debug('Set handler %r on %r', handler, self)
+ else:
+ logging.debug('Delay handler %r on %r', handler, self)
def getEventManager(self):
return self.em
@@ -504,7 +506,7 @@ class Connection(BaseConnection):
"""
# check out packet and process it with current handler
packet = self._queue.pop(0)
- self._handlers.handle(packet)
+ self._handlers.handle(self, packet)
def pending(self):
return self.connector is not None and self.write_buf
Modified: trunk/neo/tests/testConnection.py
==============================================================================
--- trunk/neo/tests/testConnection.py [iso-8859-1] (original)
+++ trunk/neo/tests/testConnection.py [iso-8859-1] Tue Aug 24 18:02:19 2010
@@ -840,11 +840,11 @@ class HandlerSwitcherTests(NeoTestBase):
self._handler = handler = Mock({
'__repr__': 'initial handler',
})
- self._connection = connection = Mock({
+ self._connection = Mock({
'__repr__': 'connection',
'getAddress': ('127.0.0.1', 10000),
})
- self._handlers = HandlerSwitcher(connection, handler)
+ self._handlers = HandlerSwitcher(handler)
def _makeNotification(self, msg_id):
packet = Packets.StartOperation()
@@ -884,42 +884,44 @@ class HandlerSwitcherTests(NeoTestBase):
# Second case, emit is called from inside a handler with a pending
# handler change.
new_handler = self._makeHandler()
- self._handlers.setHandler(new_handler)
+ applied = self._handlers.setHandler(new_handler)
+ self.assertFalse(applied)
self._checkCurrentHandler(self._handler)
call_tracker = []
def packetReceived(conn, packet):
self._handlers.emit(self._makeRequest(2), 0, None)
call_tracker.append(True)
self._handler.packetReceived = packetReceived
- self._handlers.handle(self._makeAnswer(1))
+ self._handlers.handle(self._connection, 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._handlers.handle(self._connection, self._makeAnswer(2))
self._checkCurrentHandler(new_handler)
def testHandleNotification(self):
# handle with current handler
notif1 = self._makeNotification(1)
- self._handlers.handle(notif1)
+ self._handlers.handle(self._connection, notif1)
self._checkPacketReceived(self._handler, notif1)
# emit a request and delay an handler
request = self._makeRequest(2)
self._handlers.emit(request, 0, None)
handler = self._makeHandler()
- self._handlers.setHandler(handler)
+ applied = self._handlers.setHandler(handler)
+ self.assertFalse(applied)
# next notification fall into the current handler
notif2 = self._makeNotification(3)
- self._handlers.handle(notif2)
+ self._handlers.handle(self._connection, notif2)
self._checkPacketReceived(self._handler, notif2, index=1)
# handle with new handler
answer = self._makeAnswer(2)
- self._handlers.handle(answer)
+ self._handlers.handle(self._connection, answer)
notif3 = self._makeNotification(4)
- self._handlers.handle(notif3)
+ self._handlers.handle(self._connection, notif3)
self._checkPacketReceived(handler, notif2)
def testHandleAnswer1(self):
@@ -927,7 +929,7 @@ class HandlerSwitcherTests(NeoTestBase):
request = self._makeRequest(1)
self._handlers.emit(request, 0, None)
answer = self._makeAnswer(1)
- self._handlers.handle(answer)
+ self._handlers.handle(self._connection, answer)
self._checkPacketReceived(self._handler, answer)
def testHandleAnswer2(self):
@@ -935,9 +937,10 @@ class HandlerSwitcherTests(NeoTestBase):
request = self._makeRequest(1)
self._handlers.emit(request, 0, None)
handler = self._makeHandler()
- self._handlers.setHandler(handler)
+ applied = self._handlers.setHandler(handler)
+ self.assertFalse(applied)
answer = self._makeAnswer(1)
- self._handlers.handle(answer)
+ self._handlers.handle(self._connection, answer)
self._checkPacketReceived(self._handler, answer)
self._checkCurrentHandler(handler)
@@ -954,19 +957,22 @@ class HandlerSwitcherTests(NeoTestBase):
h3 = self._makeHandler()
# emit all requests and setHandleres
self._handlers.emit(r1, 0, None)
- self._handlers.setHandler(h1)
+ applied = self._handlers.setHandler(h1)
+ self.assertFalse(applied)
self._handlers.emit(r2, 0, None)
- self._handlers.setHandler(h2)
+ applied = self._handlers.setHandler(h2)
+ self.assertFalse(applied)
self._handlers.emit(r3, 0, None)
- self._handlers.setHandler(h3)
+ applied = self._handlers.setHandler(h3)
+ self.assertFalse(applied)
self._checkCurrentHandler(self._handler)
self.assertTrue(self._handlers.isPending())
# process answers
- self._handlers.handle(a1)
+ self._handlers.handle(self._connection, a1)
self._checkCurrentHandler(h1)
- self._handlers.handle(a2)
+ self._handlers.handle(self._connection, a2)
self._checkCurrentHandler(h2)
- self._handlers.handle(a3)
+ self._handlers.handle(self._connection, a3)
self._checkCurrentHandler(h3)
def testHandleAnswer4(self):
@@ -982,13 +988,14 @@ class HandlerSwitcherTests(NeoTestBase):
self._handlers.emit(r1, 0, None)
self._handlers.emit(r2, 0, None)
self._handlers.emit(r3, 0, None)
- self._handlers.setHandler(h)
+ applied = self._handlers.setHandler(h)
+ self.assertFalse(applied)
# process answers
- self._handlers.handle(a1)
+ self._handlers.handle(self._connection, a1)
self._checkCurrentHandler(self._handler)
- self._handlers.handle(a2)
+ self._handlers.handle(self._connection, a2)
self._checkCurrentHandler(self._handler)
- self._handlers.handle(a3)
+ self._handlers.handle(self._connection, a3)
self._checkCurrentHandler(h)
def testHandleUnexpected(self):
@@ -999,10 +1006,11 @@ class HandlerSwitcherTests(NeoTestBase):
h = self._makeHandler()
# emit requests aroung state setHandler
self._handlers.emit(r1, 0, None)
- self._handlers.setHandler(h)
+ applied = self._handlers.setHandler(h)
+ self.assertFalse(applied)
self._handlers.emit(r2, 0, None)
# process answer for next state
- self._handlers.handle(a2)
+ self._handlers.handle(self._connection, a2)
self.checkAborted(self._connection)
def testTimeout(self):
@@ -1012,7 +1020,8 @@ class HandlerSwitcherTests(NeoTestBase):
"""
now = time()
# No timeout when no pending request
- self.assertEqual(self._handlers.checkTimeout(now), None)
+ self.assertEqual(self._handlers.checkTimeout(self._connection, now),
+ None)
# Prepare some requests
msg_id_1 = 1
msg_id_2 = 2
@@ -1041,21 +1050,26 @@ class HandlerSwitcherTests(NeoTestBase):
self._handlers.emit(r1, msg_1_time, None)
self._handlers.emit(r2, msg_2_time, None)
# No timeout before msg_1_time
- self.assertEqual(self._handlers.checkTimeout(now), None)
+ self.assertEqual(self._handlers.checkTimeout(self._connection, now),
+ None)
# Timeout for msg_1 after msg_1_time
- self.assertEqual(self._handlers.checkTimeout(msg_1_time + 0.5),
- msg_id_1)
+ self.assertEqual(self._handlers.checkTimeout(self._connection,
+ msg_1_time + 0.5), msg_id_1)
# If msg_1 met its answer, no timeout after msg_1_time
- self._handlers.handle(a1)
- self.assertEqual(self._handlers.checkTimeout(msg_1_time + 0.5), None)
+ self._handlers.handle(self._connection, a1)
+ self.assertEqual(self._handlers.checkTimeout(self._connection,
+ msg_1_time + 0.5), None)
# Next timeout is after msg_2_time
- self.assertEqual(self._handlers.checkTimeout(msg_2_time + 0.5), msg_id_2)
- self._handlers.handle(a2)
+ self.assertEqual(self._handlers.checkTimeout(self._connection,
+ msg_2_time + 0.5), msg_id_2)
+ self._handlers.handle(self._connection, a2)
# Sanity check
- self.assertEqual(self._handlers.checkTimeout(msg_2_time + 0.5), None)
+ self.assertEqual(self._handlers.checkTimeout(self._connection,
+ msg_2_time + 0.5), None)
# msg_3 timeout will fire msg_3_on_timeout callback, which causes the
# timeout to be ignored (it returns True)
- self.assertEqual(self._handlers.checkTimeout(msg_3_time + 0.5), None)
+ self.assertEqual(self._handlers.checkTimeout(self._connection,
+ msg_3_time + 0.5), None)
# ...check that callback actually fired
self.assertEqual(len(markers), 1)
# ...with expected parameters
@@ -1067,7 +1081,8 @@ class HandlerSwitcherTests(NeoTestBase):
self._handlers.emit(r4, msg_4_time, OnTimeout(msg_4_on_timeout))
# msg_4 timeout will fire msg_4_on_timeout callback, which lets the
# timeout be detected (it returns False)
- self.assertEqual(self._handlers.checkTimeout(msg_4_time + 0.5), msg_id_4)
+ self.assertEqual(self._handlers.checkTimeout(self._connection,
+ msg_4_time + 0.5), msg_id_4)
# ...check that callback actually fired
self.assertEqual(len(markers), 1)
# ...with expected parameters
More information about the Neo-report
mailing list