From d34d398bc624521d969efab8eb1150c4a6cdeef0 Mon Sep 17 00:00:00 2001 From: deva Date: Thu, 14 Jan 2010 10:59:24 +0000 Subject: Almost finished the inotify wrapper. It still needs more tests. Made MacroList work recursive, added watch through inotify (also recursive). --- server/src/macrolist.cc | 116 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 16 deletions(-) (limited to 'server/src/macrolist.cc') diff --git a/server/src/macrolist.cc b/server/src/macrolist.cc index 0d0916d..89abfe8 100644 --- a/server/src/macrolist.cc +++ b/server/src/macrolist.cc @@ -33,6 +33,24 @@ #include "debug.h" #include "macroheaderparser.h" +#include +#include +#include + +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 listdir(std::string path) { std::vector files; @@ -45,11 +63,21 @@ static std::vector listdir(std::string path) struct dirent *d; while((d = readdir(dir)) != 0) { - //if(d->d_type == DT_DIR) { - std::string name = d->d_name; - if(name.length() >= 4 && name.substr(name.length() - 4) == ".xml") - files.push_back(name); - //} + if(std::string(d->d_name) == "." || std::string(d->d_name) == "..") continue; + + PRACRO_DEBUG(macrolist, "d_name: %s - d_type: %d\n", d->d_name, d->d_type); + + if(isdir(path + "/" + d->d_name)) { + std::vector 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); @@ -60,18 +88,16 @@ MacroList::MacroList(std::string macropath) { MutexAutolock lock(mutex); + inotify.addDirectory(macropath, WATCH_DEEP_FOLLOW, + IN_CLOSE_WRITE | + IN_MOVED_FROM | IN_MOVED_TO | IN_MOVE_SELF | + IN_DELETE | IN_DELETE_SELF); + this->macropath = macropath; std::vector macros = listdir(macropath); std::vector::iterator i = macros.begin(); while(i != macros.end()) { - MacroHeaderParser parser(macropath + "/" + *i); - try { - parser.parse(); - Macro *macro = parser.getMacro(); - (*this)[macro->attributes["name"]][VersionStr(macro->attributes["version"])] = *i; - } catch(Exception &e) { - PRACRO_WARN(macrolist, "Skipping %s: %s\n", i->c_str(), e.what()); - } + addFile(*i); i++; } @@ -91,19 +117,77 @@ MacroList::MacroList(std::string macropath) } } +bool MacroList::removeFile(std::string file) +{ + // Check if the file is already in the tree. + iterator i = begin(); + while(i != end()) { + MacroListItem::iterator j = i->second.begin(); + while(j != i->second.end()) { + if(file == j->second) { + PRACRO_DEBUG(macrolist, "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 MacroList::addFile(std::string file) +{ + PRACRO_DEBUG(macrolist, "Adding file: %s\n", file.c_str()); + MacroHeaderParser parser(file); + try { + parser.parse(); + Macro *macro = parser.getMacro(); + (*this)[macro->attributes["name"]][VersionStr(macro->attributes["version"])] = file; + } catch(Exception &e) { + PRACRO_WARN(macrolist, "Skipping %s: %s\n", file.c_str(), e.what()); + } +} + +void MacroList::updateFile(std::string file) +{ + removeFile(file); + addFile(file); +} + +void MacroList::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 MacroList::getLatestVersion(std::string macro) throw(Exception) { MutexAutolock lock(mutex); + updateList(); + if(find(macro) == end()) throw Exception("Macro ["+macro+"] does not exist"); MacroListItem mli = (*this)[macro]; - if(mli.size() == 0) return ""; + if(mli.size() == 0) throw Exception("Macro ["+macro+"] does not exist"); PRACRO_DEBUG(macrolist, "Search for %s - found %s v%s\n", macro.c_str(), - (macropath + "/" + mli.begin()->second).c_str(), + mli.begin()->second.c_str(), ((std::string)mli.begin()->first).c_str()); - return macropath + "/" + mli.begin()->second; + return mli.begin()->second; } #ifdef TEST_MACROLIST -- cgit v1.2.3