diff --git a/static_file_handler.hpp b/static_file_handler.hpp index d7bbe7f..f7dc4cb 100644 --- a/static_file_handler.hpp +++ b/static_file_handler.hpp @@ -11,9 +11,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include using std::string_view; using std::string; @@ -27,6 +31,11 @@ private: std::unordered_set file_index_; mutable std::shared_mutex index_mutex_; size_t max_cache_size_ = 50 * 1024 * 1024; // 50MB cache limit + + int inotify_fd_ = -1; + int watch_fd_ = -1; + std::thread watch_thread_; + std::atomic stop_watching_{false}; void build_file_index() { std::unique_lock lock(index_mutex_); @@ -44,6 +53,34 @@ private: } } + void invalidate_cache() { + std::unique_lock lock(index_mutex_); + cache_.clear(); + } + + void watch_files() { + char buffer[4096]; + while (!stop_watching_) { + int len = read(inotify_fd_, buffer, sizeof(buffer)); + if (len <= 0) continue; + + bool needs_rebuild = false; + for (int i = 0; i < len;) { + struct inotify_event* event = (struct inotify_event*)&buffer[i]; + if (event->mask & (IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO)) { + needs_rebuild = true; + break; + } + i += sizeof(struct inotify_event) + event->len; + } + + if (needs_rebuild) { + build_file_index(); + invalidate_cache(); + } + } + } + bool file_exists_fast(const string& relative_path) const { std::shared_lock lock(index_mutex_); return file_index_.count(relative_path) > 0; @@ -106,6 +143,31 @@ public: url_prefix_ += '/'; } build_file_index(); + start_watching(); + } + + ~StaticFileHandler() { + stop_watching_ = true; + if (watch_thread_.joinable()) { + watch_thread_.join(); + } + if (watch_fd_ != -1) close(watch_fd_); + if (inotify_fd_ != -1) close(inotify_fd_); + } + + void start_watching() { + inotify_fd_ = inotify_init1(IN_NONBLOCK); + if (inotify_fd_ == -1) return; + + watch_fd_ = inotify_add_watch(inotify_fd_, root_path_.c_str(), + IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO); + if (watch_fd_ == -1) { + close(inotify_fd_); + inotify_fd_ = -1; + return; + } + + watch_thread_ = std::thread(&StaticFileHandler::watch_files, this); } void refresh_index() {