1 #ifndef WATCHTOWERLIST_H 2 #define WATCHTOWERLIST_H 3 4 // Utility classes for the WatchTower implementations 5 6 #include <functional> 7 #include <string> 8 #include <vector> 9 #include <map> 10 #include <list> 11 #include <memory> 12 #include <algorithm> 13 14 // Utility classes 15 struct ProtocolInfo { 16 // Win32 notification variables 17 static const int READ_DIR_CHANGE_BUFFER_SIZE = 4096; 18 19 void* handle_; 20 static const unsigned long buffer_length_ = READ_DIR_CHANGE_BUFFER_SIZE; 21 char buffer_[buffer_length_]; 22 }; 23 24 // List of files and observers 25 struct ObservedDir { 26 ObservedDir( const std::string this_path ) : path { this_path } {} 27 28 // Returns the address of the protocol specific informations 29 ProtocolInfo* protocolInfo() { return &protocol_info_; } 30 31 std::string path; 32 int dir_wd_; 33 // Contains data specific to the protocol (inotify/Win32...) 34 ProtocolInfo protocol_info_; 35 }; 36 37 struct ObservedFile { 38 ObservedFile( 39 const std::string& file_name, 40 std::shared_ptr<void> callback, 41 int file_wd, 42 int symlink_wd ) : file_name_( file_name ) { 43 addCallback( callback ); 44 45 file_wd_ = file_wd; 46 symlink_wd_ = symlink_wd; 47 dir_ = nullptr; 48 } 49 50 void addCallback( std::shared_ptr<void> callback ) { 51 callbacks.push_back( callback ); 52 } 53 54 std::string file_name_; 55 // List of callbacks for this file 56 std::vector<std::shared_ptr<void>> callbacks; 57 58 // watch descriptor for the file itself 59 int file_wd_; 60 // watch descriptor for the symlink (if file is a symlink) 61 int symlink_wd_; 62 63 // link to the dir containing the file 64 std::shared_ptr<ObservedDir> dir_; 65 }; 66 67 // A list of the observed files and directories 68 // This class is not thread safe 69 class ObservedFileList { 70 public: 71 ObservedFileList() = default; 72 ~ObservedFileList() = default; 73 74 ObservedFile* searchByName( const std::string& file_name ); 75 ObservedFile* searchByFileOrSymlinkWd( int wd ); 76 ObservedFile* searchByDirWdAndName( int wd, const char* name ); 77 78 ObservedFile* addNewObservedFile( ObservedFile new_observed ); 79 // Remove a callback, remove and returns the file object if 80 // it was the last callback on this object, nullptr if not. 81 // The caller has ownership of the object. 82 std::shared_ptr<ObservedFile> removeCallback( 83 std::shared_ptr<void> callback ); 84 85 // Return the watched directory if it is watched, or nullptr 86 std::shared_ptr<ObservedDir> watchedDirectory( const std::string& dir_name ); 87 // Create a new watched directory for dir_name 88 std::shared_ptr<ObservedDir> addWatchedDirectory( const std::string& dir_name ); 89 90 std::shared_ptr<ObservedDir> watchedDirectoryForFile( const std::string& file_name ); 91 std::shared_ptr<ObservedDir> addWatchedDirectoryForFile( const std::string& file_name ); 92 93 private: 94 // List of observed files 95 std::list<ObservedFile> observed_files_; 96 97 // List of observed dirs, key-ed by name 98 std::map<std::string, std::weak_ptr<ObservedDir>> observed_dirs_; 99 100 // Map the inotify file (including symlinks) wds to the observed file 101 std::map<int, ObservedFile*> by_file_wd_; 102 // Map the inotify directory wds to the observed files 103 std::map<int, ObservedFile*> by_dir_wd_; 104 }; 105 106 #endif 107