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