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