From e1d4c1224c0e1abce1d8cae49e241b37f1ca3eed Mon Sep 17 00:00:00 2001 From: deva Date: Fri, 15 Jan 2010 10:43:59 +0000 Subject: Add fix to entitylist, for mixing updates on dir rename/moves. Updated MacroList and TemplateList to macth new interface and use new insert method. --- server/src/entitylist.cc | 108 +++++++++++++++++++++++++++------------------ server/src/entitylist.h | 6 ++- server/src/inotify.cc | 14 ++++++ server/src/inotify.h | 3 ++ server/src/macrolist.cc | 9 ++-- server/src/templatelist.cc | 9 ++-- 6 files changed, 96 insertions(+), 53 deletions(-) diff --git a/server/src/entitylist.cc b/server/src/entitylist.cc index 6964df1..6440a11 100644 --- a/server/src/entitylist.cc +++ b/server/src/entitylist.cc @@ -62,16 +62,17 @@ static std::vector listdir(std::string path) struct dirent *d; while((d = readdir(dir)) != 0) { - if(std::string(d->d_name) == "." || std::string(d->d_name) == "..") continue; + std::string name = d->d_name; - if(isdir(path + "/" + d->d_name)) { - std::vector sub = listdir(path + "/" + d->d_name); + if(name == "." || name == "..") continue; + + if(isdir(path + "/" + name)) { + std::vector sub = listdir(path + "/" + name); files.insert(files.end(), sub.begin(), sub.end()); continue; } - if(isfile(path + "/" + d->d_name)) { - std::string name = d->d_name; + if(isfile(path + "/" + name)) { if(name.length() >= 4 && name.substr(name.length() - 4) == ".xml") files.push_back(path + "/" + name); } @@ -81,23 +82,22 @@ static std::vector listdir(std::string path) return files; } -EntityList::EntityList(std::string entityname) +EntityList::EntityList(std::string entitypath, std::string entityname) { MutexAutolock lock(mutex); this->entityname = entityname; + this->entitypath = entitypath; } EntityList::~EntityList() { } -void EntityList::rescan(std::string entitypath) +void EntityList::rescan() { - MutexAutolock lock(mutex); - clear(); - // inotify.clear(); + inotify.clear(); inotify.addDirectory(entitypath, WATCH_DEEP_FOLLOW, IN_CLOSE_WRITE | @@ -105,9 +105,6 @@ void EntityList::rescan(std::string entitypath) IN_DELETE | IN_DELETE_SELF | IN_CREATE); - - - std::vector entitys = listdir(entitypath); std::vector::iterator i = entitys.begin(); while(i != entitys.end()) { @@ -162,16 +159,15 @@ 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? */} + PRACRO_DEBUG(entitylist, "Handling event %s on %s, with param %s\n", + event.maskstr().c_str(), + event.name().c_str(), + event.file().c_str()); - if(event.isCreateEvent()) { - if(event.isDir()) { // A new directory was ceated. Scan it for files. + if(event.isDir()) { + if(event.isCreateEvent()) { + // A new directory was ceated. Scan it for files. std::vector entitys = listdir(event.name()+"/"+event.file()); std::vector::iterator i = entitys.begin(); while(i != entitys.end()) { @@ -179,6 +175,18 @@ void EntityList::updateList() i++; } } + + if(event.isMoveSelfEvent()) rescan(); + if(event.isDeleteSelfEvent()) rescan(); + if(event.isDeleteEvent()) rescan(); + if(event.isMovedFromEvent()) rescan(); + if(event.isMovedToEvent()) rescan(); + + } else { + 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()); } } } @@ -189,9 +197,11 @@ std::string EntityList::getLatestVersion(std::string entity) throw(Exception) updateList(); - if(find(entity) == end()) throw Exception("Entity ("+entityname+") ["+entity+"] does not exist"); + 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."); + 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(), @@ -200,54 +210,62 @@ std::string EntityList::getLatestVersion(std::string entity) throw(Exception) return mli.begin()->second; } +void EntityList::insertEntity(std::string entity, std::string version, std::string file) +{ + std::pair p(VersionStr(version), file); + (*this)[entity].insert(p); +} + #ifdef TEST_ENTITYLIST //deps: inotify.cc debug.cc mutex.cc exception.cc versionstr.cc log.cc //cflags: -I.. //libs: -lpthread #include "test.h" +#include + +#define _DIR "/tmp/entitylist_test_dir" + class TestList : public EntityList { public: - TestList(std::string path) : EntityList("test") { rescan(path); } - - void setNext(std::string v, std::string e) - { - this->v = v; - this->e = e; - } + TestList(std::string path) : EntityList(path, "test") { rescan(); } private: void addFile(std::string file) { - fprintf(stderr, "Inserting: %s %s\n", e.c_str(), v.c_str()); - std::pair p(VersionStr(v), file); - (*this)[e].insert(p); + char version[32]; + FILE *fp = fopen(file.c_str(), "r"); + if(!fp) return; + memset(version, 0, sizeof(version)); + fread(version, sizeof(version), 1, fp); + fclose(fp); + + fprintf(stderr, "Inserting: %s\n", version); + insertEntity("test", version, file); } - - std::string v; - std::string e; }; -#define _DIR "/tmp/entitylist_test_dir" - bool createfile(TestList &lst, std::string filename, std::string name, std::string version) { - lst.setNext(version, name); - FILE *fp = fopen(filename.c_str(), "w"); if(!fp) return false; - fprintf(fp, "something"); + fprintf(fp, "%s", version.c_str()); fclose(fp); return true; } TEST_BEGIN; +pracro_debug_parse("-all,+entitylist"); + if(mkdir(_DIR, 0777) == -1) TEST_FATAL("Could not create test dir."); TestList lst(_DIR); +TEST_EXCEPTION(lst.getLatestVersion("test"), Exception, + "Test lookup of macro in empty tree."); + if(!createfile(lst, _DIR"/file1.xml", "test", "1.0")) TEST_FATAL("Unable to write to the file"); @@ -282,13 +300,17 @@ rename(_DIR"/more/file1.xml", _DIR"/more/file2.xml"); TEST_EQUAL_STR(lst.getLatestVersion("test"), _DIR"/more/file2.xml", "Test"); -rename(_DIR"/more/file2.xml", _DIR"/file3.xml"); +rename(_DIR"/more", _DIR"/more2"); + +TEST_EQUAL_STR(lst.getLatestVersion("test"), _DIR"/more2/file2.xml", "Test"); + +rename(_DIR"/more2/file2.xml", _DIR"/file3.xml"); TEST_EQUAL_STR(lst.getLatestVersion("test"), _DIR"/file3.xml", "Test"); unlink(_DIR"/file3.xml"); -rmdir(_DIR"/more"); +rmdir(_DIR"/more2"); TEST_EQUAL_STR(lst.getLatestVersion("test"), _DIR"/file1.xml", "Test"); diff --git a/server/src/entitylist.h b/server/src/entitylist.h index 9185f67..3bcdfd0 100644 --- a/server/src/entitylist.h +++ b/server/src/entitylist.h @@ -58,7 +58,7 @@ public: * @param entitypath A std::string containing the path in which we should look * for xml files. */ - EntityList(std::string entityname); + EntityList(std::string entitypath, std::string entityname); virtual ~EntityList(); /** @@ -71,7 +71,8 @@ public: std::string getLatestVersion(std::string entity) throw(Exception); protected: - void rescan(std::string entitypath); + void rescan(); + void insertEntity(std::string entity, std::string version, std::string file); private: virtual void addFile(std::string file) = 0; @@ -84,6 +85,7 @@ private: INotify inotify; std::string entityname; + std::string entitypath; }; #endif/*__PRACRO_ENTITYLIST_H__*/ diff --git a/server/src/inotify.cc b/server/src/inotify.cc index dba3bfd..5fb983e 100644 --- a/server/src/inotify.cc +++ b/server/src/inotify.cc @@ -193,6 +193,11 @@ uint32_t INotify::Event::mask() return _mask; } +std::string INotify::Event::maskstr() +{ + return mask2asc(_mask); +} + INotify::INotify() { ifd = inotify_init1(O_NONBLOCK); @@ -370,6 +375,15 @@ INotify::Event INotify::getNextEvent() return e; } +void INotify::clear() +{ + if(ifd != -1) close(ifd); + ifd = inotify_init1(O_NONBLOCK); + if(ifd == -1) { + perror("Inotify init failed.\n"); + } +} + #ifdef TEST_INOTIFY //deps: debug.cc //cflags: -I.. diff --git a/server/src/inotify.h b/server/src/inotify.h index cbf75b2..d63e384 100644 --- a/server/src/inotify.h +++ b/server/src/inotify.h @@ -69,6 +69,7 @@ public: std::string name(); std::string file(); uint32_t mask(); + std::string maskstr(); private: std::string _name; @@ -97,6 +98,8 @@ public: bool hasEvents(); Event getNextEvent(); + void clear(); + private: class Watch { public: diff --git a/server/src/macrolist.cc b/server/src/macrolist.cc index 9dadb12..954149a 100644 --- a/server/src/macrolist.cc +++ b/server/src/macrolist.cc @@ -34,9 +34,9 @@ #include "debug.h" MacroList::MacroList(std::string path) - : EntityList("macro") + : EntityList(path, "macro") { - rescan(path); + rescan(); } @@ -47,8 +47,9 @@ void MacroList::addFile(std::string file) try { parser.parse(); Macro *macro = parser.getMacro(); - std::pair p(VersionStr(macro->attributes["version"]), file); - (*this)[macro->attributes["name"]].insert(p); + insertEntity(macro->attributes["name"], + macro->attributes["version"], + file); } catch(Exception &e) { PRACRO_WARN(macrolist, "Skipping %s: %s\n", file.c_str(), e.what()); } diff --git a/server/src/templatelist.cc b/server/src/templatelist.cc index 0fc8ec5..b8e8462 100644 --- a/server/src/templatelist.cc +++ b/server/src/templatelist.cc @@ -32,9 +32,9 @@ #include "debug.h" TemplateList::TemplateList(std::string path) - : EntityList("template") + : EntityList(path, "template") { - rescan(path); + rescan(); } void TemplateList::addFile(std::string file) @@ -44,8 +44,9 @@ void TemplateList::addFile(std::string file) try { parser.parse(); Template *templ = parser.getTemplate(); - std::pair p(VersionStr(templ->attributes["version"]), file); - (*this)[templ->attributes["name"]].insert(p); + insertEntity(templ->attributes["name"], + templ->attributes["version"], + file); } catch(Exception &e) { PRACRO_WARN(templatelist, "Skipping %s: %s\n", file.c_str(), e.what()); } -- cgit v1.2.3