aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java
diff options
context:
space:
mode:
authorGravatar Damien Martin-Guillerez <dmarting@google.com>2016-06-02 12:18:11 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2016-06-02 15:41:56 +0000
commit990fa00f7e1a7a8d5bcda78681a9cd7df5d5c023 (patch)
tree581b00b0f5432f8fdf35e02af6039d2774439b17 /src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java
parent0b5d61fe0722b71a63b9756f8687d1ce2e380072 (diff)
Introduce FsEventsDiffAwareness for OS X.
Use FsEvents API (https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref) to watch the file system. This change also refactor the LocalDiffAwareness to extract the WatchService specific part. It now select the FsEventsDiffAwareness on OSX and the WatchServiceDiffAwareness on Linux. RELNOTES[NEW]: On OSX, --watchfs now uses FsEvents to be notified of changes from the filesystem (previously, this flag had no effect on OS X). Fixes #1074. -- Change-Id: I927951468e4543a399e0e0ad0f1dd23d38ce15a0 Reviewed-on: https://bazel-review.googlesource.com/3420 MOS_MIGRATED_REVID=123854017
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java b/src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java
new file mode 100644
index 0000000000..cf0fc621b5
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java
@@ -0,0 +1,108 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.skyframe;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.UnixJniLoader;
+
+import java.io.File;
+import java.nio.file.Path;
+
+/**
+ * A {@link DiffAwareness} that use fsevents to watch the filesystem to use in lieu of
+ * {@link LocalDiffAwareness}.
+ *
+ * <p>
+ * On OS X, the local diff awareness cannot work because WatchService is dummy and do polling, which
+ * is slow (https://bugs.openjdk.java.net/browse/JDK-7133447).
+ */
+public final class MacOSXFsEventsDiffAwareness extends LocalDiffAwareness {
+
+ private boolean closed;
+
+ // Keep a pointer to a native structure in the JNI code (the FsEvents callback needs that
+ // structure).
+ private long nativePointer;
+
+ /**
+ * Watch changes on the file system under <code>watchRoot</code> with a granularity of
+ * <code>delay</code> seconds.
+ */
+ MacOSXFsEventsDiffAwareness(String watchRoot, double latency) {
+ super(watchRoot);
+ create(new String[] {watchRootPath.toAbsolutePath().toString()}, latency);
+
+ // Start a thread that just contains the OS X run loop.
+ new Thread(
+ new Runnable() {
+ @Override
+ public void run() {
+ MacOSXFsEventsDiffAwareness.this.run();
+ }
+ })
+ .start();
+ }
+
+ /**
+ * Watch changes on the file system under <code>watchRoot</code> with a granularity of 5ms.
+ */
+ MacOSXFsEventsDiffAwareness(String watchRoot) {
+ this(watchRoot, 0.005);
+ }
+
+ /**
+ * Helper function to start the watch of <code>paths</code>, called by the constructor.
+ */
+ private native void create(String[] paths, double latency);
+
+ /**
+ * Run the main loop
+ */
+ private native void run();
+
+ /**
+ * Close this watch service, this service should not be used any longer after closing.
+ */
+ public synchronized void close() {
+ Preconditions.checkState(!closed);
+ closed = true;
+ doClose();
+ }
+
+ /**
+ * JNI code stopping the main loop and shutting down listening to FSEvents.
+ */
+ private synchronized native void doClose();
+
+ /**
+ * JNI code returning the list of absolute path modified since last call.
+ */
+ private native String[] poll();
+
+ static {
+ UnixJniLoader.loadJni();
+ }
+
+ @Override
+ public synchronized View getCurrentView() throws BrokenDiffAwarenessException {
+ Preconditions.checkState(!closed);
+ ImmutableSet.Builder<Path> paths = ImmutableSet.builder();
+ for (String path : poll()) {
+ paths.add(new File(path).toPath());
+ }
+ return newView(paths.build());
+ }
+}