xref: /glogg/src/watchtowerlist.h (revision c540156c41190af6e419dffb1b2c43c87fdd3cde)
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