Exemple #1
0
    def read(self, length=None):
        """
        Read a line from the socket is no length is specified,
        otherwise read ``length`` bytes. Always strip away the newlines.
        """
        try:
            if length is not None:
                bytes_left = length + 2  # read the line ending
                if length > self.MAX_READ_LENGTH:
                    # apparently reading more than 1MB or so from a windows
                    # socket can cause MemoryErrors. See:
                    # https://github.com/andymccurdy/redis-py/issues/205
                    # read smaller chunks at a time to work around this
                    try:
                        buf = StringIO()
                        while bytes_left > 0:
                            read_len = min(bytes_left, self.MAX_READ_LENGTH)
                            buf.write(self._fp.read(read_len))
                            bytes_left -= read_len
                        buf.seek(0)
                        return buf.read(length)
                    finally:
                        buf.close()
                return self._fp.read(bytes_left)[:-2]

            # no length, read a full line
            return self._fp.readline()[:-2]
        except (socket.error, socket.timeout), e:
            raise ConnectionError("Error while reading from socket: %s" % \
                (e.args,))
Exemple #2
0
 def connect(self):
     "Connects to the Redis server if not already connected"
     if self._sock:
         return
     try:
         sock = self._connect()
     except socket.error, e:
         raise ConnectionError(self._error_message(e))
Exemple #3
0
 def read_response(self):
     if not self._reader:
         raise ConnectionError("Socket closed on remote end")
     response = self._reader.gets()
     while response is False:
         try:
             buffer = self._sock.recv(4096)
         except (socket.error, socket.timeout), e:
             raise ConnectionError("Error while reading from socket: %s" % \
                 (e.args,))
         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 \n, there's more.
         if not buffer.endswith('\n'):
             continue
         response = self._reader.gets()
 def send(self, command, redis_instance):
     "Send ``command`` to the Redis server. Return the result."
     self.connect(redis_instance)
     try:
         self._sock.sendall(command)
     except socket.error, e:
         if e.args[0] == errno.EPIPE:
             self.disconnect()
         raise ConnectionError("Error %s while writing to socket. %s." % \
             e.args)
 def connect(self, redis_instance):
     "Connects to the Redis server is not already connected"
     if self._sock:
         return
     try:
         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         sock.connect((self.host, self.port))
     except socket.error, e:
         raise ConnectionError("Error %s connecting to %s:%s. %s." % \
             (e.args[0], self.host, self.port, e.args[1]))
Exemple #6
0
 def send_packed_command(self, command):
     "Send an already packed command to the Redis server"
     if not self._sock:
         self.connect()
     try:
         self._sock.sendall(command)
     except socket.error, e:
         self.disconnect()
         if len(e.args) == 1:
             _errno, errmsg = 'UNKNOWN', e.args[0]
         else:
             _errno, errmsg = e.args
         raise ConnectionError("Error %s while writing to socket. %s." % \
             (_errno, errmsg))
 def read(self, length=None):
     """
     Read a line from the socket is length is None,
     otherwise read ``length`` bytes
     """
     try:
         if length is not None:
             return self._fp.read(length)
         return self._fp.readline()
     except socket.error, e:
         self.disconnect()
         if e.args and e.args[0] == errno.EAGAIN:
             raise ConnectionError("Error while reading from socket: %s" % \
                 e.args[1])
Exemple #8
0
    def read_response(self):
        response = self.read()
        if not response:
            raise ConnectionError("Socket closed on remote end")

        byte, response = response[0], response[1:]

        # server returned an error
        if byte == '-':
            if response.startswith('ERR '):
                response = response[4:]
                return ResponseError(response)
            if response.startswith('LOADING '):
                # If we're loading the dataset into memory, kill the socket
                # so we re-initialize (and re-SELECT) next time.
                raise ConnectionError("Redis is loading data into memory")
        # single value
        elif byte == '+':
            return response
        # int value
        elif byte == ':':
            return long(response)
        # bulk response
        elif byte == '$':
            length = int(response)
            if length == -1:
                return None
            response = self.read(length)
            return response
        # multi-bulk response
        elif byte == '*':
            length = int(response)
            if length == -1:
                return None
            return [self.read_response() for i in xrange(length)]
        raise InvalidResponse("Protocol Error")
Exemple #9
0
    def on_connect(self):
        "Initialize the connection, authenticate and select a database"
        self._parser.on_connect(self)

        # if a password is specified, authenticate
        if self.password:
            self.send_command('AUTH', self.password)
            if self.read_response() != 'OK':
                raise AuthenticationError('Invalid Password')

        # if a database is specified, switch to it
        if self.db:
            self.send_command('SELECT', self.db)
            if self.read_response() != 'OK':
                raise ConnectionError('Invalid Database')
    def _parse_response(self, command_name):
        conn = self.connection
        response = conn.read().strip()
        if not response:
            self.connection.disconnect()
            raise ConnectionError("Socket closed on remote end")

        # server returned a null value
        if response in ('$-1', '*-1'):
            return None
        byte, response = response[0], response[1:]

        # server returned an error
        if byte == '-':
            if response.startswith('ERR '):
                response = response[4:]
            raise ResponseError(response)
        # single value
        elif byte == '+':
            return response
        # int value
        elif byte == ':':
            return int(response)
        # bulk response
        elif byte == '$':
            length = int(response)
            if length == -1:
                return None
            response = length and conn.read(length) or ''
            conn.read(2)  # read the \r\n delimiter
            return response
        # multi-bulk response
        elif byte == '*':
            length = int(response)
            if length == -1:
                return None
            return [self._parse_response(command_name) for i in range(length)]

        raise InvalidResponse("Unknown response type for: %s" % command_name)
Exemple #11
0
 def make_connection(self):
     "Create a new connection"
     if self._created_connections >= self.max_connections:
         raise ConnectionError("Too many connections")
     self._created_connections += 1
     return self.connection_class(**self.connection_kwargs)