1*9ebe83d5SNicolas Bonnefon /* 2*9ebe83d5SNicolas Bonnefon * Copyright (C) 2015 Nicolas Bonnefon and other contributors 3*9ebe83d5SNicolas Bonnefon * 4*9ebe83d5SNicolas Bonnefon * This file is part of glogg. 5*9ebe83d5SNicolas Bonnefon * 6*9ebe83d5SNicolas Bonnefon * glogg is free software: you can redistribute it and/or modify 7*9ebe83d5SNicolas Bonnefon * it under the terms of the GNU General Public License as published by 8*9ebe83d5SNicolas Bonnefon * the Free Software Foundation, either version 3 of the License, or 9*9ebe83d5SNicolas Bonnefon * (at your option) any later version. 10*9ebe83d5SNicolas Bonnefon * 11*9ebe83d5SNicolas Bonnefon * glogg is distributed in the hope that it will be useful, 12*9ebe83d5SNicolas Bonnefon * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*9ebe83d5SNicolas Bonnefon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*9ebe83d5SNicolas Bonnefon * GNU General Public License for more details. 15*9ebe83d5SNicolas Bonnefon * 16*9ebe83d5SNicolas Bonnefon * You should have received a copy of the GNU General Public License 17*9ebe83d5SNicolas Bonnefon * along with glogg. If not, see <http://www.gnu.org/licenses/>. 18*9ebe83d5SNicolas Bonnefon */ 19*9ebe83d5SNicolas 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 38dc7f5916SNicolas Bonnefon FileId() { wd_ = -1; } 39b278d183SNicolas Bonnefon bool operator==( const FileId& other ) const 40b278d183SNicolas Bonnefon { return wd_ == other.wd_; } 41b278d183SNicolas Bonnefon private: 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 49dc7f5916SNicolas Bonnefon DirId() { wd_ = -1; } 50b278d183SNicolas Bonnefon bool operator==( const DirId& other ) const 51b278d183SNicolas Bonnefon { return wd_ == other.wd_; } 528b11848fSNicolas Bonnefon bool valid() const 538b11848fSNicolas Bonnefon { return (wd_ != -1); } 54b278d183SNicolas Bonnefon private: 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 62dc7f5916SNicolas Bonnefon SymlinkId() { wd_ = -1; } 63b278d183SNicolas Bonnefon bool operator==( const SymlinkId& other ) const 64b278d183SNicolas Bonnefon { return wd_ == other.wd_; } 65b278d183SNicolas Bonnefon private: 66b278d183SNicolas Bonnefon SymlinkId( int wd ) { wd_ = wd; } 67dc7f5916SNicolas Bonnefon int wd_; 68c540156cSNicolas Bonnefon }; 69c540156cSNicolas Bonnefon 7058f443c7SNicolas Bonnefon #ifdef HAS_TEMPLATE_ALIASES 71f09fa651SNicolas Bonnefon using INotifyObservedFile = ObservedFile<INotifyWatchTowerDriver>; 72f09fa651SNicolas Bonnefon using INotifyObservedFileList = ObservedFileList<INotifyWatchTowerDriver>; 7358f443c7SNicolas Bonnefon #else 7458f443c7SNicolas Bonnefon typedef ObservedFile<INotifyWatchTowerDriver> INotifyObservedFile; 7558f443c7SNicolas Bonnefon typedef ObservedFileList<INotifyWatchTowerDriver> INotifyObservedFileList; 7658f443c7SNicolas Bonnefon #endif 77f09fa651SNicolas Bonnefon 78f09fa651SNicolas Bonnefon // Default constructor 79c540156cSNicolas Bonnefon INotifyWatchTowerDriver(); 80b0345991SNicolas Bonnefon ~INotifyWatchTowerDriver(); 81b0345991SNicolas Bonnefon 82b0345991SNicolas Bonnefon // No copy/assign/move please 83b0345991SNicolas Bonnefon INotifyWatchTowerDriver( const INotifyWatchTowerDriver& ) = delete; 84b0345991SNicolas Bonnefon INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver& ) = delete; 85b0345991SNicolas Bonnefon INotifyWatchTowerDriver( const INotifyWatchTowerDriver&& ) = delete; 86b0345991SNicolas Bonnefon INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver&& ) = delete; 87c540156cSNicolas Bonnefon 88b278d183SNicolas Bonnefon FileId addFile( const std::string& file_name ); 89b278d183SNicolas Bonnefon SymlinkId addSymlink( const std::string& file_name ); 90b278d183SNicolas Bonnefon DirId addDir( const std::string& file_name ); 91c540156cSNicolas Bonnefon 92b278d183SNicolas Bonnefon void removeFile( const FileId& file_id ); 93b278d183SNicolas Bonnefon void removeSymlink( const SymlinkId& symlink_id ); 943104b268SNicolas Bonnefon void removeDir( const DirId& dir_id ); 95c540156cSNicolas Bonnefon 963104b268SNicolas Bonnefon // Wait for an event for the OS, treat it and 973104b268SNicolas Bonnefon // return a list of files to notify about. 983104b268SNicolas Bonnefon // This must be called with the lock on the list held, 993104b268SNicolas Bonnefon // the function will unlock it temporary whilst blocking. 10091f7c705SNicolas Bonnefon // Also returns a list of file that need readding 10191f7c705SNicolas Bonnefon // (because of renames/symlink...) 102f09fa651SNicolas Bonnefon std::vector<INotifyObservedFile*> waitAndProcessEvents( 103f09fa651SNicolas Bonnefon INotifyObservedFileList* list, 10491f7c705SNicolas Bonnefon std::unique_lock<std::mutex>* list_mutex, 10591f7c705SNicolas Bonnefon std::vector<INotifyObservedFile*>* files_needing_readding ); 1063104b268SNicolas Bonnefon 1073104b268SNicolas Bonnefon // Interrupt waitAndProcessEvents if it is blocking. 108b0345991SNicolas Bonnefon void interruptWait(); 109b278d183SNicolas Bonnefon 110b278d183SNicolas Bonnefon private: 111b278d183SNicolas Bonnefon // Only written at initialisation so no protection needed. 112b278d183SNicolas Bonnefon const int inotify_fd_; 113b278d183SNicolas Bonnefon 114b0345991SNicolas Bonnefon // Breaking pipe 115b0345991SNicolas Bonnefon int breaking_pipe_read_fd_; 116b0345991SNicolas Bonnefon int breaking_pipe_write_fd_; 117b0345991SNicolas Bonnefon 118b278d183SNicolas Bonnefon // Private member functions 119b278d183SNicolas Bonnefon size_t processINotifyEvent( const struct inotify_event* event, 120f09fa651SNicolas Bonnefon INotifyObservedFileList* list, 12191f7c705SNicolas Bonnefon std::vector<INotifyObservedFile*>* files_to_notify, 12291f7c705SNicolas Bonnefon std::vector<INotifyObservedFile*>* files_needing_readding ); 123c540156cSNicolas Bonnefon }; 124c540156cSNicolas Bonnefon 125c540156cSNicolas Bonnefon #endif 126