Skip to content

Commit ad4ac90

Browse files
committed
Added LinuxProduceSyntheticEvents option for issue #192.
1 parent 87abe59 commit ad4ac90

File tree

6 files changed

+46
-8
lines changed

6 files changed

+46
-8
lines changed

.ecode/project_build.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,16 @@
3131
"preset": "generic",
3232
"relative_file_paths": true
3333
}
34-
}
34+
},
35+
"run": [
36+
{
37+
"args": "",
38+
"command": "efsw-test-debug",
39+
"name": "efsw-test-debug",
40+
"run_in_terminal": true,
41+
"working_dir": "${project_root}/bin"
42+
}
43+
]
3544
},
3645
"linux-release": {
3746
"build": [

include/efsw/efsw.h

+7
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ enum efsw_option {
106106
/// the number of events reported. This will have an small performance and memory impact as a
107107
/// consequence.
108108
EFSW_OPT_MAC_SANITIZE_EVENTS = 4,
109+
/// Linux does not support natively recursive watchers. This means that when using recursive
110+
/// watches efsw registers new watchers for each directory. If new file are created between
111+
/// the time efsw takes to register the new directory those events might be missed. To avoid
112+
/// missing new file notifications efsw will trigger synthetic new file events for existing
113+
/// files in the new directroy watched. This might have the unintended consequence of sending
114+
/// duplicated created events due to the system also emitting this event.
115+
LINUX_PRODUCE_SYNTHETIC_EVENTS = 5,
109116
};
110117

111118
/// Basic interface for listening for file events.

include/efsw/efsw.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@ enum Option {
148148
/// the number of events reported. This will have an small performance and memory impact as a
149149
/// consequence.
150150
MacSanitizeEvents = 4,
151+
/// Linux does not support natively recursive watchers. This means that when using recursive
152+
/// watches efsw registers new watchers for each directory. If new file are created between
153+
/// the time efsw takes to register the new directory those events might be missed. To avoid
154+
/// missing new file notifications efsw will trigger synthetic created file events for existing
155+
/// files in the new directroy watched. This might have the unintended consequence of sending
156+
/// duplicated created events due to the system also emitting this event.
157+
LinuxProduceSyntheticEvents = 5,
151158
};
152159
}
153160
typedef Options::Option Option;

src/efsw/FileWatcherInotify.cpp

+19-6
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,17 @@ FileWatcherInotify::~FileWatcherInotify() {
6969
}
7070

7171
WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher,
72-
bool recursive, const std::vector<WatcherOption>& ) {
72+
bool recursive, const std::vector<WatcherOption>& options ) {
7373
if ( !mInitOK )
7474
return Errors::Log::createLastError( Errors::Unspecified, directory );
7575
Lock initLock( mInitLock );
76-
return addWatch( directory, watcher, recursive, NULL );
76+
bool syntheticEvents = getOptionValue( options, Options::LinuxProduceSyntheticEvents, 0 ) != 0;
77+
return addWatch( directory, watcher, recursive, syntheticEvents, NULL );
7778
}
7879

7980
WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher,
80-
bool recursive, WatcherInotify* parent ) {
81+
bool recursive, bool syntheticEvents,
82+
WatcherInotify* parent, bool fromInternalEvent ) {
8183
std::string dir( directory );
8284

8385
FileSystem::dirAddSlashAtEnd( dir );
@@ -160,7 +162,17 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis
160162
const FileInfo& cfi = it->second;
161163

162164
if ( cfi.isDirectory() && cfi.isReadable() ) {
163-
addWatch( cfi.Filepath, watcher, recursive, pWatch );
165+
addWatch( cfi.Filepath, watcher, recursive, syntheticEvents, pWatch );
166+
}
167+
}
168+
169+
if ( fromInternalEvent && parent != NULL && syntheticEvents ) {
170+
for ( const auto& file : files ) {
171+
if ( file.second.isRegularFile() ) {
172+
pWatch->Listener->handleFileAction(
173+
pWatch->ID, pWatch->Directory,
174+
FileSystem::fileNameFromPath( file.second.Filepath ), Actions::Add );
175+
}
164176
}
165177
}
166178
}
@@ -448,8 +460,9 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath )
448460
}
449461

450462
if ( !found ) {
451-
addWatch( fpath, watch->Listener, watch->Recursive,
452-
static_cast<WatcherInotify*>( watch ) );
463+
WatcherInotify* iWatch = static_cast<WatcherInotify*>( watch );
464+
addWatch( fpath, watch->Listener, watch->Recursive, iWatch->syntheticEvents,
465+
static_cast<WatcherInotify*>( watch ), true );
453466
}
454467
}
455468
}

src/efsw/FileWatcherInotify.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ class FileWatcherInotify : public FileWatcherImpl {
6565
std::vector<std::pair<WatcherInotify*, std::string>> mMovedOutsideWatches;
6666

6767
WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive,
68-
WatcherInotify* parent = NULL );
68+
bool syntheticEvents, WatcherInotify* parent = NULL,
69+
bool fromInternalEvent = false );
6970

7071
bool pathInWatches( const std::string& path ) override;
7172

src/efsw/WatcherInotify.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class WatcherInotify : public Watcher {
1616
WatchID InotifyID;
1717

1818
FileInfo DirInfo;
19+
bool syntheticEvents{ false };
1920
};
2021

2122
} // namespace efsw

0 commit comments

Comments
 (0)