def write(self, data, try_left=None): if try_left is None: try_left = self.try_left if not self._stream: self.connect() if not self._stream: raise ConnectionError('Tried to write to non-existent connection') if try_left > 0: try: self._stream.write(data) except IOError: self.disconnect() self.write(data, try_left - 1) else: raise ConnectionError('Tried to write to non-existent connection')
def readline(self, callback): try: if not self._stream: self.disconnect() raise ConnectionError('Tried to read from non-existent connection') self._stream.read_until('\r\n', callback) except IOError: self.on_disconnect()
def read(self, length, callback): try: if not self._stream: self.disconnect() raise ConnectionError('Tried to read from non-existent connection') self._stream.read_bytes(length, callback) except IOError: self.on_disconnect()
def connect(self): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) sock.settimeout(self.timeout) sock.connect((self.host, self.port)) self._stream = IOStream(sock, io_loop=self._io_loop) except socket.error, e: raise ConnectionError(str(e))
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)
def error_wrapper(e): if isinstance(e, GeneratorExit): return ConnectionError('Connection lost') else: return e
def on_disconnect(self): if self.subscribed: self.subscribed = False raise ConnectionError("Socket closed on remote end")
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)
def _sudden_disconnect(self, callbacks): self.connection.disconnect() self.call_callbacks( callbacks, (ConnectionError("Socket closed on remote end"), None))