Наше приложение C ++ использует FSEventStream для мониторинга файловой системы с гранулярностью на уровне файлов (создание потока с флагом kFSEventStreamCreateFlagFileEvents) с одним прослушивателем на каждый том. Однако в API Apple FSEvent, похоже, есть некоторые ошибки / ошибки, связанные с тем, как они сжимают (удаляют дубликаты) события из потока перед его отправкой нам:
Незначительно, но раздражает: при запуске потока с использованием предыдущего идентификатора события в качестве отправной точки (для регистрации изменений в файловой системе со времени последнего мониторинга) порядок предоставляемых событий отличается от того, который мы получаем, если мы слушаем события по мере их возникновения, в том смысле, что они поступают не в порядке eventId, а сортируются в алфавитном порядке по имени файла. Мы решили эту проблему, накапливая все исторические события в списке, отсортированном по идентификатору, перед обработкой набора.
Major: Если события переименования происходят достаточно быстро, фактические события, передаваемые нам в функции обратного вызова, не отражают того, что фактически произошло в файловой системе. Рассмотрим наш тестовый пример, в котором мы меняем имена каталогов:
а. изменить файл
б. переименуйте его родительский каталог в _temp
с. переименовать другой каталог в имя предыдущего родителя
д. переименуйте _temp в dir на шаге c.
Если мы поместим задержку в 50 мс между каждым из этих шагов (по существу, любая задержка, которая гарантирует, что данное событие не будет в том же обратном вызове, что и другое событие), мы получим правильную последовательность событий (с переименованиями, отображаемыми в виде пар событий):
fsEventsCallback: Received FSEvents callback with 1 events:
fsEventsCallback: ID=34303406 PATH= /Users/stebro/swaptest/subdir1/file_1.txt FLAGS=kFSEventStreamEventFlagItemInodeMetaMod, kFSEventStreamEventFlagItemIsFile, kFSEventStreamEventFlagItemModified
fsEventsCallback: Received FSEvents callback with 2 events:
fsEventsCallback: ID=34303436 PATH= /Users/stebro/swaptest/subdir1 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34303437 PATH= /Users/stebro/swaptest/subdir1_temp FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: Received FSEvents callback with 2 events:
fsEventsCallback: ID=34303620 PATH= /Users/stebro/swaptest/subdir2 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34303621 PATH= /Users/stebro/swaptest/subdir1 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: Received FSEvents callback with 2 events:
fsEventsCallback: ID=34303741 PATH= /Users/stebro/swaptest/subdir1_temp FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34303742 PATH= /Users/stebro/swaptest/subdir2 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
Однако без задержки (или настолько малой задержки, что множественные события переименования будут поступать при одном и том же вызове обратного вызова), создается впечатление, что ОС использует «услугу» удаления того, что она считает избыточными событиями, что приводит к этому беспорядку. :
fsEventsCallback: Received FSEvents callback with 4 events:
fsEventsCallback: ID=34251572 PATH= /Users/stebro/swaptest/subdir1/file_1.txt FLAGS=kFSEventStreamEventFlagItemInodeMetaMod, kFSEventStreamEventFlagItemIsFile, kFSEventStreamEventFlagItemModified
fsEventsCallback: ID=34251580 PATH= /Users/stebro/swaptest/subdir1 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34251583 PATH= /Users/stebro/swaptest/subdir1_temp FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34251584 PATH= /Users/stebro/swaptest/subdir2 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
Есть ли что-то, что мы можем сделать, чтобы подавить это сжатие? Мы создаем поток с помощью этого вызова:
FSEventStreamCreateRelativeToDevice(kCFAllocatorDefault,
&fsEventsCallback,
&context,
device,
reinterpret_cast<CFArrayRef>(_monitoredPaths),
lastEventId,
0, // Latency - problem exists with values of 1, 0.1 and 3 as well
kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer);
Задача ещё не решена.
Других решений пока нет …