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"])
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 __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"])
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')
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')
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)
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)