如何在fseventstream中解决破裂的事件压缩

How to solve broken event compression in FSEventStream

本文关键字:事件 压缩 解决 fseventstream      更新时间:2023-10-16

我们的C 应用程序使用fseventstream用文件级粒度监视文件系统(使用kfseventstreamcreateflagfileevents flag创建流(,每个卷都有一个侦听器。但是,Apple FSEVENT API中似乎存在一些错误/错误,这是由于它们如何压缩(删除重复(事件在将它们发送给我们之前:

  1. 次要,但很烦人:使用先前的事件ID作为起点(为了捕获自我们上次监视以来的文件系统更改(时,所提供的事件的顺序为与我们听到事件发生的情况不同,我们会得到的不同,因为事件不会以最终的顺序到达,而是通过文件名对字母进行排序。我们已经在处理集合之前将所有历史事件累积在ID列表中的所有历史事件。

  2. 专业:如果重命名事件发生得足够快,则在回调功能中给我们的实际事件并不代表文件系统上实际发生的事情。考虑我们交换DIR名称的测试案例:

    a。更改文件

    b。将其父级命名为_temp

    c。重命名为前任父母的名称

    d。将_temp重命名为步骤c。

如果我们将每个步骤之间的延迟延迟50 ms(本质上,保证给定事件不会与另一个事件相同的延迟(,我们会得到正确的事件序列(重命名显示显示作为事件成对(:

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);

可以使用kFSEventStreamCreateFlagUseExtendedData(自OS X 10.13以来可用(的过度攻击事件折叠的解决方案。使用该标志创建的流将包括事件文件的 inode 。这样,您可以检测报告的事件批处理中发生的"重命名链"。

P.S。我在文件显示器中尝试了您的方案;事件序列正确。