1c540156cSNicolas Bonnefon #ifndef INOTIFYWATCHTOWERDRIVER_H 2c540156cSNicolas Bonnefon #define INOTIFYWATCHTOWERDRIVER_H 3c540156cSNicolas Bonnefon 4b278d183SNicolas Bonnefon #include <memory> 5b278d183SNicolas Bonnefon #include <mutex> 6b278d183SNicolas Bonnefon #include <vector> 7c540156cSNicolas Bonnefon 8f09fa651SNicolas Bonnefon template <typename Driver> 9b278d183SNicolas Bonnefon class ObservedFile; 10f09fa651SNicolas Bonnefon template <typename Driver> 11b278d183SNicolas Bonnefon class ObservedFileList; 12b278d183SNicolas Bonnefon 13b278d183SNicolas Bonnefon class INotifyWatchTowerDriver { 14c540156cSNicolas Bonnefon public: 15b278d183SNicolas Bonnefon class FileId { 16b278d183SNicolas Bonnefon public: 17b278d183SNicolas Bonnefon friend class INotifyWatchTowerDriver; 18b278d183SNicolas Bonnefon 19dc7f5916SNicolas Bonnefon FileId() { wd_ = -1; } 20b278d183SNicolas Bonnefon bool operator==( const FileId& other ) const 21b278d183SNicolas Bonnefon { return wd_ == other.wd_; } 22b278d183SNicolas Bonnefon private: 23b278d183SNicolas Bonnefon FileId( int wd ) { wd_ = wd; } 24dc7f5916SNicolas Bonnefon int wd_; 25c540156cSNicolas Bonnefon }; 26b278d183SNicolas Bonnefon class DirId { 27b278d183SNicolas Bonnefon public: 28b278d183SNicolas Bonnefon friend class INotifyWatchTowerDriver; 29b278d183SNicolas Bonnefon 30dc7f5916SNicolas Bonnefon DirId() { wd_ = -1; } 31b278d183SNicolas Bonnefon bool operator==( const DirId& other ) const 32b278d183SNicolas Bonnefon { return wd_ == other.wd_; } 33b278d183SNicolas Bonnefon private: 34b278d183SNicolas Bonnefon DirId( int wd ) { wd_ = wd; } 35dc7f5916SNicolas Bonnefon int wd_; 36c540156cSNicolas Bonnefon }; 37b278d183SNicolas Bonnefon class SymlinkId { 38b278d183SNicolas Bonnefon public: 39b278d183SNicolas Bonnefon friend class INotifyWatchTowerDriver; 40b278d183SNicolas Bonnefon 41dc7f5916SNicolas Bonnefon SymlinkId() { wd_ = -1; } 42b278d183SNicolas Bonnefon bool operator==( const SymlinkId& other ) const 43b278d183SNicolas Bonnefon { return wd_ == other.wd_; } 44b278d183SNicolas Bonnefon private: 45b278d183SNicolas Bonnefon SymlinkId( int wd ) { wd_ = wd; } 46dc7f5916SNicolas Bonnefon int wd_; 47c540156cSNicolas Bonnefon }; 48c540156cSNicolas Bonnefon 4958f443c7SNicolas Bonnefon #ifdef HAS_TEMPLATE_ALIASES 50f09fa651SNicolas Bonnefon using INotifyObservedFile = ObservedFile<INotifyWatchTowerDriver>; 51f09fa651SNicolas Bonnefon using INotifyObservedFileList = ObservedFileList<INotifyWatchTowerDriver>; 5258f443c7SNicolas Bonnefon #else 5358f443c7SNicolas Bonnefon typedef ObservedFile<INotifyWatchTowerDriver> INotifyObservedFile; 5458f443c7SNicolas Bonnefon typedef ObservedFileList<INotifyWatchTowerDriver> INotifyObservedFileList; 5558f443c7SNicolas Bonnefon #endif 56f09fa651SNicolas Bonnefon 57f09fa651SNicolas Bonnefon // Default constructor 58c540156cSNicolas Bonnefon INotifyWatchTowerDriver(); 59b0345991SNicolas Bonnefon ~INotifyWatchTowerDriver(); 60b0345991SNicolas Bonnefon 61b0345991SNicolas Bonnefon // No copy/assign/move please 62b0345991SNicolas Bonnefon INotifyWatchTowerDriver( const INotifyWatchTowerDriver& ) = delete; 63b0345991SNicolas Bonnefon INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver& ) = delete; 64b0345991SNicolas Bonnefon INotifyWatchTowerDriver( const INotifyWatchTowerDriver&& ) = delete; 65b0345991SNicolas Bonnefon INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver&& ) = delete; 66c540156cSNicolas Bonnefon 67b278d183SNicolas Bonnefon FileId addFile( const std::string& file_name ); 68b278d183SNicolas Bonnefon SymlinkId addSymlink( const std::string& file_name ); 69b278d183SNicolas Bonnefon DirId addDir( const std::string& file_name ); 70c540156cSNicolas Bonnefon 71b278d183SNicolas Bonnefon void removeFile( const FileId& file_id ); 72b278d183SNicolas Bonnefon void removeSymlink( const SymlinkId& symlink_id ); 73*3104b268SNicolas Bonnefon void removeDir( const DirId& dir_id ); 74c540156cSNicolas Bonnefon 75*3104b268SNicolas Bonnefon // Wait for an event for the OS, treat it and 76*3104b268SNicolas Bonnefon // return a list of files to notify about. 77*3104b268SNicolas Bonnefon // This must be called with the lock on the list held, 78*3104b268SNicolas Bonnefon // the function will unlock it temporary whilst blocking. 79f09fa651SNicolas Bonnefon std::vector<INotifyObservedFile*> waitAndProcessEvents( 80f09fa651SNicolas Bonnefon INotifyObservedFileList* list, 81*3104b268SNicolas Bonnefon std::unique_lock<std::mutex>* list_mutex ); 82*3104b268SNicolas Bonnefon 83*3104b268SNicolas Bonnefon // Interrupt waitAndProcessEvents if it is blocking. 84b0345991SNicolas Bonnefon void interruptWait(); 85b278d183SNicolas Bonnefon 86b278d183SNicolas Bonnefon private: 87b278d183SNicolas Bonnefon // Only written at initialisation so no protection needed. 88b278d183SNicolas Bonnefon const int inotify_fd_; 89b278d183SNicolas Bonnefon 90b0345991SNicolas Bonnefon // Breaking pipe 91b0345991SNicolas Bonnefon int breaking_pipe_read_fd_; 92b0345991SNicolas Bonnefon int breaking_pipe_write_fd_; 93b0345991SNicolas Bonnefon 94b278d183SNicolas Bonnefon // Private member functions 95b278d183SNicolas Bonnefon size_t processINotifyEvent( const struct inotify_event* event, 96f09fa651SNicolas Bonnefon INotifyObservedFileList* list, 97f09fa651SNicolas Bonnefon std::vector<INotifyObservedFile*>* files_to_notify ); 98c540156cSNicolas Bonnefon }; 99c540156cSNicolas Bonnefon 100c540156cSNicolas Bonnefon #endif 101