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