diff --git a/calendar-daemon.cpp b/calendar-daemon.cpp index ed89b38..781af00 100644 --- a/calendar-daemon.cpp +++ b/calendar-daemon.cpp @@ -10,17 +10,21 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include const int MINUTE = 1000000; +const int MINUTE = 60; +const int SLEEP_INTERVAL = 60 * MINUTE; sql::Database* init_database(std::string calendar) { return db::init(calendar + ".db"); @@ -34,6 +38,10 @@ void update_database(std::string directory, sql::Database *db) { } } +void init_fswatcher(std::string directory, sql::Database *db) { + db::FSWatcher fswatcher(db, directory); + fswatcher.run(); +} void do_heartbeat(std::string directory, sql::Database *db) { util::notify("Updating files from " + directory, ""); update_database(directory, db); @@ -104,6 +112,7 @@ int main(void) std::string directory = "/home/stefan/.local/share/khal/calendars/" + calendar + "/"; sql::Database* db = init_database(calendar); + std::thread thread([&](){ init_fswatcher(directory, db); }); // Enter daemon loop while(1) diff --git a/db/FSWatcher.cpp b/db/FSWatcher.cpp new file mode 100644 index 0000000..00756c0 --- /dev/null +++ b/db/FSWatcher.cpp @@ -0,0 +1,79 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + +bool is_ics(const std::filesystem::path filepath) { + return filepath.extension() == ".ics"; +} + +namespace db { + + FSWatcher::FSWatcher(sql::Database *db, const std::string &directory) : m_db(db), m_directory(directory) {} + + void FSWatcher::run() { + // Parse the directory to watch + std::filesystem::path path(m_directory); + + // Set the event handler which will be used to process particular events + auto create_entry = [&](inotify::Notification notification) { + create_event(notification.path); + }; + + auto modify_entry = [&](inotify::Notification notification) { + modify_event(notification.path); + }; + + auto remove_entry = [&](inotify::Notification notification) { + delete_event(notification.path); + }; + + /* + auto handleUnexpectedNotification = [](inotify::Notification notification) { + std::cout << "Event " << notification.event << " on " << notification.path << " at " + << notification.time.time_since_epoch().count() + << " was triggered, but was not expected" << std::endl; + }; + */ + + auto file_creation = { inotify::Event::create }; + auto file_deletion = { inotify::Event::remove }; + auto file_modification = { inotify::Event::moved_to }; + + // The notifier is configured to watch the parsed path for the defined events. Particular files + // or paths can be ignored(once). + auto notifier = inotify::BuildNotifier() + .watchPathRecursively(path) + .onEvents(file_creation, create_entry) + .onEvents(file_modification, modify_entry) + .onEvents(file_deletion, remove_entry); + + // The event loop is started in a separate thread context. + notifier.run(); + } + + void FSWatcher::create_event(const std::string event_file) { + if(!is_ics(event_file)) return; + ical::IcalObject* object = new ical::IcalObject(); + util::parse_main_component(object, util::parse_ics_file(event_file)); + db::insert_events(m_db, object); + DEBUG << "Created Event " << event_file; + + } + + void FSWatcher::modify_event(const std::string event_file) { + if(!is_ics(event_file)) return; + DEBUG << "Modified Event " << event_file; + } + + void FSWatcher::delete_event(const std::string event_file) { + if(!is_ics(event_file)) return; + DEBUG << "Removing Event " << event_file; + } +} diff --git a/db/FSWatcher.h b/db/FSWatcher.h new file mode 100644 index 0000000..19c81e9 --- /dev/null +++ b/db/FSWatcher.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace db { + class FSWatcher { + public: + FSWatcher(sql::Database *db, const std::string &directory); + + void run(); + + void create_event(const std::string event_file); + void modify_event(const std::string event_file); + void delete_event(const std::string event_file); + private: + sql::Database* m_db; + const std::string m_directory; + }; +}