[Neo-report] r2001 vincent - in /trunk/neo: connection.py protocol.py

nobody at svn.erp5.org nobody at svn.erp5.org
Mon Apr 19 11:49:34 CEST 2010


Author: vincent
Date: Mon Apr 19 11:49:33 2010
New Revision: 2001

Log:
Avoid parsing packet header multiple times when there is not enough data.

Modified:
    trunk/neo/connection.py
    trunk/neo/protocol.py

Modified: trunk/neo/connection.py
==============================================================================
--- trunk/neo/connection.py [iso-8859-1] (original)
+++ trunk/neo/connection.py [iso-8859-1] Mon Apr 19 11:49:33 2010
@@ -20,7 +20,7 @@
 from neo import logging
 from neo.locking import RLock
 
-from neo.protocol import PacketMalformedError, Packets
+from neo.protocol import PacketMalformedError, Packets, ParserState
 from neo.connector import ConnectorException, ConnectorTryAgainException, \
         ConnectorInProgressException, ConnectorConnectionRefusedException, \
         ConnectorConnectionClosedException
@@ -293,6 +293,7 @@
         self.uuid = None
         self._queue = []
         self._on_close = None
+        self._parser_state = ParserState()
         event_manager.addReader(self)
 
     def setOnClose(self, callback):
@@ -359,7 +360,7 @@
         while True:
             # parse a packet
             try:
-                packet = Packets.parse(self.read_buf)
+                packet = Packets.parse(self.read_buf, self._parser_state)
                 if packet is None:
                     break
             except PacketMalformedError, msg:

Modified: trunk/neo/protocol.py
==============================================================================
--- trunk/neo/protocol.py [iso-8859-1] (original)
+++ trunk/neo/protocol.py [iso-8859-1] Mon Apr 19 11:49:33 2010
@@ -1575,6 +1575,21 @@
         return (request, answer)
     return request
 
+class ParserState(object):
+    """
+    Parser internal state.
+    To be considered opaque datatype outside of PacketRegistry.parse .
+    """
+    payload = None
+
+    def set(self, payload):
+        self.payload = payload
+
+    def get(self):
+        return self.payload
+
+    def clear(self):
+        self.payload = None
 
 class PacketRegistry(dict):
     """
@@ -1586,28 +1601,32 @@
         # load packet classes
         self.update(StaticRegistry)
 
-    def parse(self, buf):
-        if len(buf) < PACKET_HEADER_SIZE:
+    def parse(self, buf, state_container):
+        state = state_container.get()
+        if state is None:
+            header = buf.read(PACKET_HEADER_SIZE)
+            if header is None:
+                return None
+            msg_id, msg_type, msg_len = unpack(PACKET_HEADER_FORMAT, header)
+            try:
+                packet_klass = self[msg_type]
+            except KeyError:
+                raise PacketMalformedError('Unknown packet type')
+            if msg_len > MAX_PACKET_SIZE:
+                raise PacketMalformedError('message too big (%d)' % msg_len)
+            if msg_len < MIN_PACKET_SIZE:
+                raise PacketMalformedError('message too small (%d)' % msg_len)
+            msg_len -= PACKET_HEADER_SIZE
+        else:
+            msg_id, packet_klass, msg_len = state
+        data = buf.read(msg_len)
+        if data is None:
+            # Not enough.
+            state_container.set((msg_id, packet_klass, msg_len))
             return None
-        header = buf.peek(PACKET_HEADER_SIZE)
-        assert header is not None
-        msg_id, msg_type, msg_len = unpack(PACKET_HEADER_FORMAT, header)
-        try:
-            packet_klass = self[msg_type]
-        except KeyError:
-            raise PacketMalformedError('Unknown packet type')
-        if msg_len > MAX_PACKET_SIZE:
-            raise PacketMalformedError('message too big (%d)' % msg_len)
-        if msg_len < MIN_PACKET_SIZE:
-            raise PacketMalformedError('message too small (%d)' % msg_len)
-        if len(buf) < msg_len:
-            # Not enough.
-            return None
-        buf.skip(PACKET_HEADER_SIZE)
-        msg_len -= PACKET_HEADER_SIZE
+        if state:
+            state_container.clear()
         packet = packet_klass()
-        data = buf.read(msg_len)
-        assert data is not None
         packet.setContent(msg_id, data)
         return packet
 





More information about the Neo-report mailing list