def _unpack_response(response, cursor_id=None, as_class=dict, tz_aware=False): """Unpack a response from the database. Check the response for errors and unpack, returning a dictionary containing the response data. :Parameters: - `response`: byte string as returned from the database - `cursor_id` (optional): cursor_id we sent to get this response - used for raising an informative exception when we get cursor id not valid at server response - `as_class` (optional): class to use for resulting documents """ response_flag = struct.unpack("<i", response[:4])[0] if response_flag & 1: # Shouldn't get this response if we aren't doing a getMore assert cursor_id is not None raise InterfaceError("cursor id '%s' not valid at server" % cursor_id) elif response_flag & 2: error_object = bson.BSON(response[20:]).decode() if error_object["$err"] == "not master": raise DatabaseError("master has changed") raise DatabaseError("database error: %s" % error_object["$err"]) result = {} result["cursor_id"] = struct.unpack("<q", response[4:12])[0] result["starting_from"] = struct.unpack("<i", response[12:16])[0] result["number_returned"] = struct.unpack("<i", response[16:20])[0] result["data"] = bson.decode_all(response[20:], as_class, tz_aware) assert len(result["data"]) == result["number_returned"] return result
def send_message(self, message, with_last_error=False, callback=None): """Say something to Mongo. Raises ConnectionFailure if the message cannot be sent. Raises OperationFailure if `with_last_error` is ``True`` and the response to the getLastError call returns an error. Return the response from lastError, or ``None`` if `with_last_error` is ``False``. :Parameters: - `message`: message to send - `with_last_error`: check getLastError status after sending the message """ if self._callback is not None: raise ProgrammingError('connection already in use') if self.closed(): if self._autoreconnect: self._connect() else: raise InterfaceError( 'connection is closed and autoreconnect is false') self._callback = stack_context.wrap(callback) self._check_response = with_last_error with stack_context.StackContext(self.close_on_error): self.__send_message(message, with_last_error=with_last_error)
def close(self): logger.debug('{0} connection close'.format(self)) if self._callback: self._callback((None, InterfaceError('connection closed'))) self.reset() self._connected = False self._stream.close()
def send_message(self, message, callback): if not self._connected: if self._auto_reconnect: self._connect() else: raise InterfaceError( 'connection is closed and autoreconnect is false') self._send_message(message, callback)
def _connect(self): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) s.connect((self._host, self._port)) self._stream = iostream.IOStream(s) self._stream.set_close_callback(self._on_socket_close) self._connected = True except socket.error, error: raise InterfaceError(error)
def send_message_with_response(self, message, callback): """Send a message to Mongo and return the response. Sends the given message and returns the response. :Parameters: - `message`: (request_id, data) pair making up the message to send """ if self._callback is not None: raise ProgrammingError('connection already in use') if self.closed(): if self._autoreconnect: self._connect() else: raise InterfaceError( 'connection is closed and autoreconnect is false') self._callback = stack_context.wrap(callback) self._check_response = False with stack_context.StackContext(self.close_on_error): self.__send_message_and_receive(message)