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_; } 33*8b11848fSNicolas Bonnefon bool valid() const 34*8b11848fSNicolas Bonnefon { return (wd_ != -1); } 35b278d183SNicolas Bonnefon private: 36b278d183SNicolas Bonnefon DirId( int wd ) { wd_ = wd; } 37dc7f5916SNicolas Bonnefon int wd_; 38c540156cSNicolas Bonnefon }; 39b278d183SNicolas Bonnefon class SymlinkId { 40b278d183SNicolas Bonnefon public: 41b278d183SNicolas Bonnefon friend class INotifyWatchTowerDriver; 42b278d183SNicolas Bonnefon 43dc7f5916SNicolas Bonnefon SymlinkId() { wd_ = -1; } 44b278d183SNicolas Bonnefon bool operator==( const SymlinkId& other ) const 45b278d183SNicolas Bonnefon { return wd_ == other.wd_; } 46b278d183SNicolas Bonnefon private: 47b278d183SNicolas Bonnefon SymlinkId( int wd ) { wd_ = wd; } 48dc7f5916SNicolas Bonnefon int wd_; 49c540156cSNicolas Bonnefon }; 50c540156cSNicolas Bonnefon 5158f443c7SNicolas Bonnefon #ifdef HAS_TEMPLATE_ALIASES 52f09fa651SNicolas Bonnefon using INotifyObservedFile = ObservedFile<INotifyWatchTowerDriver>; 53f09fa651SNicolas Bonnefon using INotifyObservedFileList = ObservedFileList<INotifyWatchTowerDriver>; 5458f443c7SNicolas Bonnefon #else 5558f443c7SNicolas Bonnefon typedef ObservedFile<INotifyWatchTowerDriver> INotifyObservedFile; 5658f443c7SNicolas Bonnefon typedef ObservedFileList<INotifyWatchTowerDriver> INotifyObservedFileList; 5758f443c7SNicolas Bonnefon #endif 58f09fa651SNicolas Bonnefon 59f09fa651SNicolas Bonnefon // Default constructor 60c540156cSNicolas Bonnefon INotifyWatchTowerDriver(); 61b0345991SNicolas Bonnefon ~INotifyWatchTowerDriver(); 62b0345991SNicolas Bonnefon 63b0345991SNicolas Bonnefon // No copy/assign/move please 64b0345991SNicolas Bonnefon INotifyWatchTowerDriver( const INotifyWatchTowerDriver& ) = delete; 65b0345991SNicolas Bonnefon INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver& ) = delete; 66b0345991SNicolas Bonnefon INotifyWatchTowerDriver( const INotifyWatchTowerDriver&& ) = delete; 67b0345991SNicolas Bonnefon INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver&& ) = delete; 68c540156cSNicolas Bonnefon 69b278d183SNicolas Bonnefon FileId addFile( const std::string& file_name ); 70b278d183SNicolas Bonnefon SymlinkId addSymlink( const std::string& file_name ); 71b278d183SNicolas Bonnefon DirId addDir( const std::string& file_name ); 72c540156cSNicolas Bonnefon 73b278d183SNicolas Bonnefon void removeFile( const FileId& file_id ); 74b278d183SNicolas Bonnefon void removeSymlink( const SymlinkId& symlink_id ); 753104b268SNicolas Bonnefon void removeDir( const DirId& dir_id ); 76c540156cSNicolas Bonnefon 773104b268SNicolas Bonnefon // Wait for an event for the OS, treat it and 783104b268SNicolas Bonnefon // return a list of files to notify about. 793104b268SNicolas Bonnefon // This must be called with the lock on the list held, 803104b268SNicolas Bonnefon // the function will unlock it temporary whilst blocking. 8191f7c705SNicolas Bonnefon // Also returns a list of file that need readding 8291f7c705SNicolas Bonnefon // (because of renames/symlink...) 83f09fa651SNicolas Bonnefon std::vector<INotifyObservedFile*> waitAndProcessEvents( 84f09fa651SNicolas Bonnefon INotifyObservedFileList* list, 8591f7c705SNicolas Bonnefon std::unique_lock<std::mutex>* list_mutex, 8691f7c705SNicolas Bonnefon std::vector<INotifyObservedFile*>* files_needing_readding ); 873104b268SNicolas Bonnefon 883104b268SNicolas Bonnefon // Interrupt waitAndProcessEvents if it is blocking. 89b0345991SNicolas Bonnefon void interruptWait(); 90b278d183SNicolas Bonnefon 91b278d183SNicolas Bonnefon private: 92b278d183SNicolas Bonnefon // Only written at initialisation so no protection needed. 93b278d183SNicolas Bonnefon const int inotify_fd_; 94b278d183SNicolas Bonnefon 95b0345991SNicolas Bonnefon // Breaking pipe 96b0345991SNicolas Bonnefon int breaking_pipe_read_fd_; 97b0345991SNicolas Bonnefon int breaking_pipe_write_fd_; 98b0345991SNicolas Bonnefon 99b278d183SNicolas Bonnefon // Private member functions 100b278d183SNicolas Bonnefon size_t processINotifyEvent( const struct inotify_event* event, 101f09fa651SNicolas Bonnefon INotifyObservedFileList* list, 10291f7c705SNicolas Bonnefon std::vector<INotifyObservedFile*>* files_to_notify, 10391f7c705SNicolas Bonnefon std::vector<INotifyObservedFile*>* files_needing_readding ); 104c540156cSNicolas Bonnefon }; 105c540156cSNicolas Bonnefon 106c540156cSNicolas Bonnefon #endif 107