From f2f1d5b1da4f985bcbb0c075cf42efcacecae2a6 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 3 Jul 2009 17:23:37 +0200 Subject: =?UTF-8?q?Timestamps=20f=C3=BCr=20Benutzercache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- src/Common/Backends/NetworkUserBackend.cpp | 193 +++++++++++++++---- src/Common/Backends/NetworkUserBackend.h | 44 +++-- src/Common/UserBackend.h | 19 +- src/Common/UserCache.cpp | 209 ++++++++++++--------- src/Common/UserCache.h | 29 +-- src/Common/UserManager.cpp | 36 ++-- src/Common/UserManager.h | 18 +- .../RequestHandlers/UserRequestHandlerGroup.cpp | 191 +++++++++++++++---- src/modules/UserBackendMysql/UserBackendMysql.cpp | 81 +++++++- 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 + 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 > NetworkUserBackend::getUserList() throw(Core::Exception) { - boost::shared_ptr request(new SimpleUserRequest(application, "ListUsers")); +boost::shared_ptr > NetworkUserBackend::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new SimpleUserRequest(application, "ListUsers", timestamp)); application->getRequestManager()->sendRequest(connection, request); + request->wait(); std::pair, Core::Exception> result = request->getResult(); if(!result.first || result.second) throw result.second; - boost::shared_ptr > userList(new std::map); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } const XmlPacket::List *users = result.first->getList("users"); if(users) { + boost::shared_ptr > userList(new std::map); + for(XmlPacket::List::const_iterator user = users->begin(); user != users->end(); ++user) { UserInfo userInfo(user->get("uid"), user->get("username")); userInfo.setGid(user->get("gid")); @@ -60,13 +86,15 @@ boost::shared_ptr > NetworkUserBackend:: userList->insert(std::make_pair(userInfo.getUid(), userInfo)); } + + return userList; } - return userList; + return boost::shared_ptr >(); } -boost::shared_ptr NetworkUserBackend::getUserInfo(unsigned long uid) throw(Core::Exception) { - boost::shared_ptr request(new IdUserRequest(application, "GetUserInfo", "uid", uid)); +boost::shared_ptr NetworkUserBackend::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new IdUserRequest(application, "GetUserInfo", "uid", uid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -74,15 +102,29 @@ boost::shared_ptr NetworkUserBackend::getUserInfo(unsigned long if(!result.first || result.second) throw result.second; - boost::shared_ptr userInfo(new UserInfo(result.first->get("uid"), result.first->get("username"))); - userInfo->setGid(result.first->get("gid")); - userInfo->setFullName(result.first->get("fullName")); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } + + unsigned long uid2 = result.first->get("uid"); - return userInfo; + if(uid2) { + boost::shared_ptr userInfo(new UserInfo(uid2, result.first->get("username"))); + + userInfo->setGid(result.first->get("gid")); + userInfo->setFullName(result.first->get("fullName")); + + return userInfo; + } + + return boost::shared_ptr(); } -boost::shared_ptr NetworkUserBackend::getUserInfoByName(const std::string &name) throw(Core::Exception) { - boost::shared_ptr request(new NameUserRequest(application, "GetUserInfo", name)); +boost::shared_ptr NetworkUserBackend::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new NameUserRequest(application, "GetUserInfo", name, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -90,15 +132,29 @@ boost::shared_ptr NetworkUserBackend::getUserInfoByName(const st if(!result.first || result.second) throw result.second; - boost::shared_ptr userInfo(new UserInfo(result.first->get("uid"), result.first->get("username"))); - userInfo->setGid(result.first->get("gid")); - userInfo->setFullName(result.first->get("fullName")); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } + + unsigned long uid = result.first->get("uid"); + + if(uid) { + boost::shared_ptr userInfo(new UserInfo(uid, result.first->get("username"))); + + userInfo->setGid(result.first->get("gid")); + userInfo->setFullName(result.first->get("fullName")); - return userInfo; + return userInfo; + } + + return boost::shared_ptr(); } -boost::shared_ptr > NetworkUserBackend::getUserGroupList(unsigned long uid) throw(Core::Exception) { - boost::shared_ptr request(new IdUserRequest(application, "ListUserGroups", "uid", uid)); +boost::shared_ptr > NetworkUserBackend::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new IdUserRequest(application, "ListUserGroups", "uid", uid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -106,19 +162,29 @@ boost::shared_ptr > NetworkUserBackend::getUserGro if(!result.first || result.second) throw result.second; - boost::shared_ptr > groupList(new std::set); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } const XmlPacket::List *groups = result.first->getList("groups"); + if(groups) { + boost::shared_ptr > groupList(new std::set); + for(XmlPacket::List::const_iterator group = groups->begin(); group != groups->end(); ++group) groupList->insert(group->get("gid")); + + return groupList; } - return groupList; + return boost::shared_ptr >(); } -boost::shared_ptr > NetworkUserBackend::getGroupList() throw(Core::Exception) { - boost::shared_ptr request(new SimpleUserRequest(application, "ListGroups")); +boost::shared_ptr > NetworkUserBackend::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new SimpleUserRequest(application, "ListGroups", timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -126,21 +192,30 @@ boost::shared_ptr > NetworkUserBackend: if(!result.first || result.second) throw result.second; - boost::shared_ptr > groupList(new std::map); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } const XmlPacket::List *groups = result.first->getList("groups"); if(groups) { + boost::shared_ptr > groupList(new std::map); + for(XmlPacket::List::const_iterator group = groups->begin(); group != groups->end(); ++group) { GroupInfo groupInfo(group->get("gid"), group->get("name")); groupList->insert(std::make_pair(groupInfo.getGid(), groupInfo)); } + + return groupList; } - return groupList; + return boost::shared_ptr >(); } -boost::shared_ptr NetworkUserBackend::getGroupInfo(unsigned long gid) throw(Core::Exception) { - boost::shared_ptr request(new IdUserRequest(application, "GetGroupInfo", "gid", gid)); +boost::shared_ptr NetworkUserBackend::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new IdUserRequest(application, "GetGroupInfo", "gid", gid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -148,13 +223,23 @@ boost::shared_ptr NetworkUserBackend::getGroupInfo(unsigned lon if(!result.first || result.second) throw result.second; - boost::shared_ptr groupInfo(new GroupInfo(result.first->get("gid"), result.first->get("name"))); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } + + unsigned long gid2 = result.first->get("gid"); - return groupInfo; + if(gid2) + return boost::shared_ptr(new GroupInfo(gid2, result.first->get("name"))); + + return boost::shared_ptr(); } -boost::shared_ptr NetworkUserBackend::getGroupInfoByName(const std::string &name) throw(Core::Exception) { - boost::shared_ptr request(new NameUserRequest(application, "GetGroupInfo", name)); +boost::shared_ptr NetworkUserBackend::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new NameUserRequest(application, "GetGroupInfo", name, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -162,13 +247,23 @@ boost::shared_ptr NetworkUserBackend::getGroupInfoByName(const if(!result.first || result.second) throw result.second; - boost::shared_ptr groupInfo(new GroupInfo(result.first->get("gid"), result.first->get("name"))); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } + + unsigned long gid = result.first->get("gid"); - return groupInfo; + if(gid) + return boost::shared_ptr(new GroupInfo(gid, result.first->get("name"))); + + return boost::shared_ptr(); } -boost::shared_ptr > NetworkUserBackend::getGroupUserList(unsigned long gid) throw(Core::Exception) { - boost::shared_ptr request(new IdUserRequest(application, "ListGroupUsers", "gid", gid)); +boost::shared_ptr > NetworkUserBackend::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new IdUserRequest(application, "ListGroupUsers", "gid", gid, timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -176,20 +271,29 @@ boost::shared_ptr > NetworkUserBackend::getGroupUs if(!result.first || result.second) throw result.second; - boost::shared_ptr > userList(new std::set); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } const XmlPacket::List *users = result.first->getList("users"); if(users) { + boost::shared_ptr > userList(new std::set); + for(XmlPacket::List::const_iterator user = users->begin(); user != users->end(); ++user) { userList->insert(user->get("uid")); } + + return userList; } - return userList; + return boost::shared_ptr >(); } -boost::shared_ptr > NetworkUserBackend::getFullUserGroupList() throw(Core::Exception) { - boost::shared_ptr request(new SimpleUserRequest(application, "GetFullUserGroupList")); +boost::shared_ptr > NetworkUserBackend::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::shared_ptr request(new SimpleUserRequest(application, "GetFullUserGroupList", timestamp)); application->getRequestManager()->sendRequest(connection, request); request->wait(); @@ -197,15 +301,24 @@ boost::shared_ptr > NetworkUse if(!result.first || result.second) throw result.second; - boost::shared_ptr > ret(new std::multimap); + if(timestamp) { + try { + *timestamp = boost::posix_time::from_iso_string(result.first->get("timestamp")); + } + catch(...) {} + } const XmlPacket::List *list = result.first->getList("userGroupList"); if(list) { + boost::shared_ptr > ret(new std::multimap); + for(XmlPacket::List::const_iterator entry = list->begin(); entry != list->end(); ++entry) ret->insert(std::make_pair(entry->get("uid"), entry->get("gid"))); + + return ret; } - return ret; + return boost::shared_ptr >(); } 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 > getUserList() throw(Core::Exception); - virtual boost::shared_ptr getUserInfo(unsigned long uid) throw(Core::Exception); - virtual boost::shared_ptr getUserInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr > getUserGroupList(unsigned long uid) throw(Core::Exception); + virtual boost::shared_ptr > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getGroupList() throw(Core::Exception); - virtual boost::shared_ptr getGroupInfo(unsigned long gid) throw(Core::Exception); - virtual boost::shared_ptr getGroupInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr > getGroupUserList(unsigned long gid) throw(Core::Exception); + virtual boost::shared_ptr > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getFullUserGroupList() throw(Core::Exception); + virtual boost::shared_ptr > 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 #include +#include #include @@ -47,40 +48,40 @@ class UserBackend { UserBackend() {} - virtual boost::shared_ptr > getUserList() throw(Core::Exception) { + virtual boost::shared_ptr > getUserList(boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr getUserInfo(unsigned long uid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr 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 getUserInfoByName(const std::string &name _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr 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 > getUserGroupList(unsigned long uid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr > 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 > getGroupList() throw(Core::Exception) { + virtual boost::shared_ptr > getGroupList(boost::posix_time::ptime *timestamp _UNUSED_PARAMETER_) throw(Core::Exception) { throw(Core::Exception(Core::Exception::NOT_IMPLEMENTED)); } - virtual boost::shared_ptr getGroupInfo(unsigned long gid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr 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 getGroupInfoByName(const std::string &name _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr 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 > getGroupUserList(unsigned long gid _UNUSED_PARAMETER_) throw(Core::Exception) { + virtual boost::shared_ptr > 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 > getFullUserGroupList() throw(Core::Exception) { + virtual boost::shared_ptr > 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 > UserCache::getUserList() throw(Core::Exception) { - boost::lock_guard 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 > UserCache::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); try { - users = backend->getUserList(); - - userNames.reset(new std::map); - for(std::map::const_iterator user = users->begin(); user != users->end(); ++user) - userNames->insert(std::make_pair(user->second.getUsername(), user->first)); - - return users; + boost::shared_ptr > newUsers = backend->getUserList(&userTime); + + if(newUsers) { + users = newUsers; + userException = Core::Exception(); + + userNames.reset(new std::map); + for(std::map::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 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 >(); +} - boost::lock_guard lock(mutex); +boost::shared_ptr UserCache::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); - if(!users) - throw userException; + if(!getUserList(timestamp)) + return boost::shared_ptr(); std::map::const_iterator user = users->find(uid); @@ -66,13 +76,11 @@ boost::shared_ptr UserCache::getUserInfo(unsigned long uid) thro return boost::shared_ptr(new UserInfo(user->second)); } -boost::shared_ptr UserCache::getUserInfoByName(const std::string &name) throw(Core::Exception) { - getUserList(); +boost::shared_ptr UserCache::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); - boost::lock_guard lock(mutex); - - if(!users) - throw userException; + if(!getUserList(timestamp)) + return boost::shared_ptr(); std::map::const_iterator uid = userNames->find(name); if(uid == userNames->end()) @@ -83,13 +91,11 @@ boost::shared_ptr UserCache::getUserInfoByName(const std::string return boost::shared_ptr(new UserInfo(user->second)); } -boost::shared_ptr > UserCache::getUserGroupList(unsigned long uid) throw(Core::Exception) { - getFullUserGroupList(); - - boost::lock_guard lock(mutex); +boost::shared_ptr > UserCache::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); - if(!userGroups) - throw userGroupException; + if(!getFullUserGroupList(timestamp)) + return boost::shared_ptr >(); std::pair::const_iterator, std::multimap::const_iterator> range = userGroups->equal_range(uid); @@ -102,40 +108,50 @@ boost::shared_ptr > UserCache::getUserGroupList(un } -boost::shared_ptr > UserCache::getGroupList() throw(Core::Exception) { - boost::lock_guard 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 > UserCache::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); try { - groups = backend->getGroupList(); - - groupNames.reset(new std::map); - for(std::map::const_iterator group = groups->begin(); group != groups->end(); ++group) - groupNames->insert(std::make_pair(group->second.getName(), group->first)); - - return groups; + boost::shared_ptr > newGroups = backend->getGroupList(&groupTime); + + if(newGroups) { + groups = newGroups; + groupException = Core::Exception(); + + groupNames.reset(new std::map); + for(std::map::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 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 >(); +} - boost::lock_guard lock(mutex); +boost::shared_ptr UserCache::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); - if(!groups) - throw groupException; + if(!getGroupList(timestamp)) + return boost::shared_ptr(); std::map::const_iterator group = groups->find(gid); @@ -145,13 +161,11 @@ boost::shared_ptr UserCache::getGroupInfo(unsigned long gid) th return boost::shared_ptr(new GroupInfo(group->second)); } -boost::shared_ptr UserCache::getGroupInfoByName(const std::string &name) throw(Core::Exception) { - getGroupList(); +boost::shared_ptr UserCache::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); - boost::lock_guard lock(mutex); - - if(!groups) - throw groupException; + if(!getGroupList(timestamp)) + return boost::shared_ptr(); std::map::const_iterator gid = groupNames->find(name); if(gid == groupNames->end()) @@ -162,13 +176,11 @@ boost::shared_ptr UserCache::getGroupInfoByName(const std::stri return boost::shared_ptr(new GroupInfo(group->second)); } -boost::shared_ptr > UserCache::getGroupUserList(unsigned long gid) throw(Core::Exception) { - getFullUserGroupList(); - - boost::lock_guard lock(mutex); +boost::shared_ptr > UserCache::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard lock(mutex); - if(!userGroups) - throw userGroupException; + if(!getFullUserGroupList(timestamp)) + return boost::shared_ptr >(); std::pair::iterator, std::multimap::iterator> range = groupUsers->equal_range(gid); @@ -180,30 +192,43 @@ boost::shared_ptr > UserCache::getGroupUserList(un return users; } -boost::shared_ptr > UserCache::getFullUserGroupList() throw(Core::Exception) { - boost::lock_guard lock(mutex); +boost::shared_ptr > UserCache::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + boost::lock_guard 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); - for(std::multimap::const_iterator usergroup = userGroups->begin(); usergroup != userGroups->end(); ++usergroup) - groupUsers->insert(std::make_pair(usergroup->second, usergroup->first)); - - return userGroups; + boost::shared_ptr > newUserGroups = backend->getFullUserGroupList(&userGroupTime); + + if(newUserGroups) { + userGroups = newUserGroups; + userGroupException = Core::Exception(); + + groupUsers.reset(new std::multimap); + for(std::multimap::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 >(); } } 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 -#include +#include namespace Mad { namespace Common { @@ -40,32 +40,35 @@ class UserCache : public UserBackend, private boost::noncopyable { boost::shared_ptr backend; - boost::shared_mutex mutex; + boost::recursive_mutex mutex; boost::shared_ptr > users; boost::shared_ptr > userNames; Core::Exception userException; + boost::posix_time::ptime userTime; boost::shared_ptr > groups; boost::shared_ptr > groupNames; Core::Exception groupException; + boost::posix_time::ptime groupTime; boost::shared_ptr > userGroups; boost::shared_ptr > groupUsers; Core::Exception userGroupException; + boost::posix_time::ptime userGroupTime; protected: - virtual boost::shared_ptr > getUserList() throw(Core::Exception); - virtual boost::shared_ptr getUserInfo(unsigned long uid) throw(Core::Exception); - virtual boost::shared_ptr getUserInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr > getUserGroupList(unsigned long uid) throw(Core::Exception); + virtual boost::shared_ptr > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getGroupList() throw(Core::Exception); - virtual boost::shared_ptr getGroupInfo(unsigned long gid) throw(Core::Exception); - virtual boost::shared_ptr getGroupInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr > getGroupUserList(unsigned long gid) throw(Core::Exception); + virtual boost::shared_ptr > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getFullUserGroupList() throw(Core::Exception); + virtual boost::shared_ptr > 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 backend0) : application(application0), backend(backend0) {} + UserCache(Application *application0, boost::shared_ptr 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 backend) } -boost::shared_ptr > UserManager::getUserList() throw(Core::Exception) { +boost::shared_ptr > UserManager::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 > UserManager::getUser throw e; } -boost::shared_ptr UserManager::getUserInfo(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr UserManager::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 UserManager::getUserInfo(unsigned long uid) th throw e; } -boost::shared_ptr UserManager::getUserInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr UserManager::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 UserManager::getUserInfoByName(const std::stri throw e; } -boost::shared_ptr > UserManager::getUserGroupList(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr > UserManager::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 > UserManager::getUserGroupList( throw e; } -boost::shared_ptr > UserManager::getGroupList() throw(Core::Exception) { +boost::shared_ptr > UserManager::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::shared_ptr > ret; @@ -123,7 +123,7 @@ boost::shared_ptr > 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 > UserManager::getGro throw e; } -boost::shared_ptr UserManager::getGroupInfo(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr UserManager::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 UserManager::getGroupInfo(unsigned long gid) throw e; } -boost::shared_ptr UserManager::getGroupInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr UserManager::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 UserManager::getGroupInfoByName(const std::st throw e; } -boost::shared_ptr > UserManager::getGroupUserList(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr > UserManager::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 > UserManager::getGroupUserList( throw e; } -boost::shared_ptr > UserManager::getFullUserGroupList() throw(Core::Exception) { +boost::shared_ptr > UserManager::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { Core::Exception e(Core::Exception::NOT_IMPLEMENTED); boost::lock_guard 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 > getUserList() throw(Core::Exception); - boost::shared_ptr getUserInfo(unsigned long uid) throw(Core::Exception); - boost::shared_ptr getUserInfoByName(const std::string &name) throw(Core::Exception); - boost::shared_ptr > getUserGroupList(unsigned long uid) throw(Core::Exception); + boost::shared_ptr > getUserList(boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); - boost::shared_ptr > getGroupList() throw(Core::Exception); - boost::shared_ptr getGroupInfo(unsigned long gid) throw(Core::Exception); - boost::shared_ptr getGroupInfoByName(const std::string &name) throw(Core::Exception); - boost::shared_ptr > getGroupUserList(unsigned long gid) throw(Core::Exception); + boost::shared_ptr > getGroupList(boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); + boost::shared_ptr > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp = 0) throw(Core::Exception); - boost::shared_ptr > getFullUserGroupList() throw(Core::Exception); + boost::shared_ptr > 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 . */ +#include + #include "UserRequestHandlerGroup.h" #include "../Application.h" + #include +#include + namespace Mad { namespace Server { namespace RequestHandlers { -void UserRequestHandlerGroup::handleUserListRequest(boost::shared_ptr packet _UNUSED_PARAMETER_, Common::XmlPacket *ret, +void UserRequestHandlerGroup::handleUserListRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr > info = application->getUserManager()->getUserList(); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr > users = application->getUserManager()->getUserList(×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("users"); - for(std::map::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::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 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("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + boost::shared_ptr info; unsigned long uid = packet->get("uid"); if(uid) - info = application->getUserManager()->getUserInfo(uid); + info = application->getUserManager()->getUserInfo(uid, ×tamp); else - info = application->getUserManager()->getUserInfoByName(packet->get("name")); + info = application->getUserManager()->getUserInfoByName(packet->get("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 packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr > groups = application->getUserManager()->getUserGroupList(packet->get("uid")); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr > groups = application->getUserManager()->getUserGroupList(packet->get("uid"), ×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("groups"); - for(std::set::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::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 packet _UNUSED_PARAMETER_, Common::XmlPacket *ret, +void UserRequestHandlerGroup::handleGroupListRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr > info = application->getUserManager()->getGroupList(); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr > groups = application->getUserManager()->getGroupList(×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("groups"); - for(std::map::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::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 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("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + boost::shared_ptr info; unsigned long gid = packet->get("gid"); if(gid) - info = application->getUserManager()->getGroupInfo(gid); + info = application->getUserManager()->getGroupInfo(gid, ×tamp); else - info = application->getUserManager()->getGroupInfoByName(packet->get("name")); + info = application->getUserManager()->getGroupInfoByName(packet->get("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 packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr > users = application->getUserManager()->getGroupUserList(packet->get("gid")); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr > users = application->getUserManager()->getGroupUserList(packet->get("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::const_iterator user = users->begin(); user != users->end(); ++user) { @@ -119,18 +216,34 @@ void UserRequestHandlerGroup::handleGroupUserListRequest(boost::shared_ptr packet _UNUSED_PARAMETER_, Common::XmlPacket *ret, +void UserRequestHandlerGroup::handleFullUserGroupListRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection _UNUSED_PARAMETER_) { - boost::shared_ptr > userGroups = application->getUserManager()->getFullUserGroupList(); + boost::posix_time::ptime timestamp(boost::posix_time::not_a_date_time); + + const std::string ×tr = packet->get("timestamp"); + if(!timestr.empty()) { + try { + timestamp = boost::posix_time::from_iso_string(timestr); + } + catch(...) {} + } + + boost::shared_ptr > userGroups = application->getUserManager()->getFullUserGroupList(×tamp); ret->setType("OK"); - Common::XmlPacket::List *list = ret->createList("userGroupList"); - for(std::map::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::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 > UserBackendMysql::getUserList() throw(Core::Exception) { +boost::shared_ptr > UserBackendMysql::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -164,11 +171,18 @@ boost::shared_ptr > UserBackendM return users; } -boost::shared_ptr UserBackendMysql::getUserInfo(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr UserBackendMysql::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -205,11 +219,18 @@ boost::shared_ptr UserBackendMysql::getUserInfo(unsigned throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr UserBackendMysql::getUserInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr UserBackendMysql::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -243,11 +264,18 @@ boost::shared_ptr UserBackendMysql::getUserInfoByName(co throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr > UserBackendMysql::getUserGroupList(unsigned long uid) throw(Core::Exception) { +boost::shared_ptr > UserBackendMysql::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -275,11 +303,18 @@ boost::shared_ptr > UserBackendMysql::getUserGroup } -boost::shared_ptr > UserBackendMysql::getGroupList() throw(Core::Exception) { +boost::shared_ptr > UserBackendMysql::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -302,11 +337,18 @@ boost::shared_ptr > UserBackend return groups; } -boost::shared_ptr UserBackendMysql::getGroupInfo(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr UserBackendMysql::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -335,11 +377,18 @@ boost::shared_ptr UserBackendMysql::getGroupInfo(unsign throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr UserBackendMysql::getGroupInfoByName(const std::string &name) throw(Core::Exception) { +boost::shared_ptr UserBackendMysql::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -365,11 +414,18 @@ boost::shared_ptr UserBackendMysql::getGroupInfoByName( throw Core::Exception(Core::Exception::NOT_FOUND); } -boost::shared_ptr > UserBackendMysql::getGroupUserList(unsigned long gid) throw(Core::Exception) { +boost::shared_ptr > UserBackendMysql::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + if(!mysql || mysql_ping(mysql)) throw Core::Exception(Core::Exception::NOT_AVAILABLE); @@ -396,11 +452,18 @@ boost::shared_ptr > UserBackendMysql::getGroupUser return users; } -boost::shared_ptr > UserBackendMysql::getFullUserGroupList() throw(Core::Exception) { +boost::shared_ptr > UserBackendMysql::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { application->getThreadManager()->detach(); boost::unique_lock lock(mutex); + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + 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 > getUserList() throw(Core::Exception); - virtual boost::shared_ptr getUserInfo(unsigned long uid) throw(Core::Exception); - virtual boost::shared_ptr getUserInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr > getUserGroupList(unsigned long uid) throw(Core::Exception); + virtual boost::shared_ptr > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getGroupList() throw(Core::Exception); - virtual boost::shared_ptr getGroupInfo(unsigned long gid) throw(Core::Exception); - virtual boost::shared_ptr getGroupInfoByName(const std::string &name) throw(Core::Exception); - virtual boost::shared_ptr > getGroupUserList(unsigned long gid) throw(Core::Exception); + virtual boost::shared_ptr > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getFullUserGroupList() throw(Core::Exception); + virtual boost::shared_ptr > 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); } -- cgit v1.2.3