diff options
Diffstat (limited to 'server/src/entitylist.cc')
-rw-r--r-- | server/src/entitylist.cc | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/server/src/entitylist.cc b/server/src/entitylist.cc new file mode 100644 index 0000000..64bd49d --- /dev/null +++ b/server/src/entitylist.cc @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * entitylist.cc + * + * Thu Jan 14 14:17:34 CET 2010 + * Copyright 2010 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "entitylist.h" + +#include <sys/types.h> +#include <dirent.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <vector> + +#include "debug.h" + +static inline bool isdir(std::string name) +{ + struct stat s; + stat(name.c_str(), &s); + return S_ISDIR(s.st_mode); +} + +static inline bool isfile(std::string name) +{ + struct stat s; + stat(name.c_str(), &s); + return S_ISREG(s.st_mode); +} + +static std::vector<std::string> listdir(std::string path) +{ + std::vector<std::string> files; + + DIR* dir = opendir(path.c_str()); + if(!dir) { + PRACRO_ERR(entitylist, "Could not open directory: %s\n", path.c_str()); + return files; + } + + struct dirent *d; + while((d = readdir(dir)) != 0) { + if(std::string(d->d_name) == "." || std::string(d->d_name) == "..") continue; + + if(isdir(path + "/" + d->d_name)) { + std::vector<std::string> sub = listdir(path + "/" + d->d_name); + files.insert(files.end(), sub.begin(), sub.end()); + continue; + } + + if(isfile(path + "/" + d->d_name)) { + std::string name = d->d_name; + if(name.length() >= 4 && name.substr(name.length() - 4) == ".xml") + files.push_back(path + "/" + name); + } + } + closedir(dir); + + return files; +} + +EntityList::EntityList(std::string entityname) +{ + MutexAutolock lock(mutex); + + this->entityname = entityname; +} + +EntityList::~EntityList() +{ +} + +void EntityList::rescan(std::string entitypath) +{ + MutexAutolock lock(mutex); + + clear(); + // inotify.clear(); + + inotify.addDirectory(entitypath, WATCH_DEEP_FOLLOW, + IN_CLOSE_WRITE | + IN_MOVED_FROM | IN_MOVED_TO | IN_MOVE_SELF | + IN_DELETE | IN_DELETE_SELF); + + + + + std::vector<std::string> entitys = listdir(entitypath); + std::vector<std::string>::iterator i = entitys.begin(); + while(i != entitys.end()) { + addFile(*i); + i++; + } + + { + iterator i = begin(); + while(i != end()) { + EntityListItem::iterator j = i->second.begin(); + while(j != i->second.end()) { + PRACRO_DEBUG(entitylist, "%s - v%s file: %s\n", + i->first.c_str(), + ((std::string)j->first).c_str(), + j->second.c_str()); + j++; + } + i++; + } + } +} + +bool EntityList::removeFile(std::string file) +{ + // Check if the file is already in the tree. + iterator i = begin(); + while(i != end()) { + EntityListItem::iterator j = i->second.begin(); + while(j != i->second.end()) { + if(file == j->second) { + PRACRO_DEBUG(entitylist, "Removing file: %s\n", file.c_str()); + i->second.erase(j->first); + if(i->second.size() == 0) erase(i->first); + return true; + } + j++; + } + i++; + } + + return false; +} + +void EntityList::updateFile(std::string file) +{ + removeFile(file); + addFile(file); +} + +void EntityList::updateList() +{ + while(inotify.hasEvents()) { + INotify::Event event = inotify.getNextEvent(); + if(event.isCloseWriteEvent()) updateFile(event.name()+"/"+event.file()); + if(event.isMovedFromEvent()) removeFile(event.name()+"/"+event.file()); + if(event.isMovedToEvent()) updateFile(event.name()+"/"+event.file()); + if(event.isDeleteEvent()) removeFile(event.name()+"/"+event.file()); + + if(event.isMoveSelfEvent()) {/* TODO: what to do here? */} + if(event.isDeleteSelfEvent()) {/* TODO: what to do here? */} + } +} + +std::string EntityList::getLatestVersion(std::string entity) throw(Exception) +{ + MutexAutolock lock(mutex); + + updateList(); + + if(find(entity) == end()) throw Exception("Entity ("+entityname+") ["+entity+"] does not exist"); + EntityListItem mli = (*this)[entity]; + if(mli.size() == 0) throw Exception("Entity ("+entityname+") ["+entity+"] does not exist."); + PRACRO_DEBUG(entitylist, "Search for %s - found %s v%s\n", + entity.c_str(), + mli.begin()->second.c_str(), + ((std::string)mli.begin()->first).c_str()); + + return mli.begin()->second; +} + +#ifdef TEST_ENTITYLIST +//Additional dependency files +//deps: +//Required cflags (autoconf vars may be used) +//cflags: +//Required link options (autoconf vars may be used) +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). + +TEST_END; + +#endif/*TEST_ENTITYLIST*/ |