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