Beispiel #1
0
    def process_data(self, data, cmd_line, callback):
        error, response = None, None

        data = data[:-2]  # strip \r\n

        if data == '$-1':
            response = None
        elif data == '*0' or data == '*-1':
            response = []
        else:
            head, tail = data[0], data[1:]

            if head == '*':
                error, response = yield self.consume_multibulk(
                    int(tail), cmd_line)
            elif head == '$':
                error, response = yield self.consume_bulk(int(tail) + 2)
            elif head == '+':
                response = tail
            elif head == ':':
                response = int(tail)
            elif head == '-':
                if tail.startswith('ERR'):
                    tail = tail[4:]
                error = ResponseError(tail, cmd_line)
            else:
                error = ResponseError('Unknown response type %s' % head,
                                      cmd_line)

        callback((error, response))
Beispiel #2
0
    def process_data(self, data, cmd_line, callback):
        with execution_context(callback) as ctx:
            data = data.decode('utf-8')
            data = data[:-2]  # strip \r\n

            if data == '$-1':
                response = None
            elif data == '*0' or data == '*-1':
                response = []
            else:
                if len(data) == 0:
                    raise IOError('Disconnected')
                head, tail = data[0], data[1:]

                if head == '*':
                    response = yield self.consume_multibulk(
                        int(tail), cmd_line)
                elif head == '$':
                    response = yield self.consume_bulk(int(tail) + 2)
                elif head == '+':
                    response = tail
                elif head == ':':
                    response = int(tail)
                elif head == '-':
                    if tail.startswith('ERR'):
                        tail = tail[4:]
                    response = ResponseError(tail, cmd_line)
                else:
                    raise ResponseError('Unknown response type %s' % head,
                                        cmd_line)
            ctx.ret_call(response)
Beispiel #3
0
 def consume_bulk(self, length, callback):
     data = yield async (self.connection.read)(length)
     error = None
     if not data:
         error = ResponseError('EmptyResponse')
     else:
         data = data[:-2]
     callback((error, data))
Beispiel #4
0
 def format_reply(self, cmd_line, data):
     if cmd_line.cmd not in self.REPLY_MAP:
         return data
     try:
         res = self.REPLY_MAP[cmd_line.cmd](data, *cmd_line.args,
                                            **cmd_line.kwargs)
     except Exception, e:
         res = ResponseError('failed to format reply, raw data: %s' % data,
                             cmd_line)
Beispiel #5
0
 def consume_bulk(self, length, callback):
     with execution_context(callback) as ctx:
         data = yield async (self.connection.read)(length)
         if isinstance(data, Exception):
             raise data
         if not data:
             raise ResponseError('EmptyResponse')
         else:
             data = data[:-2]
         ctx.ret_call(data)
Beispiel #6
0
 def format_reply(self, cmd_line, data):
     if cmd_line.cmd not in self.REPLY_MAP:
         return data
     try:
         res = self.REPLY_MAP[cmd_line.cmd](data, *cmd_line.args,
                                            **cmd_line.kwargs)
     except Exception, e:
         raise ResponseError(
             'failed to format reply to %s, raw data: %s; err message: %s' %
             (cmd_line, data, e), cmd_line)
Beispiel #7
0
    def consume_multibulk(self, length, cmd_line, callback):
        with execution_context(callback) as ctx:
            tokens = []
            while len(tokens) < length:
                data = yield async (self.connection.readline)()
                if not data:
                    raise ResponseError(
                        'Not enough data in response to %s, accumulated tokens: %s'
                        % (cmd_line, tokens), cmd_line)
                token = yield self.process_data(data, cmd_line)  #FIXME error
                tokens.append(token)

            ctx.ret_call(tokens)
Beispiel #8
0
    def execute(self, callbacks):
        with execution_context(callbacks) as ctx:
            command_stack = self.command_stack
            self.command_stack = []

            if callbacks is None:
                callbacks = []
            elif not hasattr(callbacks, '__iter__'):
                callbacks = [callbacks]

            if self.transactional:
                command_stack = [CmdLine('MULTI')
                                 ] + command_stack + [CmdLine('EXEC')]

            request = format_pipeline_request(command_stack)

            try:
                self.connection.write(request)
            except IOError:
                self.command_stack = []
                self.connection.disconnect()
                raise ConnectionError("Socket closed on remote end")
            except Exception, e:
                self.command_stack = []
                self.connection.disconnect()
                raise e

            yield self.connection.queue_wait()
            responses = []
            total = len(command_stack)
            cmds = iter(command_stack)

            while len(responses) < total:
                data = yield async (self.connection.readline)()
                if not data:
                    raise ResponseError('Not enough data after EXEC')
                try:
                    cmd_line = cmds.next()
                    if self.transactional and cmd_line.cmd != 'EXEC':
                        response = yield self.process_data(
                            data, CmdLine('MULTI_PART'))
                    else:
                        response = yield self.process_data(data, cmd_line)
                    responses.append(response)
                except Exception, e:
                    responses.append(e)
Beispiel #9
0
    def execute(self, callbacks):
        with execution_context(callbacks) as ctx:
            command_stack = self.command_stack
            self.command_stack = []

            if callbacks is None:
                callbacks = []
            elif not hasattr(callbacks, '__iter__'):
                callbacks = [callbacks]

            if self.transactional:
                command_stack = [CmdLine('MULTI')
                                 ] + command_stack + [CmdLine('EXEC')]

            request = format_pipeline_request(command_stack)

            try:
                self.connection.write(request)
            except IOError:
                self.command_stack = []
                self.connection.disconnect()
                raise ConnectionError("Socket closed on remote end")
            except Exception as e:
                self.command_stack = []
                self.connection.disconnect()
                raise e

            yield self.connection.queue_wait()
            responses = []
            total = len(command_stack)
            cmds = iter(command_stack)

            while len(responses) < total:
                data = yield async (self.connection.readline)()
                if not data:
                    raise ResponseError('Not enough data after EXEC')
                try:
                    cmd_line = cmds.next()
                    if self.transactional and cmd_line.cmd != 'EXEC':
                        response = yield self.process_data(
                            data, CmdLine('MULTI_PART'))
                    else:
                        response = yield self.process_data(data, cmd_line)
                    responses.append(response)
                except Exception as e:
                    responses.append(e)
            self.connection.read_done()

            def format_replies(cmd_lines, responses):
                results = []
                for cmd_line, response in zip(cmd_lines, responses):
                    try:
                        results.append(self.format_reply(cmd_line, response))
                    except Exception as e:
                        results.append(e)
                return results

            if self.transactional:
                command_stack = command_stack[:-1]
                responses = responses[-1]  # actual data only from EXEC command
                #FIXME:  assert all other responses to be 'QUEUED'
                log.info('responses %s', responses)
                results = format_replies(command_stack[1:], responses)
                log.info('results %s', results)
            else:
                results = format_replies(command_stack, responses)

            ctx.ret_call(results)