/*
* Copyright (C) 2015 Nicolas Bonnefon and other contributors
*
* This file is part of glogg.
*
* glogg is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* glogg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with glogg. If not, see .
*/
#ifndef INOTIFYWATCHTOWERDRIVER_H
#define INOTIFYWATCHTOWERDRIVER_H
#include
#include
#include
template
class ObservedFile;
template
class ObservedFileList;
class INotifyWatchTowerDriver {
public:
class FileId {
public:
friend class INotifyWatchTowerDriver;
FileId() { wd_ = -1; }
bool operator==( const FileId& other ) const
{ return wd_ == other.wd_; }
private:
FileId( int wd ) { wd_ = wd; }
int wd_;
};
class DirId {
public:
friend class INotifyWatchTowerDriver;
DirId() { wd_ = -1; }
bool operator==( const DirId& other ) const
{ return wd_ == other.wd_; }
bool valid() const
{ return (wd_ != -1); }
private:
DirId( int wd ) { wd_ = wd; }
int wd_;
};
class SymlinkId {
public:
friend class INotifyWatchTowerDriver;
SymlinkId() { wd_ = -1; }
bool operator==( const SymlinkId& other ) const
{ return wd_ == other.wd_; }
private:
SymlinkId( int wd ) { wd_ = wd; }
int wd_;
};
// Dummy class for inotify
class FileChangeToken {
public:
FileChangeToken() {}
FileChangeToken( const std::string& ) {}
void readFromFile( const std::string& ) {}
bool operator!=( const FileChangeToken& )
{ return true; }
};
#ifdef HAS_TEMPLATE_ALIASES
using INotifyObservedFile = ObservedFile;
using INotifyObservedFileList = ObservedFileList;
#else
typedef ObservedFile INotifyObservedFile;
typedef ObservedFileList INotifyObservedFileList;
#endif
// Default constructor
INotifyWatchTowerDriver();
~INotifyWatchTowerDriver();
// No copy/assign/move please
INotifyWatchTowerDriver( const INotifyWatchTowerDriver& ) = delete;
INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver& ) = delete;
INotifyWatchTowerDriver( const INotifyWatchTowerDriver&& ) = delete;
INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver&& ) = delete;
FileId addFile( const std::string& file_name );
SymlinkId addSymlink( const std::string& file_name );
DirId addDir( const std::string& file_name );
void removeFile( const FileId& file_id );
void removeSymlink( const SymlinkId& symlink_id );
void removeDir( const DirId& dir_id );
// Wait for an event for the OS, treat it and
// return a list of files to notify about.
// This must be called with the lock on the list held,
// the function will unlock it temporary whilst blocking.
// Also returns a list of file that need readding
// (because of renames/symlink...)
std::vector waitAndProcessEvents(
INotifyObservedFileList* list,
std::unique_lock* list_mutex,
std::vector* files_needing_readding,
int timeout_ms );
// Interrupt waitAndProcessEvents if it is blocking.
void interruptWait();
private:
// Only written at initialisation so no protection needed.
const int inotify_fd_;
// Breaking pipe
int breaking_pipe_read_fd_;
int breaking_pipe_write_fd_;
// Private member functions
size_t processINotifyEvent( const struct inotify_event* event,
INotifyObservedFileList* list,
std::vector* files_to_notify,
std::vector* files_needing_readding );
};
#endif