xref: /glogg/src/inotifywatchtowerdriver.h (revision 4fc8b18a21bd30bff0e4e47756c46ed70894d2ee)
1 /*
2  * Copyright (C) 2015 Nicolas Bonnefon and other contributors
3  *
4  * This file is part of glogg.
5  *
6  * glogg is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * glogg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef INOTIFYWATCHTOWERDRIVER_H
21 #define INOTIFYWATCHTOWERDRIVER_H
22 
23 #include <memory>
24 #include <mutex>
25 #include <vector>
26 
27 template <typename Driver>
28 class ObservedFile;
29 template <typename Driver>
30 class ObservedFileList;
31 
32 class INotifyWatchTowerDriver {
33   public:
34     class FileId {
35       public:
36         friend class INotifyWatchTowerDriver;
37 
FileId()38         FileId() { wd_ = -1; }
39         bool operator==( const FileId& other ) const
40         { return wd_ == other.wd_; }
41       private:
FileId(int wd)42         FileId( int wd ) { wd_ = wd; }
43         int wd_;
44     };
45     class DirId {
46       public:
47         friend class INotifyWatchTowerDriver;
48 
DirId()49         DirId() { wd_ = -1; }
50         bool operator==( const DirId& other ) const
51         { return wd_ == other.wd_; }
valid()52         bool valid() const
53         { return (wd_ != -1); }
54       private:
DirId(int wd)55         DirId( int wd ) { wd_ = wd; }
56         int wd_;
57     };
58     class SymlinkId {
59       public:
60         friend class INotifyWatchTowerDriver;
61 
SymlinkId()62         SymlinkId() { wd_ = -1; }
63         bool operator==( const SymlinkId& other ) const
64         { return wd_ == other.wd_; }
65       private:
SymlinkId(int wd)66         SymlinkId( int wd ) { wd_ = wd; }
67         int wd_;
68     };
69 
70     // Dummy class for inotify
71     class FileChangeToken {
72       public:
FileChangeToken()73         FileChangeToken() {}
FileChangeToken(const std::string &)74         FileChangeToken( const std::string& ) {}
75 
readFromFile(const std::string &)76         void readFromFile( const std::string& ) {}
77 
78         bool operator!=( const FileChangeToken& )
79         { return true; }
80     };
81 
82 #ifdef HAS_TEMPLATE_ALIASES
83     using INotifyObservedFile = ObservedFile<INotifyWatchTowerDriver>;
84     using INotifyObservedFileList = ObservedFileList<INotifyWatchTowerDriver>;
85 #else
86     typedef ObservedFile<INotifyWatchTowerDriver> INotifyObservedFile;
87     typedef ObservedFileList<INotifyWatchTowerDriver> INotifyObservedFileList;
88 #endif
89 
90     // Default constructor
91     INotifyWatchTowerDriver();
92     ~INotifyWatchTowerDriver();
93 
94     // No copy/assign/move please
95     INotifyWatchTowerDriver( const INotifyWatchTowerDriver& ) = delete;
96     INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver& ) = delete;
97     INotifyWatchTowerDriver( const INotifyWatchTowerDriver&& ) = delete;
98     INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver&& ) = delete;
99 
100     FileId addFile( const std::string& file_name );
101     SymlinkId addSymlink( const std::string& file_name );
102     DirId addDir( const std::string& file_name );
103 
104     void removeFile( const FileId& file_id );
105     void removeSymlink( const SymlinkId& symlink_id );
106     void removeDir( const DirId& dir_id );
107 
108     // Wait for an event for the OS, treat it and
109     // return a list of files to notify about.
110     // This must be called with the lock on the list held,
111     // the function will unlock it temporary whilst blocking.
112     // Also returns a list of file that need readding
113     // (because of renames/symlink...)
114     std::vector<INotifyObservedFile*> waitAndProcessEvents(
115             INotifyObservedFileList* list,
116             std::unique_lock<std::mutex>* list_mutex,
117             std::vector<INotifyObservedFile*>* files_needing_readding,
118             int timeout_ms );
119 
120     // Interrupt waitAndProcessEvents if it is blocking.
121     void interruptWait();
122 
123   private:
124     // Only written at initialisation so no protection needed.
125     const int inotify_fd_;
126 
127     // Breaking pipe
128     int breaking_pipe_read_fd_;
129     int breaking_pipe_write_fd_;
130 
131     // Private member functions
132     size_t processINotifyEvent( const struct inotify_event* event,
133             INotifyObservedFileList* list,
134             std::vector<INotifyObservedFile*>* files_to_notify,
135             std::vector<INotifyObservedFile*>* files_needing_readding );
136 };
137 
138 #endif
139