Beispiel #1
0
def _check_command_response(response, msg="%s", allowable_errors=[]):

    if not response["ok"]:
        if "wtimeout" in response and response["wtimeout"]:
            raise TimeoutError(msg % response["errmsg"])

        details = response
        # Mongos returns the error details in a 'raw' object
        # for some errors.
        if "raw" in response:
            for shard in response["raw"].itervalues():
                if not shard.get("ok"):
                    # Just grab the first error...
                    details = shard
                    break

        if not details["errmsg"] in allowable_errors:
            if details["errmsg"] == "db assertion failure":
                ex_msg = ("db assertion failure, assertion: '%s'" %
                          details.get("assertion", ""))
                if "assertionCode" in details:
                    ex_msg += (", assertionCode: %d" %
                               (details["assertionCode"], ))
                raise DatabaseError(ex_msg, details.get("assertionCode"))
            raise DatabaseError(msg % details["errmsg"])
Beispiel #2
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
Beispiel #3
0
    def __check_response_to_last_error(self, response):
        """Check a response to a lastError message for errors.

        `response` is a byte string representing a response to the message.
        If it represents an error response we raise DatabaseError.

        Return the response as a document.
        """
        response = helpers._unpack_response(response)
        assert response["number_returned"] == 1
        error = response["data"][0]

        helpers._check_command_response(error)

        error_msg = error.get("err", "")
        if error_msg is None:
            return error

        details = error
        # mongos returns the error code in an error object
        # for some errors.
        if "errObjects" in error:
            for errobj in error["errObjects"]:
                if errobj["err"] == error_msg:
                    details = errobj
                    break

        if "code" in details:
            if details["code"] in [11000, 11001, 12582]:
                raise IntegrityError(details["err"])
            else:
                raise DatabaseError(details["err"], details["code"])
        else:
            raise DatabaseError(details["err"])
Beispiel #4
0
    def test_raises_error_when_cant_unpack_response(self, fake_helpers):
        """[ConnectionTestCase] - Returns DatabaseError when can't unpack response from mongo"""

        fake_helpers.provides('_unpack_response') \
            .raises(DatabaseError('database error'))

        object_id = ObjectId()
        message_test = message.query(0, 'mongotor_test.$cmd', 0, 1,
                                     {'driverOIDTest': object_id})

        self.conn.send_message(message_test,
                               with_last_error=True,
                               callback=self.stop)

        self.wait.when.called_with().throw(DatabaseError, 'database error')
Beispiel #5
0
    def test_raises_error_when_cant_unpack_response(self, fake_helpers):
        """[ConnectionTestCase] - Returns DatabaseError when can't unpack response from mongo"""

        fake_helpers.provides('_unpack_response') \
            .raises(DatabaseError('database error'))

        object_id = ObjectId()
        message_test = message.query(0, 'mongotor_test.$cmd', 0, 1,
                                     {'driverOIDTest': object_id})

        self.conn.send_message(message_test, callback=self.stop)
        response, error = self.wait()

        response.should.be.none
        error.should.be.a('mongotor.errors.DatabaseError')
Beispiel #6
0
    def get_node(self, read_preference=None, callback=None):
        assert callback

        # check if database is connected
        if not self._connected:
            # connect database
            yield gen.Task(self._connect)

        if read_preference is None:
            read_preference = self._read_preference

        node = ReadPreference.select_node(self._nodes, read_preference)
        if not node:
            raise DatabaseError('could not find an available node')

        callback(node)
Beispiel #7
0
    def wrapped(self, *args, **kwargs):
        if not hasattr(self, '_initialized'):
            raise DatabaseError(
                "you must be initialize database before perform this action")

        return fn(self, *args, **kwargs)