diff options
author | 2016-06-02 12:18:11 +0000 | |
---|---|---|
committer | 2016-06-02 15:41:56 +0000 | |
commit | 990fa00f7e1a7a8d5bcda78681a9cd7df5d5c023 (patch) | |
tree | 581b00b0f5432f8fdf35e02af6039d2774439b17 /src/main/java/com/google/devtools/build/lib/skyframe/MacOSXFsEventsDiffAwareness.java | |
parent | 0b5d61fe0722b71a63b9756f8687d1ce2e380072 (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.java | 108 |
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()); + } +} |