Database::Database(const char *nm, bool& newDb, const string& path ) : _name(nm), _path(path), _namespaceIndex( _path, _name ), _extentManager(_name, _path, 0, storageGlobalParams.directoryperdb), _profileName(_name + ".system.profile"), _namespacesName(_name + ".system.namespaces"), _indexesName(_name + ".system.indexes"), _extentFreelistName( _name + ".$freelist" ), _collectionLock( "Database::_collectionLock" ) { Status status = validateDBName( _name ); if ( !status.isOK() ) { warning() << "tried to open invalid db: " << _name << endl; uasserted( 10028, status.toString() ); } try { newDb = _namespaceIndex.exists(); _profile = serverGlobalParams.defaultProfile; checkDuplicateUncasedNames(true); // If already exists, open. Otherwise behave as if empty until // there's a write, then open. if (!newDb) { _namespaceIndex.init(); _extentManager.init( _namespaceIndex.details( _extentFreelistName ) ); openAllFiles(); } _magic = 781231; } catch(std::exception& e) { log() << "warning database " << path << " " << nm << " could not be opened" << endl; DBException* dbe = dynamic_cast<DBException*>(&e); if ( dbe != 0 ) { log() << "DBException " << dbe->getCode() << ": " << e.what() << endl; } else { log() << e.what() << endl; } _extentManager.reset(); throw; } }
void Command::generateErrorResponse(OperationContext* txn, rpc::ReplyBuilderInterface* replyBuilder, const DBException& exception, const rpc::RequestInterface& request, Command* command, const BSONObj& metadata) { LOG(1) << "assertion while executing command '" << request.getCommandName() << "' " << "on database '" << request.getDatabase() << "' " << "with arguments '" << command->getRedactedCopyForLogging(request.getCommandArgs()) << "' " << "and metadata '" << request.getMetadata() << "': " << exception.toString(); _generateErrorResponse(txn, replyBuilder, exception, metadata); }
//------------------------------------------------------------------------------------- bool DBInterfaceMysql::processException(std::exception & e) { DBException* dbe = static_cast<DBException*>(&e); bool retry = false; if (dbe->isLostConnection()) { INFO_MSG(boost::format("DBInterfaceMysql::processException: " "Thread %p lost connection to database. Exception: %s. " "Attempting to reconnect.\n") % this % dbe->what() ); int attempts = 1; while (!this->reattach()) { ERROR_MSG(boost::format("DBInterfaceMysql::processException: " "Thread %p reconnect(%s) attempt %d failed(%s).\n") % this % db_name_ % attempts % getLastError()); KBEngine::sleep(30); ++attempts; } INFO_MSG(boost::format("DBInterfaceMysql::processException: " "Thread %p reconnected(%s). Attempts = %d\n") % this % db_name_ % attempts); retry = true; } else if (dbe->shouldRetry()) { WARNING_MSG(boost::format("DBInterfaceMysql::processException: Retrying %1%\nException:%2%\nnlastquery=%3%\n") % this % dbe->what() % lastquery_); retry = true; } else { WARNING_MSG(boost::format("DBInterfaceMysql::processException: " "Exception: %1%\nlastquery=%2%\n") % dbe->what() % lastquery_); } return retry; }
//------------------------------------------------------------------------------------- bool DBInterfaceMysql::processException(std::exception & e) { DBException* dbe = static_cast<DBException*>(&e); bool retry = false; if (dbe->isLostConnection()) { INFO_MSG(fmt::format("DBInterfaceMysql::processException: " "Thread {:p} lost connection to database. Exception: {}. " "Attempting to reconnect.\n", (void*)this, dbe->what())); int attempts = 1; while (!this->reattach()) { ERROR_MSG(fmt::format("DBInterfaceMysql::processException: " "Thread {:p} reconnect({}) attempt {} failed({}).\n", (void*)this, db_name_, attempts, getLastError())); KBEngine::sleep(30); ++attempts; } INFO_MSG(fmt::format("DBInterfaceMysql::processException: " "Thread {:p} reconnected({}). Attempts = {}\n", (void*)this, db_name_, attempts)); retry = true; } else if (dbe->shouldRetry()) { WARNING_MSG(fmt::format("DBInterfaceMysql::processException: Retrying {:p}\nException:{}\nnlastquery={}\n", (void*)this, dbe->what(), lastquery_)); retry = true; } else { WARNING_MSG(fmt::format("DBInterfaceMysql::processException: " "Exception: {}\nlastquery={}\n", dbe->what(), lastquery_)); } return retry; }
/** * Returns true if the operation can continue. */ bool handleError(OperationContext* txn, const DBException& ex, const ParsedWriteOp& wholeOp, WriteResult* out) { LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg); auto& curOp = *CurOp::get(txn); curOp.debug().exceptionInfo = ex.getInfo(); if (ErrorCodes::isInterruption(ErrorCodes::Error(ex.getCode()))) { throw; // These have always failed the whole batch. } if (ErrorCodes::isStaleShardingError(ErrorCodes::Error(ex.getCode()))) { auto staleConfigException = dynamic_cast<const SendStaleConfigException*>(&ex); if (!staleConfigException) { // We need to get extra info off of the SCE, but some common patterns can result in the // exception being converted to a Status then rethrown as a UserException, losing the // info we need. It would be a bug if this happens so we want to detect it in testing, // but it isn't severe enough that we should bring down the server if it happens in // production. dassert(staleConfigException); msgassertedNoTrace(35475, str::stream() << "Got a StaleConfig error but exception was the wrong type: " << demangleName(typeid(ex))); } ShardingState::get(txn) ->onStaleShardVersion(txn, wholeOp.ns, staleConfigException->getVersionReceived()); out->staleConfigException = stdx::make_unique<SendStaleConfigException>(*staleConfigException); return false; } out->results.emplace_back(ex.toStatus()); return wholeOp.continueOnError; }
std::string causedBy(const DBException& e) { return causedBy(e.toString()); }
void Command::generateErrorResponse(OperationContext* txn, rpc::ReplyBuilderInterface* replyBuilder, const DBException& exception) { LOG(1) << "assertion while executing command: " << exception.toString(); _generateErrorResponse(txn, replyBuilder, exception, rpc::makeEmptyMetadata()); }
static bool isAuthenticationException( const DBException& ex ) { return ex.getCode() == ErrorCodes::AuthenticationFailed; }