JVM プログラムの socket/bser インターフェイスを介してウォッチマンを統合しています。
私は奇妙なタイミングを見ています:
- ファイルはビルド システムによって書き込まれます (小さなテキスト ファイル)
- bser インターフェイスでウォッチマン通知を受け取ります
- bser サブスクリプション通知をリッスンするスレッド A は、更新を別のスレッドのキューに入れます。
- スレッド B はキューを読み取り、変更されたファイルを読み取り、ファイルのデータをネットワークに送信します。
ただし、どういうわけか、スレッド B は空のファイルを読み込んでいます。
これは、ある時点で有効に空であると想定しています。たとえば、IO/syscalls は次のようになります。
- ファイルの内容をクリアする
- チャンク 1 の書き込み
- チャンク 2 の書き込み
- ファイルを閉じる
そして、スレッド B がステップ 1 と 2 の間でファイルを読み取っていると思います。または、4 が結果がフラッシュされたときの場合は、1 と 4 かもしれません。
私の混乱は2つあります。
1)ウォッチマンのデフォルトの20ミリ秒の待機はこのようなことを説明すると思いました.スレッドBが読み取りを行ったときはもちろん、スレッドAの更新のみが表示され、ステップ4の後にデータの書き込みが完了しました.ファイル。
2) ウォッチマンが最初の syscall (ステップ 1 など) について「早すぎる」と言って、それが空のファイルである間に結果を読んだとしても、別の syscall/watchman 通知があるはずです。現在のコンテンツ」。
FWIW/奇妙なことに、Java WatchService API を使用しているときに、これとまったく同じ動作が見られました。ここでは、inotify イベントを取得しましたが、ファイルを「すぐに」読み取ったため、結果が空または部分的になり、フォローアップが行われませんでした。残りのデータが利用可能になったときの inotify イベント。
これは WatchService のまぐれ/ニュアンスであると想定していたので、ファイルを読み取る前に変更時間を確認し、変更時間が 2 秒を超えていることを確認してからファイルが「完了」したと想定することで、その時点で解決しました。 .
(これは、ビルド プロセスが 100 ミリ秒以上ごとにデータのチャンクを書き込む可能性がある場合に、書き込まれる ~100 MB 以上のファイルも処理することに注意してください。ただし、WatchService を使用すると、本質的に単一の連続書き込みであったものに対して数百の inotify 通知が表示されました。)
WatchService コードを watchman に移植したとき、この「ensureSettled」ハックを削除しました。なぜなら、watchman の 20 ミリ秒のセトリング期間 (私が使用していた 2 秒よりもはるかに短いですが、これがデフォルトです) を想定していたからです。 beta の WatchService は、問題にならないことを意味します。
しかし、ウォッチマンに移植されたコードを使用して 1 日以内に、WatchService の場合と同様に、空のファイルの読み取りが見られます。
私が欠けているものについてのアイデアはありますか?
ensureSettled ハックを元に戻すことはできますが、この時点で何が起こっているのか知りたいです。