13
13
#include < windows.h>
14
14
15
15
#else // Linux
16
- #include < poll.h>
17
16
#include < limits.h>
17
+ #include < poll.h>
18
18
#include < sys/inotify.h>
19
19
#include < unistd.h>
20
20
#endif
@@ -121,39 +121,59 @@ class FileWatcherService {
121
121
auto * watcher = static_cast <FileWatcherService*>(clientCallBackInfo);
122
122
123
123
for (size_t i = 0 ; i < numEvents; i++) {
124
- if (eventFlags[i] & kFSEventStreamEventFlagItemRemoved ) {
124
+ if (eventFlags[i] & (kFSEventStreamEventFlagItemRemoved |
125
+ kFSEventStreamEventFlagItemRenamed |
126
+ kFSEventStreamEventFlagItemModified )) {
127
+ CTL_INF (" File removed: " + std::string (paths[i]));
128
+ CTL_INF (" File event detected: " + std::string (paths[i]) +
129
+ " flags: " + std::to_string (eventFlags[i]));
125
130
watcher->model_service_ ->ForceIndexingModelList ();
126
131
}
127
132
}
128
133
}
129
134
130
135
void WatcherThread () {
131
- // macOS implementation
132
- auto mypath = CFStringCreateWithCString (NULL , watch_path_.c_str (),
133
- kCFStringEncodingUTF8 );
134
- auto path_to_watch = CFArrayCreate (NULL , (const void **)&mypath, 1 , NULL );
136
+ CFRunLoopRef runLoop = CFRunLoopGetCurrent ();
135
137
136
- FSEventStreamContext context = {0 , this , NULL , NULL , NULL };
138
+ auto path = CFStringCreateWithCString (nullptr , watch_path_.c_str (),
139
+ kCFStringEncodingUTF8 );
140
+ auto path_to_watch =
141
+ CFArrayCreate (nullptr , (const void **)&path, 1 , &kCFTypeArrayCallBacks );
137
142
138
- event_stream =
139
- FSEventStreamCreate (NULL , &FileWatcherService::callback, &context,
140
- path_to_watch, kFSEventStreamEventIdSinceNow ,
141
- 0.5 , // 500ms latency
142
- kFSEventStreamCreateFlagFileEvents );
143
+ FSEventStreamContext context = {0 , this , nullptr , nullptr , nullptr };
143
144
144
- dispatch_queue_t queue = dispatch_get_main_queue ();
145
- FSEventStreamSetDispatchQueue (event_stream, queue);
146
- FSEventStreamStart (event_stream);
145
+ event_stream = FSEventStreamCreate (
146
+ nullptr , &FileWatcherService::callback, &context, path_to_watch,
147
+ kFSEventStreamEventIdSinceNow , 1 , // each second
148
+ kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer |
149
+ kFSEventStreamCreateFlagWatchRoot );
150
+
151
+ if (!event_stream) {
152
+ CFRelease (path_to_watch);
153
+ CFRelease (path);
154
+ throw std::runtime_error (" Failed to create FSEvent stream" );
155
+ }
156
+
157
+ FSEventStreamScheduleWithRunLoop (event_stream, runLoop,
158
+ kCFRunLoopDefaultMode );
159
+
160
+ if (!FSEventStreamStart (event_stream)) {
161
+ FSEventStreamInvalidate (event_stream);
162
+ FSEventStreamRelease (event_stream);
163
+ CFRelease (path_to_watch);
164
+ CFRelease (path);
165
+ throw std::runtime_error (" Failed to start FSEvent stream" );
166
+ }
147
167
148
168
while (running_) {
149
- CFRunLoopRunInMode (kCFRunLoopDefaultMode , 1.0 , false );
169
+ CFRunLoopRunInMode (kCFRunLoopDefaultMode , 0.25 , true );
150
170
}
151
171
152
172
FSEventStreamStop (event_stream);
153
173
FSEventStreamInvalidate (event_stream);
154
174
FSEventStreamRelease (event_stream);
155
175
CFRelease (path_to_watch);
156
- CFRelease (mypath );
176
+ CFRelease (path );
157
177
}
158
178
159
179
#elif defined(_WIN32)
@@ -221,22 +241,22 @@ class FileWatcherService {
221
241
const int watch_flags = IN_DELETE | IN_DELETE_SELF | IN_CREATE;
222
242
wd = inotify_add_watch (fd, dirPath.c_str (), watch_flags);
223
243
if (wd < 0 ) {
224
- throw std::runtime_error (" Failed to add watch on " + dirPath +
225
- " : " + std::string (strerror (errno)));
244
+ throw std::runtime_error (" Failed to add watch on " + dirPath + " : " +
245
+ std::string (strerror (errno)));
226
246
}
227
247
watch_descriptors[wd] = dirPath;
228
248
229
249
// Add watches for subdirectories
230
250
try {
231
- for (const auto & entry :
251
+ for (const auto & entry :
232
252
std::filesystem::recursive_directory_iterator (dirPath)) {
233
253
if (std::filesystem::is_directory (entry)) {
234
254
int subwd = inotify_add_watch (fd, entry.path ().c_str (), watch_flags);
235
255
if (subwd >= 0 ) {
236
256
watch_descriptors[subwd] = entry.path ().string ();
237
257
} else {
238
- CTL_ERR (" Failed to add watch for subdirectory " +
239
- entry.path ().string () + " : " +
258
+ CTL_ERR (" Failed to add watch for subdirectory " +
259
+ entry.path ().string () + " : " +
240
260
std::string (strerror (errno)));
241
261
}
242
262
}
@@ -274,21 +294,17 @@ class FileWatcherService {
274
294
return ;
275
295
}
276
296
277
- const int POLL_TIMEOUT_MS = 1000 ; // 1 second timeout
297
+ const int POLL_TIMEOUT_MS = 1000 ; // 1 second timeout
278
298
char buffer[4096 ];
279
- struct pollfd pfd = {
280
- .fd = fd,
281
- .events = POLLIN,
282
- .revents = 0
283
- };
284
-
299
+ struct pollfd pfd = {.fd = fd, .events = POLLIN, .revents = 0 };
300
+
285
301
while (running_) {
286
302
// Poll will sleep until either:
287
303
// 1. Events are available (POLLIN)
288
304
// 2. POLL_TIMEOUT_MS milliseconds have elapsed
289
305
// 3. An error occurs
290
306
int poll_result = poll (&pfd, 1 , POLL_TIMEOUT_MS);
291
-
307
+
292
308
if (poll_result < 0 ) {
293
309
if (errno == EINTR) {
294
310
// System call was interrupted, just retry
@@ -297,7 +313,7 @@ class FileWatcherService {
297
313
CTL_ERR (" Poll failed: " + std::string (strerror (errno)));
298
314
break ;
299
315
}
300
-
316
+
301
317
if (poll_result == 0 ) { // Timeout - no events
302
318
// No need to sleep - poll() already waited
303
319
continue ;
@@ -327,17 +343,18 @@ class FileWatcherService {
327
343
// Process events
328
344
size_t i = 0 ;
329
345
while (i < static_cast <size_t >(length)) {
330
- struct inotify_event * event =
346
+ struct inotify_event * event =
331
347
reinterpret_cast <struct inotify_event *>(&buffer[i]);
332
-
348
+
333
349
if (event->mask & (IN_DELETE | IN_DELETE_SELF)) {
334
350
try {
335
351
model_service_->ForceIndexingModelList ();
336
352
} catch (const std::exception& e) {
337
- CTL_ERR (" Error processing delete event: " + std::string (e.what ()));
353
+ CTL_ERR (" Error processing delete event: " +
354
+ std::string (e.what ()));
338
355
}
339
356
}
340
-
357
+
341
358
i += sizeof (struct inotify_event ) + event->len ;
342
359
}
343
360
}
0 commit comments