Skip to content

Commit

Permalink
Added support for reusing a bytearray buffer when parsing with hiredi…
Browse files Browse the repository at this point in the history
…s-py 0.1.4
  • Loading branch information
tzickel committed Jun 27, 2014
1 parent bd28b48 commit e03b828
Showing 1 changed file with 32 additions and 9 deletions.
41 changes: 32 additions & 9 deletions redis/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
hiredis_version = StrictVersion(hiredis.__version__)
HIREDIS_SUPPORTS_CALLABLE_ERRORS = \
hiredis_version >= StrictVersion('0.1.3')
HIREDIS_SUPPORTS_SANE_BUFFER = \
hiredis_version >= StrictVersion('0.1.4')

if not HIREDIS_SUPPORTS_CALLABLE_ERRORS:
msg = ("redis-py works best with hiredis >= 0.1.3. You're running "
Expand Down Expand Up @@ -262,6 +264,13 @@ def __init__(self, socket_read_size):
if not HIREDIS_AVAILABLE:
raise RedisError("Hiredis is not installed")
self.socket_read_size = socket_read_size
self.usebuffer = True
if sys.version[0] == '2' and sys.version[2] < '7':
self.usebuffer = False
if not HIREDIS_SUPPORTS_SANE_BUFFER:
self.usebuffer = False
if self.usebuffer:
self._buffer = bytearray(socket_read_size)

def __del__(self):
try:
Expand Down Expand Up @@ -312,23 +321,37 @@ def read_response(self):
socket_read_size = self.socket_read_size
while response is False:
try:
buffer = self._sock.recv(socket_read_size)
# an empty string indicates the server shutdown the socket
if isinstance(buffer, str) and len(buffer) == 0:
raise socket.error("Connection closed by remote server.")
if self.usebuffer:
bufflen = self._sock.recv_into(self._buffer)
if bufflen == 0:
raise socket.error("Connection closed by remote \
server.")
else:
buffer = self._sock.recv(socket_read_size)
# an empty string indicates the server shutdown the socket
if isinstance(buffer, str) and len(buffer) == 0:
raise socket.error("Connection closed by remote \
server.")
except socket.timeout:
raise TimeoutError("Timeout reading from socket")
except socket.error:
e = sys.exc_info()[1]
raise ConnectionError("Error while reading from socket: %s" %
(e.args,))
if not buffer:
raise ConnectionError("Socket closed on remote end")
self._reader.feed(buffer)
if self.usebuffer:
self._reader.feed(self._buffer, 0, bufflen)
else:
if not buffer:
raise ConnectionError("Socket closed on remote end")
self._reader.feed(buffer)
# proactively, but not conclusively, check if more data is in the
# buffer. if the data received doesn't end with \r\n, there's more.
if not buffer.endswith(SYM_CRLF):
continue
if self.usebuffer:
if self._buffer[bufflen - 2:bufflen] != SYM_CRLF:
continue
else:
if not buffer.endswith(SYM_CRLF):
continue
response = self._reader.gets()
# if an older version of hiredis is installed, we need to attempt
# to convert ResponseErrors to their appropriate types.
Expand Down

0 comments on commit e03b828

Please sign in to comment.