bric3 / drain-java

This a pet project to explore log pattern extraction using DRAIN

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Replace JVM file watcher by alternatives that are not affected by filesystems boundaries

bric3 opened this issue · comments

The watchservice of the JVM suffers from a few drawbacks regarding its integration with the OS. In Linux in particular events of bind mounts are not received.

Let's investigate alternative, in particular the gradle native integration : https://github.com/gradle/native-platform

+    implementation("net.rubygrapefruit:file-events:0.22")
+    implementation("net.rubygrapefruit:native-platform:0.22")

Currently file watching capabilities just appeared in a 0.22 milestone, unfortunately this is not completely released (platform specific native libraries are not published on bintray (for the published milestone)).

To follow https://github.com/gradle/native-platform/releases

However native-platform:0.21 is available on it's possible to play with some api like the terminal or files, e.g. :

try {
    Terminals terminals = Native.get(Terminals.class);
    var isTerminal = terminals.withAnsiOutput().isTerminal(Output.Stdout);

    if (isTerminal) {
        var terminal = terminals.withAnsiOutput().getTerminal(Output.Stdout);
        terminal.write("Hello");
        SECONDS.sleep(5);
        terminal.cursorStartOfLine()
                .clearToEndOfLine()
                .bold().write("Bold hello")
                .reset();
    }
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

Gradle's native-platform may not be a good fit after all.

Gradle's native-platform uses macOs's fsevents to handle file events, which does not pickup all file changes.
While looking at macOs tail source code I found that it is based on BSD's kqueue and this mechanisms report correctly single file changes.

This finding has been confirmed with the tool fswatch (it implements various way to watch files ; on macOS: fsevents, kqueue, or polling).

Reference issues :

Another idea would be to use JDK16's foreign linker incubator API to leverage kqueue (if JDK 16 is available).
Or write a JNI / C code.