diff options
author | Ben Caimano <ben.caimano@10gen.com> | 2018-07-31 18:26:07 -0400 |
---|---|---|
committer | Ben Caimano <ben.caimano@10gen.com> | 2018-07-31 18:32:19 -0400 |
commit | 6711ab3bbc02ca98da1af2fe115f07e37bb076e4 (patch) | |
tree | f1859ba3692a982b0afbd06fcb523c830136c25c /src/mongo/db/auth/authorization_manager_impl.cpp | |
parent | 35757e8ef3134fad1a09cb09a69882929d9ebb76 (diff) | |
download | mongo-6711ab3bbc02ca98da1af2fe115f07e37bb076e4.tar.gz |
Revert "SERVER-35890 refactor User cache into InvalidatingLRUCache and UserHandle"
This reverts commit 78dec3622268ad27bb855eda4c6a4ed345412fd9.
Diffstat (limited to 'src/mongo/db/auth/authorization_manager_impl.cpp')
-rw-r--r-- | src/mongo/db/auth/authorization_manager_impl.cpp | 137 |
1 files changed, 87 insertions, 50 deletions
diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp index be6c356495b..054aa9ff939 100644 --- a/src/mongo/db/auth/authorization_manager_impl.cpp +++ b/src/mongo/db/auth/authorization_manager_impl.cpp @@ -59,7 +59,6 @@ #include "mongo/db/global_settings.h" #include "mongo/db/jsobj.h" #include "mongo/db/mongod_options.h" -#include "mongo/db/server_parameters.h" #include "mongo/platform/compiler.h" #include "mongo/stdx/memory.h" #include "mongo/stdx/mutex.h" @@ -78,12 +77,14 @@ using std::back_inserter; using std::string; using std::vector; + MONGO_INITIALIZER_GENERAL(SetupInternalSecurityUser, ("EndStartupOptionStorage"), ("CreateAuthorizationManager")) (InitializerContext* const context) try { - UserHandle user = std::make_shared<User>(UserName("__system", "local")); + User* user = new User(UserName("__system", "local")); + user->incrementRefCount(); // Pin this user so the ref count never drops below 1. ActionSet allActions; allActions.addAllActions(); PrivilegeVector privileges; @@ -110,8 +111,6 @@ MONGO_INITIALIZER_GENERAL(SetupInternalSecurityUser, } catch (...) { return exceptionToStatus(); } - -MONGO_EXPORT_STARTUP_SERVER_PARAMETER(authorizationManagerCacheSize, int, 100); } // namespace @@ -206,7 +205,7 @@ public: fassert(17191, !_authzManager->_isFetchPhaseBusy); _isThisGuardInFetchPhase = true; _authzManager->_isFetchPhaseBusy = true; - _startGeneration = _authzManager->_fetchGeneration; + _startGeneration = _authzManager->_cacheGeneration; _lock.unlock(); } @@ -225,7 +224,7 @@ public: } /** - * Returns true if _authzManager->_fetchGeneration remained the same while this guard was + * Returns true if _authzManager->_cacheGeneration remained the same while this guard was * in fetch phase. Behavior is undefined if this guard never entered fetch phase. * * If this returns true, do not update the cached data with this @@ -233,7 +232,7 @@ public: bool isSameCacheGeneration() const { fassert(17223, _isThisGuardInFetchPhase); fassert(17231, _lock.owns_lock()); - return _startGeneration == _authzManager->_fetchGeneration; + return _startGeneration == _authzManager->_cacheGeneration; } private: @@ -261,12 +260,18 @@ AuthorizationManagerImpl::AuthorizationManagerImpl( _privilegeDocsExist(false), _externalState(std::move(externalState)), _version(schemaVersionInvalid), - _userCache(authorizationManagerCacheSize, UserCacheInvalidator()), _isFetchPhaseBusy(false) { _updateCacheGeneration_inlock(); } -AuthorizationManagerImpl::~AuthorizationManagerImpl() {} +AuthorizationManagerImpl::~AuthorizationManagerImpl() { + for (stdx::unordered_map<UserName, User*>::iterator it = _userCache.begin(); + it != _userCache.end(); + ++it) { + fassert(17265, it->second != internalSecurity.user); + delete it->second; + } +} std::unique_ptr<AuthorizationSession> AuthorizationManagerImpl::makeAuthorizationSession() { return std::make_unique<AuthorizationSessionImpl>( @@ -308,7 +313,7 @@ Status AuthorizationManagerImpl::getAuthorizationVersion(OperationContext* opCtx OID AuthorizationManagerImpl::getCacheGeneration() { CacheGuard guard(this, CacheGuard::fetchSynchronizationManual); - return _fetchGeneration; + return _cacheGeneration; } void AuthorizationManagerImpl::setAuthEnabled(bool enabled) { @@ -408,30 +413,33 @@ Status AuthorizationManagerImpl::getRoleDescriptionsForDB( opCtx, dbname, privileges, restrictions, showBuiltinRoles, result); } -void AuthorizationManagerImpl::UserCacheInvalidator::operator()(User* user) { - user->_invalidate(); -} - -StatusWith<UserHandle> AuthorizationManagerImpl::acquireUser(OperationContext* opCtx, - const UserName& userName) { +Status AuthorizationManagerImpl::acquireUser(OperationContext* opCtx, + const UserName& userName, + User** acquiredUser) { if (userName == internalSecurity.user->getName()) { - return internalSecurity.user; + *acquiredUser = internalSecurity.user; + return Status::OK(); } + stdx::unordered_map<UserName, User*>::iterator it; + CacheGuard guard(this, CacheGuard::fetchSynchronizationManual); - boost::optional<std::shared_ptr<User>> cachedUser; - while ((boost::none == (cachedUser = _userCache.get(userName))) && + while ((_userCache.end() == (it = _userCache.find(userName))) && guard.otherUpdateInFetchPhase()) { guard.wait(); } - if (cachedUser != boost::none) { - auto ret = *cachedUser; - fassert(16914, ret.get()); - fassert(17003, ret->isValid()); - return ret; + if (it != _userCache.end()) { + fassert(16914, it->second); + fassert(17003, it->second->isValid()); + fassert(17008, it->second->getRefCount() > 0); + it->second->incrementRefCount(); + *acquiredUser = it->second; + return Status::OK(); } + std::unique_ptr<User> user; + int authzVersion = _version; guard.beginFetchPhase(); @@ -440,7 +448,6 @@ StatusWith<UserHandle> AuthorizationManagerImpl::acquireUser(OperationContext* o // after schema upgrades. static const int maxAcquireRetries = 2; Status status = Status::OK(); - std::unique_ptr<User> user; for (int i = 0; i < maxAcquireRetries; ++i) { if (authzVersion == schemaVersionInvalid) { Status status = _externalState->getStoredAuthorizationVersion(opCtx, &authzVersion); @@ -480,50 +487,87 @@ StatusWith<UserHandle> AuthorizationManagerImpl::acquireUser(OperationContext* o guard.endFetchPhase(); + user->incrementRefCount(); + // NOTE: It is not safe to throw an exception from here to the end of the method. if (guard.isSameCacheGeneration()) { + _userCache.insert(std::make_pair(userName, user.get())); if (_version == schemaVersionInvalid) _version = authzVersion; - return _userCache.insertOrAssignAndGet(userName, std::move(user)); } else { // If the cache generation changed while this thread was in fetch mode, the data // associated with the user may now be invalid, so we must mark it as such. The caller // may still opt to use the information for a short while, but not indefinitely. - user->_invalidate(); - return UserHandle(std::move(user)); + user->invalidate(); } + *acquiredUser = user.release(); + + return Status::OK(); } Status AuthorizationManagerImpl::_fetchUserV2(OperationContext* opCtx, const UserName& userName, - std::unique_ptr<User>* out) { + std::unique_ptr<User>* acquiredUser) { BSONObj userObj; Status status = getUserDescription(opCtx, userName, &userObj); if (!status.isOK()) { return status; } - auto user = std::make_unique<User>(userName); + // Put the new user into an unique_ptr temporarily in case there's an error while + // initializing the user. + auto user = stdx::make_unique<User>(userName); status = _initializeUserFromPrivilegeDocument(user.get(), userObj); if (!status.isOK()) { return status; } - - std::swap(*out, user); + acquiredUser->reset(user.release()); return Status::OK(); } +void AuthorizationManagerImpl::releaseUser(User* user) { + if (user == internalSecurity.user) { + return; + } + + CacheGuard guard(this, CacheGuard::fetchSynchronizationManual); + user->decrementRefCount(); + if (user->getRefCount() == 0) { + // If it's been invalidated then it's not in the _userCache anymore. + if (user->isValid()) { + MONGO_COMPILER_VARIABLE_UNUSED bool erased = _userCache.erase(user->getName()); + dassert(erased); + } + delete user; + } +} + void AuthorizationManagerImpl::invalidateUserByName(const UserName& userName) { CacheGuard guard(this, CacheGuard::fetchSynchronizationManual); _updateCacheGeneration_inlock(); - _userCache.invalidate(userName); + stdx::unordered_map<UserName, User*>::iterator it = _userCache.find(userName); + if (it == _userCache.end()) { + return; + } + + User* user = it->second; + _userCache.erase(it); + user->invalidate(); } void AuthorizationManagerImpl::invalidateUsersFromDB(StringData dbname) { CacheGuard guard(this, CacheGuard::fetchSynchronizationManual); _updateCacheGeneration_inlock(); - _userCache.invalidateIf( - [&](const UserName& user, const User*) { return user.getDB() == dbname; }); + stdx::unordered_map<UserName, User*>::iterator it = _userCache.begin(); + while (it != _userCache.end()) { + User* user = it->second; + if (user->getName().getDB() == dbname) { + _userCache.erase(it++); + user->invalidate(); + } else { + ++it; + } + } } void AuthorizationManagerImpl::invalidateUserCache() { @@ -533,7 +577,13 @@ void AuthorizationManagerImpl::invalidateUserCache() { void AuthorizationManagerImpl::_invalidateUserCache_inlock() { _updateCacheGeneration_inlock(); - _userCache.invalidateIf([](const UserName& a, const User*) { return true; }); + for (stdx::unordered_map<UserName, User*>::iterator it = _userCache.begin(); + it != _userCache.end(); + ++it) { + fassert(17266, it->second != internalSecurity.user); + it->second->invalidate(); + } + _userCache.clear(); // Reread the schema version before acquiring the next user. _version = schemaVersionInvalid; @@ -617,7 +667,7 @@ StatusWith<UserName> extractUserNameFromIdString(StringData idstr) { } // namespace void AuthorizationManagerImpl::_updateCacheGeneration_inlock() { - _fetchGeneration = OID::gen(); + _cacheGeneration = OID::gen(); } void AuthorizationManagerImpl::_invalidateRelevantCacheData(const char* op, @@ -663,17 +713,4 @@ void AuthorizationManagerImpl::logOp(OperationContext* opCtx, } } -std::vector<AuthorizationManager::CachedUserInfo> AuthorizationManagerImpl::getUserCacheInfo() - const { - auto cacheData = _userCache.getCacheInfo(); - std::vector<AuthorizationManager::CachedUserInfo> ret; - ret.reserve(cacheData.size()); - std::transform( - cacheData.begin(), cacheData.end(), std::back_inserter(ret), [](const auto& info) { - return AuthorizationManager::CachedUserInfo{info.key, info.active}; - }); - - return ret; -} - } // namespace mongo |