Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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()
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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)