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