守望者通知后立即读取的文件为空

时间:2016-09-28 01:45:48

标签: watchman

我正在通过JVM程序中的socket / bser接口集成watchman。

我看到奇怪的时间:

  1. 构建系统(小文本文件)
  2. 写入文件
  3. 我在bser界面上收到了一个守望者通知
  4. 线程A监听bser订阅通知会将更新置于单独线程的队列中
  5. 线程B读取队列,读取更改的文件,然后将文件的数据放在线路上
  6. 然而,不知何故,线程B正在读取一个空文件。

    其中,我认为在某些时候有效是空的,例如IO /系统调用可能是:

    1. 清除文件内容
    2. 写下块1
    3. 写下块2
    4. 关闭文件
    5. 我假设我的线程B正在步骤1和2之间读取文件。或者可能是1和4,如果4是刷新结果的话。

      我的困惑有两个:

      1)我认为守望者默认的20ms等待会解释这样的事情,我只会在我的线程A上看到更新,更不用说我的线程B在第4步之后执行读取,并且数据已完成被写入文件。

      2)即使守望者确实告诉我“太早”关于第一次系统调用(比如说第1步),并且我在空文件中读取结果,应该有另一个系统调用/守望者通知“btw,the文件现在有一些内容“。

      FWIW /奇怪的是,我在使用Java WatchService API时看到了同样的行为,我会在其中获得inotify事件,但是“太快”读取文件,因此得到空或部分结果,然后当剩下的数据可用时,不要跟进inotify事件。

      我认为这是WatchService的侥幸/细微差别,所以我当时通过检查文件模式时间来解决它,并等待确保模式时间> 2秒,然后才假定文件是“做完“写作。

      (注意,这也处理了大约100mb +文件正在写入,其中构建过程可能每100ms +写一块数据,但是使用WatchService我看到100次inotify通知,基本上是一次连续写入。)

      当我将WatchService代码移植到watchman时,我放弃了这个“确定已安装”的黑客,因为我假设守望者的20ms结算期(这比我使用的2s低,但是它是默认的)+它的一般稳健性比较对某种程度上的beta WatchService意味着它不会有问题。

      但是在使用守望者移植代码的〜一天内,我看到空文件读取,就像我使用WatchService一样。

      关于我缺少什么的任何想法?

      我可以添加一下EnsureSettled hack,但此时我很好奇发生了什么。

1 个答案:

答案 0 :(得分:0)

文档对此不太清楚,抱歉!

订阅通知的调度受到解决超时的限制,但由于文件更新是非原子的,因此默认的20ms可能会在文件内容对您可见之前启动;在内幕下,内核会针对您正在进行的各种突变生成一系列通知,因此如果截断在您写入(或可能刷新)数据之前需要20ms,您可能会在中间收到通知”

这个东西也依赖于操作系统。以下是最近发现并解决的问题的示例:https://github.com/facebook/watchman/commit/bac383c751b248ae742a2a20df3e8272238c0ae2 它听起来并不像你所经历的那样,它只是为这次讨论增添了一些色彩。

如果您已经有代码来管理客户端的结算,那么您可能更容易将其添加回来;我们在watchman-make中执行此操作。 您可能还希望尝试在您正在观看的目录树的根目录中的.watchmanconfig文件中设置https://facebook.github.io/watchman/docs/config.html#settle,并将其留给守望者服务器。如果/当您更改此设置时,您将需要删除并重新启动手表。

您选择哪种方式取决于您希望如何根据要维护的代码量来轻松配置,以及(如果未正确配置.watchmanconfig)来自用户群的大量支持问题

请注意,您可以使用https://facebook.github.io/watchman/docs/cmd/log-level.html中的命令调用来查看内核通知的实时调试日志;这可能有助于您准确了解哪些通知即将发生以及何时发生。

好奇,你是否正在使用https://github.com/facebook/watchman/tree/master/java与守望者服务器交谈?