/* * UserCache.cpp * * Copyright (C) 2009 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #include "UserCache.h" #include "Application.h" namespace Mad { namespace Common { boost::shared_ptr > UserCache::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); boost::posix_time::ptime newTime(userTime); try { boost::shared_ptr > newUsers = backend->getUserList(&newTime); if(newUsers) { users = newUsers; userException = Core::Exception(); userTime = newTime; 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::Logger::LOG_USER, Core::Logger::LOG_DEBUG, "Using cached user list"); else application->log(Core::Logger::LOG_USER, Core::Logger::LOG_DEBUG, "Error cached"); } } catch(Core::Exception e) { if(e.getErrorCode() != Core::Exception::NOT_AVAILABLE || !users) { users.reset(); userException = e; userTime = newTime; } } 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::shared_ptr UserCache::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!getUserList(timestamp)) return boost::shared_ptr(); std::map::const_iterator user = users->find(uid); if(user == users->end()) throw Core::Exception(Core::Exception::NOT_FOUND); return boost::shared_ptr(new UserInfo(user->second)); } boost::shared_ptr UserCache::getUserInfoByName(const Core::String &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!getUserList(timestamp)) return boost::shared_ptr(); std::map::const_iterator uid = userNames->find(name); if(uid == userNames->end()) throw Core::Exception(Core::Exception::NOT_FOUND); std::map::const_iterator user = users->find(uid->second); return boost::shared_ptr(new UserInfo(user->second)); } boost::shared_ptr > UserCache::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!getFullUserGroupList(timestamp)) return boost::shared_ptr >(); std::pair::const_iterator, std::multimap::const_iterator> range = userGroups->equal_range(uid); boost::shared_ptr > groups(new std::set); for(std::multimap::const_iterator group = range.first; group != range.second; ++group) groups->insert(group->second); return groups; } boost::shared_ptr > UserCache::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); boost::posix_time::ptime newTime(groupTime); try { boost::shared_ptr > newGroups = backend->getGroupList(&newTime); if(newGroups) { groups = newGroups; groupException = Core::Exception(); groupTime = newTime; 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::Logger::LOG_USER, Core::Logger::LOG_DEBUG, "Using cached group list"); else application->log(Core::Logger::LOG_USER, Core::Logger::LOG_DEBUG, "Error cached"); } } catch(Core::Exception e) { if(e.getErrorCode() != Core::Exception::NOT_AVAILABLE || !groups) { groups.reset(); groupException = e; groupTime = newTime; } } 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::shared_ptr UserCache::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!getGroupList(timestamp)) return boost::shared_ptr(); std::map::const_iterator group = groups->find(gid); if(group == groups->end()) throw Core::Exception(Core::Exception::NOT_FOUND); return boost::shared_ptr(new GroupInfo(group->second)); } boost::shared_ptr UserCache::getGroupInfoByName(const Core::String &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!getGroupList(timestamp)) return boost::shared_ptr(); std::map::iterator gid = groupNames->find(name); if(gid == groupNames->end()) throw Core::Exception(Core::Exception::NOT_FOUND); std::map::const_iterator group = groups->find(gid->second); return boost::shared_ptr(new GroupInfo(group->second)); } boost::shared_ptr > UserCache::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!getFullUserGroupList(timestamp)) return boost::shared_ptr >(); std::pair::iterator, std::multimap::iterator> range = groupUsers->equal_range(gid); boost::shared_ptr > users(new std::set); for(std::multimap::iterator user = range.first; user != range.second; ++user) users->insert(user->second); return users; } boost::shared_ptr > UserCache::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::lock_guard lock(mutex); boost::posix_time::ptime newTime(userGroupTime); try { boost::shared_ptr > newUserGroups = backend->getFullUserGroupList(&newTime); if(newUserGroups) { userGroups = newUserGroups; userGroupException = Core::Exception(); userGroupTime = newTime; 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::Logger::LOG_USER, Core::Logger::LOG_DEBUG, "Using cached user-group table"); else application->log(Core::Logger::LOG_USER, Core::Logger::LOG_DEBUG, "Error cached"); } } catch(Core::Exception e) { if(e.getErrorCode() != Core::Exception::NOT_AVAILABLE || !userGroups) { userGroups.reset(); userGroupException = e; userGroupTime = newTime; } } 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 >(); } } }