Skip to content

Feat/use rust and jni on mac #60

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ jobs:
strategy:
matrix:
os:
- image: ubuntu-latest
- image: macos-latest
mac-backend: jdk
#- image: ubuntu-latest
#- image: macos-latest
#mac-backend: jdk
- image: macos-latest
mac-backend: fsevents
- image: windows-latest
#- image: windows-latest
jdk: [11, 17, 21]

fail-fast: false
Expand All @@ -32,9 +32,12 @@ jobs:
java-version: ${{ matrix.jdk }}
distribution: 'temurin'
cache: 'maven'
#- uses: actions-rust-lang/setup-rust-toolchain@v1
- run: ./update-rust-jni-libs.sh
if: ${{ matrix.os.image == 'macos-latest' }}

- name: test
run: mvn -B clean test "-Dwatch.mac.backend=${{ matrix.os.mac-backend }}"
run: mvn -B clean test "-Dwatch.mac.backend=${{ matrix.os.mac-backend }}" -Dtest=Basic
env:
DELAY_FACTOR: 3

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ replay_pid*

# release plugin state files
/pom.xml.releaseBackup
/release.properties
/release.properties
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@
</properties>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>src/main/rust/**/*.*</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin> <!-- configure java compiler -->
<groupId>org.apache.maven.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package engineering.swat.watch.impl.mac.jni;

import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.util.List;

/**
* Start a recursive watch on a folder
*/
public class FileSystemEvents implements Closeable {
static {
NativeLibrary.load();
}

private native long start(String path, Runnable signal);
private native void stop(long watchId);
private native boolean anyEvents(long watchId);
private native List<WatchEvent<?>> pollEvents(long watchId);


private volatile boolean closed = false;
private final long activeWatch;

public FileSystemEvents(Path path, Runnable notifyNewEvents) {
activeWatch = start(path.toString(), notifyNewEvents);
}

public boolean anyEvents() throws IOException {
if (closed) {
throw new IOException("Watch is already closed");

Check warning on line 32 in src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java#L32

Added line #L32 was not covered by tests
}
return anyEvents(activeWatch);

Check warning on line 34 in src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java#L34

Added line #L34 was not covered by tests
}

public List<WatchEvent<?>> pollEvents() throws IOException {
if (closed) {
throw new IOException("Watch is already closed");

Check warning on line 39 in src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java#L39

Added line #L39 was not covered by tests
}
return pollEvents(activeWatch);

Check warning on line 41 in src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java#L41

Added line #L41 was not covered by tests
}

@Override
public void close() {
if (closed) {
return;

Check warning on line 47 in src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/FileSystemEvents.java#L47

Added line #L47 was not covered by tests
}
closed = true;
stop(activeWatch);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package engineering.swat.watch.impl.mac.jni;

import static java.nio.file.attribute.PosixFilePermission.*;

import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;

class NativeLibrary {

Check warning on line 12 in src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java#L12

Added line #L12 was not covered by tests
private static boolean isMac() {
var os = System.getProperty("os.name");
return os != null && (os.toLowerCase().contains("mac") || os.toLowerCase().contains("darwin"));

}

private static boolean isAarch64() {
var arch = System.getProperty("os.arch");
return arch != null && arch.toLowerCase().equals("aarch64");
}

private static volatile boolean loaded = false;
public static void load() {
if (loaded) {
return;

Check warning on line 27 in src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java#L27

Added line #L27 was not covered by tests
}
try {
if (!isMac()) {
throw new IllegalStateException("We should not be loading FileSystemEvents api on non mac machines");

Check warning on line 31 in src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java#L31

Added line #L31 was not covered by tests
}
String path = "/engineering/swat/watch/jni/";
if (isAarch64()) {
path += "macos-aarch64/";
}
else {
path += "macos-x64/";

Check warning on line 38 in src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java#L38

Added line #L38 was not covered by tests
}
path += "librust_fsevents_jni.dylib";

loadLibrary(path);
} finally {
loaded = true;
}
}

private static FileAttribute<Set<PosixFilePermission>> PRIVATE_FILE = PosixFilePermissions.asFileAttribute(Set.of(OWNER_READ, OWNER_WRITE , OWNER_EXECUTE));

private static void loadLibrary(String path) {
try {
var localFile = FileSystemEvents.class.getResource(path);
if (localFile.getProtocol().equals("file")) {
System.load(localFile.getPath());
return;
}
// in most cases the file is inside of a jar
// so we have to copy it out and load that file instead
var localCopy = Files.createTempFile("watch", ".dylib"/* , PRIVATE_FILE*/);
localCopy.toFile().deleteOnExit();
try (var libStream = FileSystemEvents.class.getResourceAsStream(path)) {
try (var writer = Files.newOutputStream(localCopy, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
libStream.transferTo(writer);

Check warning on line 63 in src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java#L59-L63

Added lines #L59 - L63 were not covered by tests
}
System.load(localCopy.toString());

Check warning on line 65 in src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java#L65

Added line #L65 was not covered by tests
}
}
catch (Throwable e) {
throw new IllegalStateException("We could not load: " + path, e);
}
}

Check warning on line 71 in src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/engineering/swat/watch/impl/mac/jni/NativeLibrary.java#L68-L71

Added lines #L68 - L71 were not covered by tests

}
1 change: 1 addition & 0 deletions src/main/resources/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.dylib
7 changes: 7 additions & 0 deletions src/main/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/target
/debug
**/*.rs.bk
*.pdb
*.log
*.d
*.dylib
Loading
Loading