summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--src/Common/UserManager.cpp226
-rw-r--r--src/Common/UserManager.h77
-rw-r--r--src/Core/Exception.cpp2
-rw-r--r--src/Core/Exception.h1
-rw-r--r--src/mad-server.cpp3
-rw-r--r--src/madc.cpp1
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 <iostream>
+
namespace Mad {
namespace Common {
@@ -32,24 +34,90 @@ bool UserManager::Compare::operator() (boost::shared_ptr<UserBackend> b1, boost:
boost::shared_ptr<const std::map<unsigned long, UserInfo> > UserManager::getUserList() throw(Core::Exception) {
+ {
+ boost::shared_lock<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(users)
+ return users;
+ else if(userException)
+ throw *userException;
+ }
+ }
+
Core::Exception e(Core::Exception::NOT_IMPLEMENTED);
- for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
- try {
- return (*backend)->getUserList();
+ boost::shared_ptr<const std::map<unsigned long, UserInfo> > ret;
+
+ {
+ boost::lock_guard<boost::shared_mutex> backendLock(backendMutex);
+
+ for(std::set<boost::shared_ptr<UserBackend> >::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<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(ret) {
+ boost::upgrade_to_unique_lock<boost::shared_mutex> upgradeLock(lock);
+ users = ret;
+
+ boost::shared_ptr<std::map<std::string, unsigned long> > names(new std::map<std::string, unsigned long>);
+ for(std::map<unsigned long, UserInfo>::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<const UserInfo> UserManager::getUserInfo(unsigned long uid) throw(Core::Exception) {
+ {
+ boost::shared_lock<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(!users && !userException) {
+ lock.unlock();
+ getUserList();
+ lock.lock();
+ }
+
+ if(caching) {
+ if(users) {
+ std::map<unsigned long, UserInfo>::const_iterator user = users->find(uid);
+ if(user != users->end())
+ return boost::shared_ptr<UserInfo>(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<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
return (*backend)->getUserInfo(uid);
@@ -64,8 +132,34 @@ boost::shared_ptr<const UserInfo> UserManager::getUserInfo(unsigned long uid) th
}
boost::shared_ptr<const UserInfo> UserManager::getUserInfoByName(const std::string &name) throw(Core::Exception) {
+ {
+ boost::shared_lock<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(!users && !userException) {
+ lock.unlock();
+ getUserList();
+ lock.lock();
+ }
+
+ if(caching) {
+ if(userNames) {
+ std::map<std::string, unsigned long>::const_iterator user = userNames->find(name);
+ if(user != userNames->end())
+ return boost::shared_ptr<UserInfo>(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<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
return (*backend)->getUserInfoByName(name);
@@ -82,6 +176,8 @@ boost::shared_ptr<const UserInfo> UserManager::getUserInfoByName(const std::stri
boost::shared_ptr<const std::set<unsigned long> > UserManager::getUserGroupList(unsigned long uid) throw(Core::Exception) {
Core::Exception e(Core::Exception::NOT_IMPLEMENTED);
+ boost::lock_guard<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
return (*backend)->getUserGroupList(uid);
@@ -96,24 +192,90 @@ boost::shared_ptr<const std::set<unsigned long> > UserManager::getUserGroupList(
}
boost::shared_ptr<const std::map<unsigned long, GroupInfo> > UserManager::getGroupList() throw(Core::Exception) {
+ {
+ boost::shared_lock<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(groups)
+ return groups;
+ else if(groupException)
+ throw *groupException;
+ }
+ }
+
Core::Exception e(Core::Exception::NOT_IMPLEMENTED);
- for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
- try {
- return (*backend)->getGroupList();
+ boost::shared_ptr<const std::map<unsigned long, GroupInfo> > ret;
+
+ {
+ boost::lock_guard<boost::shared_mutex> backendLock(backendMutex);
+
+ for(std::set<boost::shared_ptr<UserBackend> >::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<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(ret) {
+ boost::upgrade_to_unique_lock<boost::shared_mutex> upgradeLock(lock);
+ groups = ret;
+
+ boost::shared_ptr<std::map<std::string, unsigned long> > names(new std::map<std::string, unsigned long>);
+ for(std::map<unsigned long, GroupInfo>::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<const GroupInfo> UserManager::getGroupInfo(unsigned long gid) throw(Core::Exception) {
+ {
+ boost::shared_lock<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(!groups && !groupException) {
+ lock.unlock();
+ getGroupList();
+ lock.lock();
+ }
+
+ if(caching) {
+ if(groups) {
+ std::map<unsigned long, GroupInfo>::const_iterator group = groups->find(gid);
+ if(group != groups->end())
+ return boost::shared_ptr<GroupInfo>(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<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
return (*backend)->getGroupInfo(gid);
@@ -128,8 +290,34 @@ boost::shared_ptr<const GroupInfo> UserManager::getGroupInfo(unsigned long gid)
}
boost::shared_ptr<const GroupInfo> UserManager::getGroupInfoByName(const std::string &name) throw(Core::Exception) {
+ {
+ boost::shared_lock<boost::shared_mutex> lock(mutex);
+
+ if(caching) {
+ if(!groups && !groupException) {
+ lock.unlock();
+ getGroupList();
+ lock.lock();
+ }
+
+ if(caching) {
+ if(groupNames) {
+ std::map<std::string, unsigned long>::const_iterator group = groupNames->find(name);
+ if(group != groupNames->end())
+ return boost::shared_ptr<GroupInfo>(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<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
return (*backend)->getGroupInfoByName(name);
@@ -146,6 +334,8 @@ boost::shared_ptr<const GroupInfo> UserManager::getGroupInfoByName(const std::st
boost::shared_ptr<const std::set<unsigned long> > UserManager::getGroupUserList(unsigned long gid) throw(Core::Exception) {
Core::Exception e(Core::Exception::NOT_IMPLEMENTED);
+ boost::lock_guard<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
return (*backend)->getGroupUserList(gid);
@@ -162,9 +352,11 @@ boost::shared_ptr<const std::set<unsigned long> > 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<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::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<boost::shared_mutex> backendLock(backendMutex);
+
for(std::set<boost::shared_ptr<UserBackend> >::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 <map>
#include <set>
-#include <boost/smart_ptr.hpp>
-#include <boost/noncopyable.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
namespace Mad {
namespace Common {
@@ -47,15 +47,82 @@ class UserManager : boost::noncopyable {
std::set<boost::shared_ptr<UserBackend>, Compare> backends;
- UserManager() {}
+ boost::shared_mutex backendMutex;
+ boost::shared_mutex mutex;
+
+ bool caching;
+
+ boost::shared_ptr<const std::map<unsigned long, UserInfo> > users;
+ boost::shared_ptr<const std::map<std::string, unsigned long> > userNames;
+ boost::shared_ptr<Core::Exception> userException;
+
+ boost::shared_ptr<const std::map<unsigned long, GroupInfo> > groups;
+ boost::shared_ptr<const std::map<std::string, unsigned long> > groupNames;
+ boost::shared_ptr<Core::Exception> groupException;
+
+ boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > userGroups;
+ boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > groupUsers;
+ boost::shared_ptr<Core::Exception> userGroupException;
+
+ UserManager() : caching(false) {}
public:
void registerBackend(boost::shared_ptr<UserBackend> backend) {
- backends.insert(backend);
+ {
+ boost::lock_guard<boost::shared_mutex> lock(backendMutex);
+ backends.insert(backend);
+ }
+
+ update();
}
void unregisterBackend(boost::shared_ptr<UserBackend> backend) {
- backends.erase(backend);
+ {
+ boost::lock_guard<boost::shared_mutex> lock(backendMutex);
+ backends.erase(backend);
+ }
+
+ update();
+ }
+
+ bool isCaching() {
+ boost::shared_lock<boost::shared_mutex> lock(mutex);
+ return caching;
+ }
+
+ void setCaching(bool cache) {
+ {
+ boost::lock_guard<boost::shared_mutex> lock(mutex);
+ caching = cache;
+ }
+
+ update();
+ }
+
+ void update(bool refresh = false) {
+ {
+ boost::lock_guard<boost::shared_mutex> 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<const std::map<unsigned long, UserInfo> > 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<Common::Backends::NetworkUserBackend> networkUserBackend(new Common::Backends::NetworkUserBackend(&application, connection));
application.getUserManager()->registerBackend(networkUserBackend);
+ application.getUserManager()->setCaching(true);
Client::CommandParser commandParser(&application, connection);