diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Common/Backends/NetworkUserBackend.cpp | 193 | ||||
-rw-r--r-- | src/Common/Backends/NetworkUserBackend.h | 44 | ||||
-rw-r--r-- | src/Common/UserBackend.h | 19 | ||||
-rw-r--r-- | src/Common/UserCache.cpp | 209 | ||||
-rw-r--r-- | src/Common/UserCache.h | 29 | ||||
-rw-r--r-- | src/Common/UserManager.cpp | 36 | ||||
-rw-r--r-- | src/Common/UserManager.h | 18 | ||||
-rw-r--r-- | src/Server/RequestHandlers/UserRequestHandlerGroup.cpp | 191 | ||||
-rw-r--r-- | src/modules/UserBackendMysql/UserBackendMysql.cpp | 81 | ||||
-rw-r--r-- | src/modules/UserBackendMysql/UserBackendMysql.h | 22 |
11 files changed, 587 insertions, 257 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 50edfaf..d884224 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ find_package(DL REQUIRED) find_package(Readline REQUIRED) #find_package(KRB5 REQUIRED gssapi) find_package(OpenSSL REQUIRED) -find_package(Boost REQUIRED regex signals system thread) +find_package(Boost REQUIRED date_time regex signals system thread) find_package(MySQL) configure_file(${MAD_SOURCE_DIR}/config.h.in ${MAD_BINARY_DIR}/config.h) diff --git a/src/Common/Backends/NetworkUserBackend.cpp b/src/Common/Backends/NetworkUserBackend.cpp index f75783c..27f65f5 100644 --- a/src/Common/Backends/NetworkUserBackend.cpp +++ b/src/Common/Backends/NetworkUserBackend.cpp @@ -20,15 +20,30 @@ #include "NetworkUserBackend.h" #include "../RequestManager.h" +#include <boost/date_time/posix_time/posix_time.hpp> + namespace Mad { namespace Common { namespace Backends { +void NetworkUserBackend::SimpleUserRequest::sendRequest() { + Common::XmlPacket packet; + packet.setType(type); + + if(!timestamp.is_not_a_date_time()) + packet.set("timestamp", boost::posix_time::to_iso_string(timestamp)); + + sendPacket(packet); +} + void NetworkUserBackend::IdUserRequest::sendRequest() { Common::XmlPacket packet; packet.setType(type); packet.set(idType, id); + if(!timestamp.is_not_a_date_time()) + packet.set("timestamp", boost::posix_time::to_iso_string(timestamp)); + sendPacket(packet); } @@ -37,22 +52,33 @@ void NetworkUserBackend::NameUserRequest::sendRequest() { packet.setType(type); packet.set("name", name); + if(!timestamp.is_not_a_date_time()) + packet.set("timestamp", boost::posix_time::to_iso_string(timestamp)); + sendPacket(packet); } -boost::shared_ptr<const std::map<unsigned long, UserInfo> > NetworkUserBackend::getUserList() throw(Core::Exception) { - boost::shared_ptr<SimpleUserRequest> request(new SimpleUserRequest(application, "ListUsers")); +boost::shared_ptr<const std::map<unsigned long, UserInfo> > NetworkUserBackend::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<SimpleUserRequest> request(new SimpleUserRequest(application, "ListUsers", timestamp)); application->getRequestManager()->sendRequest(connection, request); + request->wait(); std::pair<boost::shared_ptr<const XmlPacket>, Core::Exception> result = request->getResult(); if(!result.first || result.second) throw result.second; - boost::shared_ptr<std::map<unsigned long, UserInfo> > userList(new std::map<unsigned long, UserInfo>); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } const XmlPacket::List *users = result.first->getList("users"); if(users) { + boost::shared_ptr<std::map<unsigned long, UserInfo> > userList(new std::map<unsigned long, UserInfo>); + for(XmlPacket::List::const_iterator user = users->begin(); user != users->end(); ++user) { UserInfo userInfo(user->get<unsigned long>("uid"), user->get<const std::string&>("username")); userInfo.setGid(user->get<unsigned long>("gid")); @@ -60,13 +86,15 @@ boost::shared_ptr<const std::map<unsigned long, UserInfo> > NetworkUserBackend:: userList->insert(std::make_pair(userInfo.getUid(), userInfo)); } + + return userList; } - return userList; + return boost::shared_ptr<const std::map<unsigned long, UserInfo> >(); } -boost::shared_ptr<const UserInfo> NetworkUserBackend::getUserInfo(unsigned long uid) throw(Core::Exception) { - boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "GetUserInfo", "uid", uid)); +boost::shared_ptr<const UserInfo> NetworkUserBackend::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "GetUserInfo", "uid", uid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -74,15 +102,29 @@ boost::shared_ptr<const UserInfo> NetworkUserBackend::getUserInfo(unsigned long if(!result.first || result.second) throw result.second; - boost::shared_ptr<UserInfo> userInfo(new UserInfo(result.first->get<unsigned long>("uid"), result.first->get<const std::string&>("username"))); - userInfo->setGid(result.first->get<unsigned long>("gid")); - userInfo->setFullName(result.first->get<const std::string&>("fullName")); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } + + unsigned long uid2 = result.first->get<unsigned long>("uid"); - return userInfo; + if(uid2) { + boost::shared_ptr<UserInfo> userInfo(new UserInfo(uid2, result.first->get<const std::string&>("username"))); + + userInfo->setGid(result.first->get<unsigned long>("gid")); + userInfo->setFullName(result.first->get<const std::string&>("fullName")); + + return userInfo; + } + + return boost::shared_ptr<const UserInfo>(); } -boost::shared_ptr<const UserInfo> NetworkUserBackend::getUserInfoByName(const std::string &name) throw(Core::Exception) { - boost::shared_ptr<NameUserRequest> request(new NameUserRequest(application, "GetUserInfo", name)); +boost::shared_ptr<const UserInfo> NetworkUserBackend::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<NameUserRequest> request(new NameUserRequest(application, "GetUserInfo", name, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -90,15 +132,29 @@ boost::shared_ptr<const UserInfo> NetworkUserBackend::getUserInfoByName(const st if(!result.first || result.second) throw result.second; - boost::shared_ptr<UserInfo> userInfo(new UserInfo(result.first->get<unsigned long>("uid"), result.first->get<const std::string&>("username"))); - userInfo->setGid(result.first->get<unsigned long>("gid")); - userInfo->setFullName(result.first->get<const std::string&>("fullName")); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } + + unsigned long uid = result.first->get<unsigned long>("uid"); + + if(uid) { + boost::shared_ptr<UserInfo> userInfo(new UserInfo(uid, result.first->get<const std::string&>("username"))); + + userInfo->setGid(result.first->get<unsigned long>("gid")); + userInfo->setFullName(result.first->get<const std::string&>("fullName")); - return userInfo; + return userInfo; + } + + return boost::shared_ptr<const UserInfo>(); } -boost::shared_ptr<const std::set<unsigned long> > NetworkUserBackend::getUserGroupList(unsigned long uid) throw(Core::Exception) { - boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "ListUserGroups", "uid", uid)); +boost::shared_ptr<const std::set<unsigned long> > NetworkUserBackend::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "ListUserGroups", "uid", uid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -106,19 +162,29 @@ boost::shared_ptr<const std::set<unsigned long> > NetworkUserBackend::getUserGro if(!result.first || result.second) throw result.second; - boost::shared_ptr<std::set<unsigned long> > groupList(new std::set<unsigned long>); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } const XmlPacket::List *groups = result.first->getList("groups"); + if(groups) { + boost::shared_ptr<std::set<unsigned long> > groupList(new std::set<unsigned long>); + for(XmlPacket::List::const_iterator group = groups->begin(); group != groups->end(); ++group) groupList->insert(group->get<unsigned long>("gid")); + + return groupList; } - return groupList; + return boost::shared_ptr<const std::set<unsigned long> >(); } -boost::shared_ptr<const std::map<unsigned long, GroupInfo> > NetworkUserBackend::getGroupList() throw(Core::Exception) { - boost::shared_ptr<SimpleUserRequest> request(new SimpleUserRequest(application, "ListGroups")); +boost::shared_ptr<const std::map<unsigned long, GroupInfo> > NetworkUserBackend::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<SimpleUserRequest> request(new SimpleUserRequest(application, "ListGroups", timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -126,21 +192,30 @@ boost::shared_ptr<const std::map<unsigned long, GroupInfo> > NetworkUserBackend: if(!result.first || result.second) throw result.second; - boost::shared_ptr<std::map<unsigned long, GroupInfo> > groupList(new std::map<unsigned long, GroupInfo>); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } const XmlPacket::List *groups = result.first->getList("groups"); if(groups) { + boost::shared_ptr<std::map<unsigned long, GroupInfo> > groupList(new std::map<unsigned long, GroupInfo>); + for(XmlPacket::List::const_iterator group = groups->begin(); group != groups->end(); ++group) { GroupInfo groupInfo(group->get<unsigned long>("gid"), group->get<const std::string&>("name")); groupList->insert(std::make_pair(groupInfo.getGid(), groupInfo)); } + + return groupList; } - return groupList; + return boost::shared_ptr<const std::map<unsigned long, GroupInfo> >(); } -boost::shared_ptr<const GroupInfo> NetworkUserBackend::getGroupInfo(unsigned long gid) throw(Core::Exception) { - boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "GetGroupInfo", "gid", gid)); +boost::shared_ptr<const GroupInfo> NetworkUserBackend::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "GetGroupInfo", "gid", gid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -148,13 +223,23 @@ boost::shared_ptr<const GroupInfo> NetworkUserBackend::getGroupInfo(unsigned lon if(!result.first || result.second) throw result.second; - boost::shared_ptr<GroupInfo> groupInfo(new GroupInfo(result.first->get<unsigned long>("gid"), result.first->get<const std::string&>("name"))); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } + + unsigned long gid2 = result.first->get<unsigned long>("gid"); - return groupInfo; + if(gid2) + return boost::shared_ptr<GroupInfo>(new GroupInfo(gid2, result.first->get<const std::string&>("name"))); + + return boost::shared_ptr<const GroupInfo>(); } -boost::shared_ptr<const GroupInfo> NetworkUserBackend::getGroupInfoByName(const std::string &name) throw(Core::Exception) { - boost::shared_ptr<NameUserRequest> request(new NameUserRequest(application, "GetGroupInfo", name)); +boost::shared_ptr<const GroupInfo> NetworkUserBackend::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<NameUserRequest> request(new NameUserRequest(application, "GetGroupInfo", name, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -162,13 +247,23 @@ boost::shared_ptr<const GroupInfo> NetworkUserBackend::getGroupInfoByName(const if(!result.first || result.second) throw result.second; - boost::shared_ptr<GroupInfo> groupInfo(new GroupInfo(result.first->get<unsigned long>("gid"), result.first->get<const std::string&>("name"))); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } + + unsigned long gid = result.first->get<unsigned long>("gid"); - return groupInfo; + if(gid) + return boost::shared_ptr<GroupInfo>(new GroupInfo(gid, result.first->get<const std::string&>("name"))); + + return boost::shared_ptr<const GroupInfo>(); } -boost::shared_ptr<const std::set<unsigned long> > NetworkUserBackend::getGroupUserList(unsigned long gid) throw(Core::Exception) { - boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "ListGroupUsers", "gid", gid)); +boost::shared_ptr<const std::set<unsigned long> > NetworkUserBackend::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<IdUserRequest> request(new IdUserRequest(application, "ListGroupUsers", "gid", gid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -176,20 +271,29 @@ boost::shared_ptr<const std::set<unsigned long> > NetworkUserBackend::getGroupUs if(!result.first || result.second) throw result.second; - boost::shared_ptr<std::set<unsigned long> > userList(new std::set<unsigned long>); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } const XmlPacket::List *users = result.first->getList("users"); if(users) { + boost::shared_ptr<std::set<unsigned long> > userList(new std::set<unsigned long>); + for(XmlPacket::List::const_iterator user = users->begin(); user != users->end(); ++user) { userList->insert(user->get<unsigned long>("uid")); } + + return userList; } - return userList; + return boost::shared_ptr<const std::set<unsigned long> >(); } -boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > NetworkUserBackend::getFullUserGroupList() throw(Core::Exception) { - boost::shared_ptr<SimpleUserRequest> request(new SimpleUserRequest(application, "GetFullUserGroupList")); +boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > NetworkUserBackend::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr<SimpleUserRequest> request(new SimpleUserRequest(application, "GetFullUserGroupList", timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -197,15 +301,24 @@ boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > NetworkUse if(!result.first || result.second) throw result.second; - boost::shared_ptr<std::multimap<unsigned long, unsigned long> > ret(new std::multimap<unsigned long, unsigned long>); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get<const std::string&>("timestamp")); + } + catch(...) {} + } const XmlPacket::List *list = result.first->getList("userGroupList"); if(list) { + boost::shared_ptr<std::multimap<unsigned long, unsigned long> > ret(new std::multimap<unsigned long, unsigned long>); + for(XmlPacket::List::const_iterator entry = list->begin(); entry != list->end(); ++entry) ret->insert(std::make_pair(entry->get<unsigned long>("uid"), entry->get<unsigned long>("gid"))); + + return ret; } - return ret; + return boost::shared_ptr<const std::multimap<unsigned long, unsigned long> >(); } diff --git a/src/Common/Backends/NetworkUserBackend.h b/src/Common/Backends/NetworkUserBackend.h index 66be909..8faa8e3 100644 --- a/src/Common/Backends/NetworkUserBackend.h +++ b/src/Common/Backends/NetworkUserBackend.h @@ -21,7 +21,7 @@ #define MAD_COMMON_BACKENDS_NETWORKUSERBACKEND_H_ #include "../UserBackend.h" -#include "../Requests/SimpleRequest.h" +#include "../Request.h" namespace Mad { namespace Common { @@ -29,9 +29,17 @@ namespace Backends { class NetworkUserBackend : public UserBackend { private: - class SimpleUserRequest : public Requests::SimpleRequest { + class SimpleUserRequest : public Request { + private: + std::string type; + boost::posix_time::ptime timestamp; + + protected: + virtual void sendRequest(); + public: - SimpleUserRequest(Application *application, const std::string &type) : SimpleRequest(application, type) {} + SimpleUserRequest(Application *application, const std::string &type0, boost::posix_time::ptime *timestamp0) + : Request(application), type(type0), timestamp(timestamp0 ? *timestamp0 : boost::posix_time::not_a_date_time) {} }; class IdUserRequest : public Request { @@ -39,45 +47,45 @@ class NetworkUserBackend : public UserBackend { std::string type; std::string idType; unsigned long id; - + boost::posix_time::ptime timestamp; protected: virtual void sendRequest(); public: - IdUserRequest(Application *application, const std::string &type0, const std::string &idType0, unsigned long id0) - : Request(application), type(type0), idType(idType0), id(id0) {} + IdUserRequest(Application *application, const std::string &type0, const std::string &idType0, unsigned long id0, boost::posix_time::ptime *timestamp0) + : Request(application), type(type0), idType(idType0), id(id0), timestamp(timestamp0 ? *timestamp0 : boost::posix_time::not_a_date_time) {} }; class NameUserRequest : public Request { private: std::string type; std::string name; - + boost::posix_time::ptime timestamp; protected: virtual void sendRequest(); public: - NameUserRequest(Application *application, const std::string &type0, const std::string &name0) - : Request(application), type(type0), name(name0) {} + NameUserRequest(Application *application, const std::string &type0, const std::string &name0, boost::posix_time::ptime *timestamp0) + : Request(application), type(type0), name(name0), timestamp(timestamp0 ? *timestamp0 : boost::posix_time::not_a_date_time) {} }; Application *application; Connection *connection; protected: - virtual boost::shared_ptr<const std::map<unsigned long, UserInfo> > getUserList() throw(Core::Exception); - virtual boost::shared_ptr<const UserInfo> getUserInfo(unsigned long uid) throw(Core::Exception); - virtual boost::shared_ptr<const UserInfo> getUserInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid) throw(Core::Exception); + virtual boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::UserInfo> getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::UserInfo> getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr<const std::map<unsigned long, GroupInfo> > getGroupList() throw(Core::Exception); - virtual boost::shared_ptr<const GroupInfo> getGroupInfo(unsigned long gid) throw(Core::Exception); - virtual boost::shared_ptr<const GroupInfo> getGroupInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid) throw(Core::Exception); + virtual boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::GroupInfo> getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::GroupInfo> getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList() throw(Core::Exception); + virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); //virtual void setPassword(unsigned long uid, const std::string &password) throw(Core::Exception); //virtual void addUser(const UserInfo &userInfo) throw(Core::Exception); diff --git a/src/Common/UserBackend.h b/src/Common/UserBackend.h index 829aae7..4004dbc 100644 --- a/src/Common/UserBackend.h +++ b/src/Common/UserBackend.h @@ -31,6 +31,7 @@ #include <set> #include <string> +#include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/smart_ptr.hpp> @@ -47,40 +48,40 @@ class UserBackend { UserBackend() {} - virtual boost::shared_ptr<const std::map<unsigned long, UserInfo> > getUserList() throw(Core::Exception) { + virtual boost::shared_ptr<const std::map<unsigned long, UserInfo> > getUserList(boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const UserInfo> getUserInfo(unsigned long uid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr<const UserInfo> getUserInfo(unsigned long uid _UNUSED_PARAMETER_, boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const UserInfo> getUserInfoByName(const std::string &name _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr<const UserInfo> getUserInfoByName(const std::string &name _UNUSED_PARAMETER_, boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid _UNUSED_PARAMETER_, boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const std::map<unsigned long, GroupInfo> > getGroupList() throw(Core::Exception) { + virtual boost::shared_ptr<const std::map<unsigned long, GroupInfo> > getGroupList(boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const GroupInfo> getGroupInfo(unsigned long gid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr<const GroupInfo> getGroupInfo(unsigned long gid _UNUSED_PARAMETER_, boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const GroupInfo> getGroupInfoByName(const std::string &name _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr<const GroupInfo> getGroupInfoByName(const std::string &name _UNUSED_PARAMETER_, boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid _UNUSED_PARAMETER_, boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList() throw(Core::Exception) { + virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList(boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } diff --git a/src/Common/UserCache.cpp b/src/Common/UserCache.cpp index 887e375..a32bcd3 100644 --- a/src/Common/UserCache.cpp +++ b/src/Common/UserCache.cpp @@ -23,40 +23,50 @@ namespace Mad { namespace Common { -boost::shared_ptr<const std::map<unsigned long, UserInfo> > UserCache::getUserList() throw(Core::Exception) { - boost::lock_guard<boost::shared_mutex> lock(mutex); - - if(users) { - application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Using cached user list"); - return users; - } - else if(userException) { - application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Error cached"); - throw userException; - } +boost::shared_ptr<const std::map<unsigned long, UserInfo> > UserCache::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); try { - users = backend->getUserList(); - - userNames.reset(new std::map<std::string, unsigned long>); - for(std::map<unsigned long, UserInfo>::const_iterator user = users->begin(); user != users->end(); ++user) - userNames->insert(std::make_pair(user->second.getUsername(), user->first)); - - return users; + boost::shared_ptr<const std::map<unsigned long, UserInfo> > newUsers = backend->getUserList(&userTime); + + if(newUsers) { + users = newUsers; + userException = Core::Exception(); + + userNames.reset(new std::map<std::string, unsigned long>); + for(std::map<unsigned long, UserInfo>::const_iterator user = users->begin(); user != users->end(); ++user) + userNames->insert(std::make_pair(user->second.getUsername(), user->first)); + } + else { + if(users) + application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Using cached user list"); + else + application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Error cached"); + } } catch(Core::Exception e) { + users.reset(); userException = e; - throw userException; } -} -boost::shared_ptr<const UserInfo> UserCache::getUserInfo(unsigned long uid) throw(Core::Exception) { - getUserList(); + if((!timestamp) || timestamp->is_not_a_date_time() || (*timestamp < userTime)) { + if(timestamp) + *timestamp = userTime; + + if(users) + return users; + else + throw userException; + } + + return boost::shared_ptr<const std::map<unsigned long, UserInfo> >(); +} - boost::lock_guard<boost::shared_mutex> lock(mutex); +boost::shared_ptr<const UserInfo> UserCache::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); - if(!users) - throw userException; + if(!getUserList(timestamp)) + return boost::shared_ptr<const UserInfo>(); std::map<unsigned long, UserInfo>::const_iterator user = users->find(uid); @@ -66,13 +76,11 @@ boost::shared_ptr<const UserInfo> UserCache::getUserInfo(unsigned long uid) thro return boost::shared_ptr<UserInfo>(new UserInfo(user->second)); } -boost::shared_ptr<const UserInfo> UserCache::getUserInfoByName(const std::string &name) throw(Core::Exception) { - getUserList(); +boost::shared_ptr<const UserInfo> UserCache::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); - boost::lock_guard<boost::shared_mutex> lock(mutex); - - if(!users) - throw userException; + if(!getUserList(timestamp)) + return boost::shared_ptr<const UserInfo>(); std::map<std::string, unsigned long>::const_iterator uid = userNames->find(name); if(uid == userNames->end()) @@ -83,13 +91,11 @@ boost::shared_ptr<const UserInfo> UserCache::getUserInfoByName(const std::string return boost::shared_ptr<UserInfo>(new UserInfo(user->second)); } -boost::shared_ptr<const std::set<unsigned long> > UserCache::getUserGroupList(unsigned long uid) throw(Core::Exception) { - getFullUserGroupList(); - - boost::lock_guard<boost::shared_mutex> lock(mutex); +boost::shared_ptr<const std::set<unsigned long> > UserCache::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); - if(!userGroups) - throw userGroupException; + if(!getFullUserGroupList(timestamp)) + return boost::shared_ptr<const std::set<unsigned long> >(); std::pair<std::multimap<unsigned long, unsigned long>::const_iterator, std::multimap<unsigned long, unsigned long>::const_iterator> range = userGroups->equal_range(uid); @@ -102,40 +108,50 @@ boost::shared_ptr<const std::set<unsigned long> > UserCache::getUserGroupList(un } -boost::shared_ptr<const std::map<unsigned long, GroupInfo> > UserCache::getGroupList() throw(Core::Exception) { - boost::lock_guard<boost::shared_mutex> lock(mutex); - - if(groups) { - application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Using cached group list"); - return groups; - } - else if(groupException) { - application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Error cached"); - throw groupException; - } +boost::shared_ptr<const std::map<unsigned long, GroupInfo> > UserCache::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); try { - groups = backend->getGroupList(); - - groupNames.reset(new std::map<std::string, unsigned long>); - for(std::map<unsigned long, GroupInfo>::const_iterator group = groups->begin(); group != groups->end(); ++group) - groupNames->insert(std::make_pair(group->second.getName(), group->first)); - - return groups; + boost::shared_ptr<const std::map<unsigned long, GroupInfo> > newGroups = backend->getGroupList(&groupTime); + + if(newGroups) { + groups = newGroups; + groupException = Core::Exception(); + + groupNames.reset(new std::map<std::string, unsigned long>); + for(std::map<unsigned long, GroupInfo>::const_iterator group = groups->begin(); group != groups->end(); ++group) + groupNames->insert(std::make_pair(group->second.getName(), group->first)); + } + else { + if(groups) + application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Using cached group list"); + else + application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Error cached"); + } } catch(Core::Exception e) { + groups.reset(); groupException = e; - throw groupException; } -} -boost::shared_ptr<const GroupInfo> UserCache::getGroupInfo(unsigned long gid) throw(Core::Exception) { - getGroupList(); + if((!timestamp) || timestamp->is_not_a_date_time() || (*timestamp < groupTime)) { + if(timestamp) + *timestamp = groupTime; + + if(groups) + return groups; + else + throw groupException; + } + + return boost::shared_ptr<const std::map<unsigned long, GroupInfo> >(); +} - boost::lock_guard<boost::shared_mutex> lock(mutex); +boost::shared_ptr<const GroupInfo> UserCache::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); - if(!groups) - throw groupException; + if(!getGroupList(timestamp)) + return boost::shared_ptr<const GroupInfo>(); std::map<unsigned long, GroupInfo>::const_iterator group = groups->find(gid); @@ -145,13 +161,11 @@ boost::shared_ptr<const GroupInfo> UserCache::getGroupInfo(unsigned long gid) th return boost::shared_ptr<GroupInfo>(new GroupInfo(group->second)); } -boost::shared_ptr<const GroupInfo> UserCache::getGroupInfoByName(const std::string &name) throw(Core::Exception) { - getGroupList(); +boost::shared_ptr<const GroupInfo> UserCache::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); - boost::lock_guard<boost::shared_mutex> lock(mutex); - - if(!groups) - throw groupException; + if(!getGroupList(timestamp)) + return boost::shared_ptr<const GroupInfo>(); std::map<std::string, unsigned long>::const_iterator gid = groupNames->find(name); if(gid == groupNames->end()) @@ -162,13 +176,11 @@ boost::shared_ptr<const GroupInfo> UserCache::getGroupInfoByName(const std::stri return boost::shared_ptr<GroupInfo>(new GroupInfo(group->second)); } -boost::shared_ptr<const std::set<unsigned long> > UserCache::getGroupUserList(unsigned long gid) throw(Core::Exception) { - getFullUserGroupList(); - - boost::lock_guard<boost::shared_mutex> lock(mutex); +boost::shared_ptr<const std::set<unsigned long> > UserCache::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); - if(!userGroups) - throw userGroupException; + if(!getFullUserGroupList(timestamp)) + return boost::shared_ptr<const std::set<unsigned long> >(); std::pair<std::multimap<unsigned long, unsigned long>::iterator, std::multimap<unsigned long, unsigned long>::iterator> range = groupUsers->equal_range(gid); @@ -180,30 +192,43 @@ boost::shared_ptr<const std::set<unsigned long> > UserCache::getGroupUserList(un return users; } -boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserCache::getFullUserGroupList() throw(Core::Exception) { - boost::lock_guard<boost::shared_mutex> lock(mutex); +boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserCache::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard<boost::recursive_mutex> lock(mutex); - if(userGroups) { - application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Using cached user-group table"); - return userGroups; - } - else if(userGroupException) { - application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Error cached"); - throw userGroupException; - } try { - userGroups = backend->getFullUserGroupList(); - - groupUsers.reset(new std::multimap<unsigned long, unsigned long>); - for(std::multimap<unsigned long, unsigned long>::const_iterator usergroup = userGroups->begin(); usergroup != userGroups->end(); ++usergroup) - groupUsers->insert(std::make_pair(usergroup->second, usergroup->first)); - - return userGroups; + boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > newUserGroups = backend->getFullUserGroupList(&userGroupTime); + + if(newUserGroups) { + userGroups = newUserGroups; + userGroupException = Core::Exception(); + + groupUsers.reset(new std::multimap<unsigned long, unsigned long>); + for(std::multimap<unsigned long, unsigned long>::const_iterator usergroup = userGroups->begin(); usergroup != userGroups->end(); ++usergroup) + groupUsers->insert(std::make_pair(usergroup->second, usergroup->first)); + } + else { + if(userGroups) + application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Using cached user-group table"); + else + application->log(Core::LoggerBase::USER, Core::LoggerBase::DEBUG, "Error cached"); + } } catch(Core::Exception e) { + userGroups.reset(); userGroupException = e; - throw userGroupException; } + + if((!timestamp) || timestamp->is_not_a_date_time() || (*timestamp < userTime)) { + if(timestamp) + *timestamp = userGroupTime; + + if(userGroups) + return userGroups; + else + throw userGroupException; + } + + return boost::shared_ptr<const std::multimap<unsigned long, unsigned long> >(); } } diff --git a/src/Common/UserCache.h b/src/Common/UserCache.h index 548be2e..0fe26be 100644 --- a/src/Common/UserCache.h +++ b/src/Common/UserCache.h @@ -24,7 +24,7 @@ #include <limits> -#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/recursive_mutex.hpp> namespace Mad { namespace Common { @@ -40,32 +40,35 @@ class UserCache : public UserBackend, private boost::noncopyable { boost::shared_ptr<UserBackend> backend; - boost::shared_mutex mutex; + boost::recursive_mutex mutex; boost::shared_ptr<const std::map<unsigned long, UserInfo> > users; boost::shared_ptr<std::map<std::string, unsigned long> > userNames; Core::Exception userException; + boost::posix_time::ptime userTime; boost::shared_ptr<const std::map<unsigned long, GroupInfo> > groups; boost::shared_ptr<std::map<std::string, unsigned long> > groupNames; Core::Exception groupException; + boost::posix_time::ptime groupTime; boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > userGroups; boost::shared_ptr<std::multimap<unsigned long, unsigned long> > groupUsers; Core::Exception userGroupException; + boost::posix_time::ptime userGroupTime; protected: - virtual boost::shared_ptr<const std::map<unsigned long, UserInfo> > getUserList() throw(Core::Exception); - virtual boost::shared_ptr<const UserInfo> getUserInfo(unsigned long uid) throw(Core::Exception); - virtual boost::shared_ptr<const UserInfo> getUserInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid) throw(Core::Exception); + virtual boost::shared_ptr<const std::map<unsigned long, UserInfo> > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const UserInfo> getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const UserInfo> getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr<const std::map<unsigned long, GroupInfo> > getGroupList() throw(Core::Exception); - virtual boost::shared_ptr<const GroupInfo> getGroupInfo(unsigned long gid) throw(Core::Exception); - virtual boost::shared_ptr<const GroupInfo> getGroupInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid) throw(Core::Exception); + virtual boost::shared_ptr<const std::map<unsigned long, GroupInfo> > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const GroupInfo> getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const GroupInfo> getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList() throw(Core::Exception); + virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); virtual void setPassword(unsigned long uid, const std::string &password) throw(Core::Exception) { backend->setPassword(uid, password); @@ -75,7 +78,9 @@ class UserCache : public UserBackend, private boost::noncopyable { backend->addUser(userInfo); } - UserCache(Application *application0, boost::shared_ptr<UserBackend> backend0) : application(application0), backend(backend0) {} + UserCache(Application *application0, boost::shared_ptr<UserBackend> backend0) : application(application0), backend(backend0), + userTime(boost::posix_time::not_a_date_time), groupTime(boost::posix_time::not_a_date_time), + userGroupTime(boost::posix_time::not_a_date_time) {} }; } diff --git a/src/Common/UserManager.cpp b/src/Common/UserManager.cpp index 1b20395..4031140 100644 --- a/src/Common/UserManager.cpp +++ b/src/Common/UserManager.cpp @@ -41,14 +41,14 @@ void UserManager::registerBackendCached(boost::shared_ptr<UserBackend> backend) } -boost::shared_ptr<const std::map<unsigned long, UserInfo> > UserManager::getUserList() throw(Core::Exception) { +boost::shared_ptr<const std::map<unsigned long, UserInfo> > UserManager::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getUserList(); + return backend->second->getUserList(timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -59,14 +59,14 @@ boost::shared_ptr<const std::map<unsigned long, UserInfo> > UserManager::getUser throw e; } -boost::shared_ptr<const UserInfo> UserManager::getUserInfo(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr<const UserInfo> UserManager::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getUserInfo(uid); + return backend->second->getUserInfo(uid, timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -77,14 +77,14 @@ boost::shared_ptr<const UserInfo> UserManager::getUserInfo(unsigned long uid) th throw e; } -boost::shared_ptr<const UserInfo> UserManager::getUserInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr<const UserInfo> UserManager::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getUserInfoByName(name); + return backend->second->getUserInfoByName(name, timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -95,14 +95,14 @@ boost::shared_ptr<const UserInfo> UserManager::getUserInfoByName(const std::stri throw e; } -boost::shared_ptr<const std::set<unsigned long> > UserManager::getUserGroupList(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr<const std::set<unsigned long> > UserManager::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getUserGroupList(uid); + return backend->second->getUserGroupList(uid, timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -113,7 +113,7 @@ boost::shared_ptr<const std::set<unsigned long> > UserManager::getUserGroupList( throw e; } -boost::shared_ptr<const std::map<unsigned long, GroupInfo> > UserManager::getGroupList() throw(Core::Exception) { +boost::shared_ptr<const std::map<unsigned long, GroupInfo> > UserManager::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::shared_ptr<const std::map<unsigned long, GroupInfo> > ret; @@ -123,7 +123,7 @@ boost::shared_ptr<const std::map<unsigned long, GroupInfo> > UserManager::getGro for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getGroupList(); + return backend->second->getGroupList(timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -135,14 +135,14 @@ boost::shared_ptr<const std::map<unsigned long, GroupInfo> > UserManager::getGro throw e; } -boost::shared_ptr<const GroupInfo> UserManager::getGroupInfo(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr<const GroupInfo> UserManager::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getGroupInfo(gid); + return backend->second->getGroupInfo(gid, timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -153,14 +153,14 @@ boost::shared_ptr<const GroupInfo> UserManager::getGroupInfo(unsigned long gid) throw e; } -boost::shared_ptr<const GroupInfo> UserManager::getGroupInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr<const GroupInfo> UserManager::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getGroupInfoByName(name); + return backend->second->getGroupInfoByName(name, timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -171,14 +171,14 @@ boost::shared_ptr<const GroupInfo> UserManager::getGroupInfoByName(const std::st throw e; } -boost::shared_ptr<const std::set<unsigned long> > UserManager::getGroupUserList(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr<const std::set<unsigned long> > UserManager::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getGroupUserList(gid); + return backend->second->getGroupUserList(gid, timestamp); } catch(Core::Exception e2) { if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) @@ -189,14 +189,14 @@ boost::shared_ptr<const std::set<unsigned long> > UserManager::getGroupUserList( throw e; } -boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserManager::getFullUserGroupList() throw(Core::Exception) { +boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserManager::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard<boost::shared_mutex> lock(mutex); for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) { try { - return backend->second->getFullUserGroupList(); + return backend->second->getFullUserGroupList(timestamp); } 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 c545f01..5877bac 100644 --- a/src/Common/UserManager.h +++ b/src/Common/UserManager.h @@ -69,17 +69,17 @@ class UserManager : private boost::noncopyable { backends.erase(backend); } - boost::shared_ptr<const std::map<unsigned long, UserInfo> > getUserList() throw(Core::Exception); - boost::shared_ptr<const UserInfo> getUserInfo(unsigned long uid) throw(Core::Exception); - boost::shared_ptr<const UserInfo> getUserInfoByName(const std::string &name) throw(Core::Exception); - boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid) throw(Core::Exception); + boost::shared_ptr<const std::map<unsigned long, UserInfo> > getUserList(boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr<const UserInfo> getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr<const UserInfo> getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); - boost::shared_ptr<const std::map<unsigned long, GroupInfo> > getGroupList() throw(Core::Exception); - boost::shared_ptr<const GroupInfo> getGroupInfo(unsigned long gid) throw(Core::Exception); - boost::shared_ptr<const GroupInfo> getGroupInfoByName(const std::string &name) throw(Core::Exception); - boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid) throw(Core::Exception); + boost::shared_ptr<const std::map<unsigned long, GroupInfo> > getGroupList(boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr<const GroupInfo> getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr<const GroupInfo> getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); - boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList() throw(Core::Exception); + boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList(boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); void setPassword(unsigned long uid, const std::string &password) throw(Core::Exception); diff --git a/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp b/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp index d579480..292e887 100644 --- a/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp +++ b/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp @@ -17,99 +17,196 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <config.h> + #include "UserRequestHandlerGroup.h" #include "../Application.h" + #include <Common/UserManager.h> +#include <boost/date_time/posix_time/posix_time.hpp> + namespace Mad { namespace Server { namespace RequestHandlers { -void UserRequestHandlerGroup::handleUserListRequest(boost::shared_ptr<const Common::XmlPacket> packet _UNUSED_PARAMETER_, Common::XmlPacket *ret, +void UserRequestHandlerGroup::handleUserListRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > info = application->getUserManager()->getUserList(); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get<const std::string&>("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > users = application->getUserManager()->getUserList(×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("users"); - for(std::map<unsigned long, Common::UserInfo>::const_iterator user = info->begin(); user != info->end(); ++user) { - Common::XmlPacket::List::iterator entry = list->addEntry(); + if(!timestamp.is_not_a_date_time()) + ret->set("timestamp", boost::posix_time::to_iso_string(timestamp)); + + if(users) { + Common::XmlPacket::List *list = ret->createList("users"); + + for(std::map<unsigned long, Common::UserInfo>::const_iterator user = users->begin(); user != users->end(); ++user) { + Common::XmlPacket::List::iterator entry = list->addEntry(); - entry->set("uid", user->second.getUid()); - entry->set("gid", user->second.getGid()); - entry->set("username", user->second.getUsername()); - entry->set("fullName", user->second.getFullName()); + entry->set("uid", user->second.getUid()); + entry->set("gid", user->second.getGid()); + entry->set("username", user->second.getUsername()); + entry->set("fullName", user->second.getFullName()); + } } } void UserRequestHandlerGroup::handleUserInfoRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get<const std::string&>("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + boost::shared_ptr<const Common::UserInfo> info; unsigned long uid = packet->get<unsigned long>("uid"); if(uid) - info = application->getUserManager()->getUserInfo(uid); + info = application->getUserManager()->getUserInfo(uid, ×tamp); else - info = application->getUserManager()->getUserInfoByName(packet->get<const std::string&>("name")); + info = application->getUserManager()->getUserInfoByName(packet->get<const std::string&>("name"), ×tamp); ret->setType("OK"); - ret->set("uid", info->getUid()); - ret->set("gid", info->getGid()); - ret->set("username", info->getUsername()); - ret->set("fullName", info->getFullName()); + if(!timestamp.is_not_a_date_time()) + ret->set("timestamp", boost::posix_time::to_iso_string(timestamp)); + + if(info) { + ret->set("uid", info->getUid()); + ret->set("gid", info->getGid()); + ret->set("username", info->getUsername()); + ret->set("fullName", info->getFullName()); + } } void UserRequestHandlerGroup::handleUserGroupListRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr<const std::set<unsigned long> > groups = application->getUserManager()->getUserGroupList(packet->get<unsigned long>("uid")); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get<const std::string&>("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr<const std::set<unsigned long> > groups = application->getUserManager()->getUserGroupList(packet->get<unsigned long>("uid"), ×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("groups"); - for(std::set<unsigned long>::const_iterator group = groups->begin(); group != groups->end(); ++group) { - Common::XmlPacket::List::iterator entry = list->addEntry(); + if(!timestamp.is_not_a_date_time()) + ret->set("timestamp", boost::posix_time::to_iso_string(timestamp)); + + if(groups) { + Common::XmlPacket::List *list = ret->createList("groups"); + + for(std::set<unsigned long>::const_iterator group = groups->begin(); group != groups->end(); ++group) { + Common::XmlPacket::List::iterator entry = list->addEntry(); - entry->set("gid", *group); + entry->set("gid", *group); + } } } -void UserRequestHandlerGroup::handleGroupListRequest(boost::shared_ptr<const Common::XmlPacket> packet _UNUSED_PARAMETER_, Common::XmlPacket *ret, +void UserRequestHandlerGroup::handleGroupListRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > info = application->getUserManager()->getGroupList(); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get<const std::string&>("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > groups = application->getUserManager()->getGroupList(×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("groups"); - for(std::map<unsigned long, Common::GroupInfo>::const_iterator group = info->begin(); group != info->end(); ++group) { - Common::XmlPacket::List::iterator entry = list->addEntry(); + if(!timestamp.is_not_a_date_time()) + ret->set("timestamp", boost::posix_time::to_iso_string(timestamp)); + + if(groups) { + Common::XmlPacket::List *list = ret->createList("groups"); + + for(std::map<unsigned long, Common::GroupInfo>::const_iterator group = groups->begin(); group != groups->end(); ++group) { + Common::XmlPacket::List::iterator entry = list->addEntry(); - entry->set("gid", group->second.getGid()); - entry->set("name", group->second.getName()); + entry->set("gid", group->second.getGid()); + entry->set("name", group->second.getName()); + } } } void UserRequestHandlerGroup::handleGroupInfoRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get<const std::string&>("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + boost::shared_ptr<const Common::GroupInfo> info; unsigned long gid = packet->get<unsigned long>("gid"); if(gid) - info = application->getUserManager()->getGroupInfo(gid); + info = application->getUserManager()->getGroupInfo(gid, ×tamp); else - info = application->getUserManager()->getGroupInfoByName(packet->get<const std::string&>("name")); + info = application->getUserManager()->getGroupInfoByName(packet->get<const std::string&>("name"), ×tamp); ret->setType("OK"); - ret->set("gid", info->getGid()); - ret->set("name", info->getName()); + if(!timestamp.is_not_a_date_time()) + ret->set("timestamp", boost::posix_time::to_iso_string(timestamp)); + + if(info) { + ret->set("gid", info->getGid()); + ret->set("name", info->getName()); + } } void UserRequestHandlerGroup::handleGroupUserListRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr<const std::set<unsigned long> > users = application->getUserManager()->getGroupUserList(packet->get<unsigned long>("gid")); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get<const std::string&>("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr<const std::set<unsigned long> > users = application->getUserManager()->getGroupUserList(packet->get<unsigned long>("gid"), ×tamp); ret->setType("OK"); + + if(!timestamp.is_not_a_date_time()) + ret->set("timestamp", boost::posix_time::to_iso_string(timestamp)); + Common::XmlPacket::List *list = ret->createList("users"); for(std::set<unsigned long>::const_iterator user = users->begin(); user != users->end(); ++user) { @@ -119,18 +216,34 @@ void UserRequestHandlerGroup::handleGroupUserListRequest(boost::shared_ptr<const } } -void UserRequestHandlerGroup::handleFullUserGroupListRequest(boost::shared_ptr<const Common::XmlPacket> packet _UNUSED_PARAMETER_, Common::XmlPacket *ret, +void UserRequestHandlerGroup::handleFullUserGroupListRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > userGroups = application->getUserManager()->getFullUserGroupList(); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get<const std::string&>("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > userGroups = application->getUserManager()->getFullUserGroupList(×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("userGroupList"); - for(std::map<unsigned long, unsigned long>::const_iterator userGroup = userGroups->begin(); userGroup != userGroups->end(); ++userGroup) { - Common::XmlPacket::List::iterator entry = list->addEntry(); + if(!timestamp.is_not_a_date_time()) + ret->set("timestamp", boost::posix_time::to_iso_string(timestamp)); + + if(userGroups) { + Common::XmlPacket::List *list = ret->createList("userGroupList"); + + for(std::map<unsigned long, unsigned long>::const_iterator userGroup = userGroups->begin(); userGroup != userGroups->end(); ++userGroup) { + Common::XmlPacket::List::iterator entry = list->addEntry(); - entry->set("uid", userGroup->first); - entry->set("gid", userGroup->second); + entry->set("uid", userGroup->first); + entry->set("gid", userGroup->second); + } } } diff --git a/src/modules/UserBackendMysql/UserBackendMysql.cpp b/src/modules/UserBackendMysql/UserBackendMysql.cpp index 6d64a51..82258e8 100644 --- a/src/modules/UserBackendMysql/UserBackendMysql.cpp +++ b/src/modules/UserBackendMysql/UserBackendMysql.cpp @@ -134,11 +134,18 @@ void UserBackendMysql::configFinished() { } -boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > UserBackendMysql::getUserList() throw(Core::Exception) { +boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > UserBackendMysql::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -164,11 +171,18 @@ boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > UserBackendM return users; } -boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfo(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const Common::UserInfo>(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -205,11 +219,18 @@ boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfo(unsigned throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const Common::UserInfo>(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -243,11 +264,18 @@ boost::shared_ptr<const Common::UserInfo> UserBackendMysql::getUserInfoByName(co throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getUserGroupList(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const std::set<unsigned long> >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -275,11 +303,18 @@ boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getUserGroup } -boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > UserBackendMysql::getGroupList() throw(Core::Exception) { +boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > UserBackendMysql::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -302,11 +337,18 @@ boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > UserBackend return groups; } -boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfo(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const Common::GroupInfo>(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -335,11 +377,18 @@ boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfo(unsign throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const Common::GroupInfo>(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -365,11 +414,18 @@ boost::shared_ptr<const Common::GroupInfo> UserBackendMysql::getGroupInfoByName( throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getGroupUserList(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const std::set<unsigned long> >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -396,11 +452,18 @@ boost::shared_ptr<const std::set<unsigned long> > UserBackendMysql::getGroupUser return users; } -boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserBackendMysql::getFullUserGroupList() throw(Core::Exception) { +boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserBackendMysql::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock<boost::mutex> lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr<const std::multimap<unsigned long, unsigned long> >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); diff --git a/src/modules/UserBackendMysql/UserBackendMysql.h b/src/modules/UserBackendMysql/UserBackendMysql.h index eadbf3b..52a134a 100644 --- a/src/modules/UserBackendMysql/UserBackendMysql.h +++ b/src/modules/UserBackendMysql/UserBackendMysql.h @@ -49,26 +49,28 @@ class UserBackendMysql : public Common::UserBackend, private Core::Configurable MYSQL *mysql; + boost::posix_time::ptime lastUpdate; + boost::mutex mutex; protected: virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool); virtual void configFinished(); - virtual boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > getUserList() throw(Core::Exception); - virtual boost::shared_ptr<const Common::UserInfo> getUserInfo(unsigned long uid) throw(Core::Exception); - virtual boost::shared_ptr<const Common::UserInfo> getUserInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid) throw(Core::Exception); + virtual boost::shared_ptr<const std::map<unsigned long, Common::UserInfo> > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::UserInfo> getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::UserInfo> getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const std::set<unsigned long> > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > getGroupList() throw(Core::Exception); - virtual boost::shared_ptr<const Common::GroupInfo> getGroupInfo(unsigned long gid) throw(Core::Exception); - virtual boost::shared_ptr<const Common::GroupInfo> getGroupInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid) throw(Core::Exception); + virtual boost::shared_ptr<const std::map<unsigned long, Common::GroupInfo> > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::GroupInfo> getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const Common::GroupInfo> getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr<const std::set<unsigned long> > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList() throw(Core::Exception); + virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); public: - UserBackendMysql(Common::Application *application0) : application(application0), port(0), mysql(0) { + UserBackendMysql(Common::Application *application0) : application(application0), port(0), mysql(0), lastUpdate(boost::posix_time::microsec_clock::universal_time()) { application->getConfigManager()->registerConfigurable(this); } |