import errno
import logging
import socket
-from cStringIO import StringIO
+import sys
from tornado import ioloop
from tornado import stack_context
self.io_loop = io_loop or ioloop.IOLoop.instance()
self.max_buffer_size = max_buffer_size
self.read_chunk_size = read_chunk_size
- self._read_buffer = StringIO()
+ self._read_buffer = collections.deque()
self._write_buffer = collections.deque()
self._read_delimiter = None
self._read_bytes = None
raise
if chunk is None:
return 0
- self._read_buffer.write(chunk)
- if self._read_buffer.tell() >= self.max_buffer_size:
+ self._read_buffer.append(chunk)
+ if self._read_buffer_size() >= self.max_buffer_size:
logging.error("Reached maximum read buffer size")
self.close()
raise IOError("Reached maximum read buffer size")
Returns True if the read was completed.
"""
if self._read_bytes:
- if self._read_buffer.tell() >= self._read_bytes:
+ if self._read_buffer_size() >= self._read_bytes:
num_bytes = self._read_bytes
callback = self._read_callback
self._read_callback = None
self._run_callback(callback, self._consume(num_bytes))
return True
elif self._read_delimiter:
- loc = self._read_buffer.getvalue().find(self._read_delimiter)
+ _merge_prefix(self._read_buffer, sys.maxint)
+ loc = self._read_buffer[0].find(self._read_delimiter)
if loc != -1:
callback = self._read_callback
delimiter_len = len(self._read_delimiter)
self._run_callback(callback)
def _consume(self, loc):
- buffered_string = self._read_buffer.getvalue()
- self._read_buffer = StringIO()
- self._read_buffer.write(buffered_string[loc:])
- return buffered_string[:loc]
+ _merge_prefix(self._read_buffer, loc)
+ return self._read_buffer.popleft()
def _check_closed(self):
if not self.socket:
self._state = self._state | state
self.io_loop.update_handler(self.socket.fileno(), self._state)
+ def _read_buffer_size(self):
+ return sum(len(chunk) for chunk in self._read_buffer)
+
class SSLIOStream(IOStream):
"""A utility class to write to and read from a non-blocking socket.