summaryrefslogtreecommitdiff
path: root/src/mongo/db/auth/authorization_manager_impl.cpp
diff options
context:
space:
mode:
authorBen Caimano <ben.caimano@10gen.com>2018-07-31 18:26:07 -0400
committerBen Caimano <ben.caimano@10gen.com>2018-07-31 18:32:19 -0400
commit6711ab3bbc02ca98da1af2fe115f07e37bb076e4 (patch)
treef1859ba3692a982b0afbd06fcb523c830136c25c /src/mongo/db/auth/authorization_manager_impl.cpp
parent35757e8ef3134fad1a09cb09a69882929d9ebb76 (diff)
downloadmongo-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.cpp137
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