From 61ac0032dec6cf6d93ca3f2c36af17f93d1682b9 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 25 Jun 2009 21:43:01 +0200 Subject: UserManager: Cache Benutzer- und Gruppen-Liste --- .gitignore | 2 + src/Common/UserManager.cpp | 226 +++++++++++++++++++++++++++++++++++++++++---- src/Common/UserManager.h | 77 ++++++++++++++- src/Core/Exception.cpp | 2 + src/Core/Exception.h | 1 + src/mad-server.cpp | 3 + src/madc.cpp | 1 + 7 files changed, 291 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index eabd1ab..9a5e52a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ Makefile /src/mad /src/madc /src/mad-server + +/src/mad-server.log diff --git a/src/Common/UserManager.cpp b/src/Common/UserManager.cpp index 66cbbf4..342d4bf 100644 --- a/src/Common/UserManager.cpp +++ b/src/Common/UserManager.cpp @@ -20,6 +20,8 @@ #include "UserManager.h" #include "UserBackend.h" +#include + namespace Mad { namespace Common { @@ -32,24 +34,90 @@ bool UserManager::Compare::operator() (boost::shared_ptr b1, boost: boost::shared_ptr > UserManager::getUserList() throw(Core::Exception) { + { + boost::shared_lock lock(mutex); + + if(caching) { + if(users) + return users; + else if(userException) + throw *userException; + } + } + Core::Exception e(Core::Exception::NOT_IMPLEMENTED); - for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { - try { - return (*backend)->getUserList(); + boost::shared_ptr > ret; + + { + boost::lock_guard backendLock(backendMutex); + + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { + try { + ret = (*backend)->getUserList(); + break; + } + catch(Core::Exception e2) { + if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) + e = e2; + } } - catch(Core::Exception e2) { - if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) - e = e2; + } + + { + boost::upgrade_lock lock(mutex); + + if(caching) { + if(ret) { + boost::upgrade_to_unique_lock upgradeLock(lock); + users = ret; + + boost::shared_ptr > names(new std::map); + for(std::map::const_iterator user = users->begin(); user != users->end(); ++user) + names->insert(std::make_pair(user->second.getUsername(), user->first)); + + userNames = names; + } + else + userException.reset(new Core::Exception(e)); } } - throw e; + if(ret) + return ret; + else + throw e; } boost::shared_ptr UserManager::getUserInfo(unsigned long uid) throw(Core::Exception) { + { + boost::shared_lock lock(mutex); + + if(caching) { + if(!users && !userException) { + lock.unlock(); + getUserList(); + lock.lock(); + } + + if(caching) { + if(users) { + std::map::const_iterator user = users->find(uid); + if(user != users->end()) + return boost::shared_ptr(new UserInfo(user->second)); + else + throw Core::Exception(Core::Exception::NOT_FOUND); + } + else if(userException) + throw *userException; + } + } + } + Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { return (*backend)->getUserInfo(uid); @@ -64,8 +132,34 @@ boost::shared_ptr UserManager::getUserInfo(unsigned long uid) th } boost::shared_ptr UserManager::getUserInfoByName(const std::string &name) throw(Core::Exception) { + { + boost::shared_lock lock(mutex); + + if(caching) { + if(!users && !userException) { + lock.unlock(); + getUserList(); + lock.lock(); + } + + if(caching) { + if(userNames) { + std::map::const_iterator user = userNames->find(name); + if(user != userNames->end()) + return boost::shared_ptr(new UserInfo(users->find(user->second)->second)); + else + throw Core::Exception(Core::Exception::NOT_FOUND); + } + else if(userException) + throw *userException; + } + } + } + Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { return (*backend)->getUserInfoByName(name); @@ -82,6 +176,8 @@ boost::shared_ptr UserManager::getUserInfoByName(const std::stri boost::shared_ptr > UserManager::getUserGroupList(unsigned long uid) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { return (*backend)->getUserGroupList(uid); @@ -96,24 +192,90 @@ boost::shared_ptr > UserManager::getUserGroupList( } boost::shared_ptr > UserManager::getGroupList() throw(Core::Exception) { + { + boost::shared_lock lock(mutex); + + if(caching) { + if(groups) + return groups; + else if(groupException) + throw *groupException; + } + } + Core::Exception e(Core::Exception::NOT_IMPLEMENTED); - for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { - try { - return (*backend)->getGroupList(); + boost::shared_ptr > ret; + + { + boost::lock_guard backendLock(backendMutex); + + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { + try { + ret = (*backend)->getGroupList(); + break; + } + catch(Core::Exception e2) { + if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) + e = e2; + } } - catch(Core::Exception e2) { - if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) - e = e2; + } + + { + boost::upgrade_lock lock(mutex); + + if(caching) { + if(ret) { + boost::upgrade_to_unique_lock upgradeLock(lock); + groups = ret; + + boost::shared_ptr > names(new std::map); + for(std::map::const_iterator group = groups->begin(); group != groups->end(); ++group) + names->insert(std::make_pair(group->second.getName(), group->first)); + + groupNames = names; + } + else + groupException.reset(new Core::Exception(e)); } } - throw e; + if(ret) + return ret; + else + throw e; } boost::shared_ptr UserManager::getGroupInfo(unsigned long gid) throw(Core::Exception) { + { + boost::shared_lock lock(mutex); + + if(caching) { + if(!groups && !groupException) { + lock.unlock(); + getGroupList(); + lock.lock(); + } + + if(caching) { + if(groups) { + std::map::const_iterator group = groups->find(gid); + if(group != groups->end()) + return boost::shared_ptr(new GroupInfo(group->second)); + else + throw Core::Exception(Core::Exception::NOT_FOUND); + } + else if(groupException) + throw *groupException; + } + } + } + Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { return (*backend)->getGroupInfo(gid); @@ -128,8 +290,34 @@ boost::shared_ptr UserManager::getGroupInfo(unsigned long gid) } boost::shared_ptr UserManager::getGroupInfoByName(const std::string &name) throw(Core::Exception) { + { + boost::shared_lock lock(mutex); + + if(caching) { + if(!groups && !groupException) { + lock.unlock(); + getGroupList(); + lock.lock(); + } + + if(caching) { + if(groupNames) { + std::map::const_iterator group = groupNames->find(name); + if(group != groupNames->end()) + return boost::shared_ptr(new GroupInfo(groups->find(group->second)->second)); + else + throw Core::Exception(Core::Exception::NOT_FOUND); + } + else if(groupException) + throw *groupException; + } + } + } + Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { return (*backend)->getGroupInfoByName(name); @@ -146,6 +334,8 @@ boost::shared_ptr UserManager::getGroupInfoByName(const std::st boost::shared_ptr > UserManager::getGroupUserList(unsigned long gid) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { return (*backend)->getGroupUserList(gid); @@ -162,9 +352,11 @@ boost::shared_ptr > UserManager::getGroupUserList( void UserManager::setPassword(unsigned long uid, const std::string &password) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return (*backend)->setPassword(uid, password); + (*backend)->setPassword(uid, password); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -178,9 +370,11 @@ void UserManager::setPassword(unsigned long uid, const std::string &password) th void UserManager::addUser(const UserInfo &userInfo) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); + boost::lock_guard backendLock(backendMutex); + for(std::set >::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return (*backend)->addUser(userInfo); + (*backend)->addUser(userInfo); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) diff --git a/src/Common/UserManager.h b/src/Common/UserManager.h index 215fde8..c9b0712 100644 --- a/src/Common/UserManager.h +++ b/src/Common/UserManager.h @@ -28,8 +28,8 @@ #include #include -#include -#include +#include +#include namespace Mad { namespace Common { @@ -47,15 +47,82 @@ class UserManager : boost::noncopyable { std::set, Compare> backends; - UserManager() {} + boost::shared_mutex backendMutex; + boost::shared_mutex mutex; + + bool caching; + + boost::shared_ptr > users; + boost::shared_ptr > userNames; + boost::shared_ptr userException; + + boost::shared_ptr > groups; + boost::shared_ptr > groupNames; + boost::shared_ptr groupException; + + boost::shared_ptr > userGroups; + boost::shared_ptr > groupUsers; + boost::shared_ptr userGroupException; + + UserManager() : caching(false) {} public: void registerBackend(boost::shared_ptr backend) { - backends.insert(backend); + { + boost::lock_guard lock(backendMutex); + backends.insert(backend); + } + + update(); } void unregisterBackend(boost::shared_ptr backend) { - backends.erase(backend); + { + boost::lock_guard lock(backendMutex); + backends.erase(backend); + } + + update(); + } + + bool isCaching() { + boost::shared_lock lock(mutex); + return caching; + } + + void setCaching(bool cache) { + { + boost::lock_guard lock(mutex); + caching = cache; + } + + update(); + } + + void update(bool refresh = false) { + { + boost::lock_guard lock(mutex); + + if(!caching) + return; + + users.reset(); + userNames.reset(); + userException.reset(); + + groups.reset(); + groupNames.reset(); + groupException.reset(); + + userGroups.reset(); + groupUsers.reset(); + userGroupException.reset(); + } + + if(refresh) { + getUserList(); + getGroupList(); + } } boost::shared_ptr > getUserList() throw(Core::Exception); diff --git a/src/Core/Exception.cpp b/src/Core/Exception.cpp index fbae6aa..1a71ebd 100644 --- a/src/Core/Exception.cpp +++ b/src/Core/Exception.cpp @@ -43,6 +43,8 @@ std::string Exception::strerror() const { return ret + "Not finished"; case NOT_IMPLEMENTED: return ret + "Not implemented"; + case NOT_FOUND: + return ret + "Not found"; case INTERNAL_ERRNO: return ret + std::strerror(subCode); case INVALID_ADDRESS: diff --git a/src/Core/Exception.h b/src/Core/Exception.h index 6c89549..4d58190 100644 --- a/src/Core/Exception.h +++ b/src/Core/Exception.h @@ -29,6 +29,7 @@ class Exception { public: enum ErrorCode { SUCCESS = 0x0000, UNEXPECTED_PACKET = 0x0001, INVALID_ACTION = 0x0002, NOT_AVAILABLE = 0x0003, NOT_FINISHED = 0x0004, NOT_IMPLEMENTED = 0x0005, + NOT_FOUND = 0x0006, INTERNAL_ERRNO = 0x0010, INVALID_ADDRESS = 0x0020, ALREADY_IDENTIFIED = 0x0030, UNKNOWN_DAEMON = 0x0031 diff --git a/src/mad-server.cpp b/src/mad-server.cpp index ba42a89..7cac86f 100644 --- a/src/mad-server.cpp +++ b/src/mad-server.cpp @@ -19,6 +19,7 @@ #include "Core/ConfigManager.h" #include "Common/ModuleManager.h" +#include "Common/UserManager.h" #include "Server/Application.h" #include "Server/ConnectionManager.h" @@ -37,6 +38,8 @@ int main() { application.getConfigManager()->loadFile("mad-server.conf"); application.getConfigManager()->finish(); + application.getUserManager()->setCaching(true); + while(true) sleep(1000); diff --git a/src/madc.cpp b/src/madc.cpp index a0cfb61..7738f29 100644 --- a/src/madc.cpp +++ b/src/madc.cpp @@ -81,6 +81,7 @@ int main(int argc, char *argv[]) { boost::shared_ptr networkUserBackend(new Common::Backends::NetworkUserBackend(&application, connection)); application.getUserManager()->registerBackend(networkUserBackend); + application.getUserManager()->setCaching(true); Client::CommandParser commandParser(&application, connection); -- cgit v1.2.3