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