Skip to content

Commit

Permalink
Merge 5872949 into 8d12782
Browse files Browse the repository at this point in the history
  • Loading branch information
Pushkarm029 authored Jun 24, 2024
2 parents 8d12782 + 5872949 commit dd5700d
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 15 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
- name: Java tests
run: |
cd fs-storage
make test-linux
make test
windows:
name: Test on Windows
Expand All @@ -74,7 +74,7 @@ jobs:
- name: Java tests
run: |
cd fs-storage
make test-windows
make test
mac-intel:
name: Test on macOS Intel
Expand All @@ -98,4 +98,4 @@ jobs:
- name: Java tests
run: |
cd fs-storage
make test-mac
make test
4 changes: 2 additions & 2 deletions fs-storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ log = { version = "0.4.17", features = ["release_max_level_off"] }
serde_json = "1.0.82"
serde = { version = "1.0.138", features = ["derive"] }
jni = { version = "0.21.1", optional = true }
jnix = { version = "0.5.1", features = ["derive"] }
jnix = { version = "0.5.1", features = ["derive"], optional = true }

data-error = { path = "../data-error" }

Expand All @@ -27,4 +27,4 @@ tempdir = "0.3.7"

[features]
default = ["jni-bindings"]
jni-bindings = ["jni"]
jni-bindings = ["jni", "jnix"]
30 changes: 25 additions & 5 deletions fs-storage/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@ CARGO_CMD = cargo
JAR_FILE := junit.jar
URL := https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console-standalone/1.9.3/junit-platform-console-standalone-1.9.3.jar

# Detect OS
ifeq ($(OS),Windows_NT)
DETECTED_OS := Windows
else
DETECTED_OS := $(shell uname -s)
endif

.PHONY: test
test: build-rust download-test-lib
ifeq ($(DETECTED_OS),Windows)
@$(MAKE) test-windows
else ifeq ($(DETECTED_OS),Darwin)
@$(MAKE) test-mac
else ifeq ($(DETECTED_OS),Linux)
@$(MAKE) test-linux
else
@echo "Unsupported operating system: $(DETECTED_OS)"
@exit 1
endif

.PHONY: test-linux
test-linux: build-rust download-test-lib java-test-linux

Expand All @@ -13,11 +33,11 @@ test-windows: build-rust download-test-lib java-test-windows

.PHONY: build-rust
build-rust:
$(CARGO_CMD) build
@$(CARGO_CMD) build

.PHONY: download-test-lib
download-test-lib:
cd tests && \
@cd tests && \
if [ ! -f "$(JAR_FILE)" ]; then \
curl -o "$(JAR_FILE)" "$(URL)"; \
else \
Expand All @@ -26,7 +46,7 @@ download-test-lib:

.PHONY: java-test-linux
java-test-linux:
(cd ../target/debug && \
@(cd ../target/debug && \
export LD_LIBRARY_PATH=$$PWD && \
cd ../../fs-storage/tests && \
javac -d out FileStorage.java && \
Expand All @@ -35,7 +55,7 @@ java-test-linux:

.PHONY: java-test-mac
java-test-mac:
(cd ../target/debug && \
@(cd ../target/debug && \
export DYLD_LIBRARY_PATH=$$PWD && \
cd ../../fs-storage/tests && \
javac -d out FileStorage.java && \
Expand All @@ -44,7 +64,7 @@ java-test-mac:

.PHONY: java-test-windows
java-test-windows:
(cd ../target/debug && \
@(cd ../target/debug && \
export LIBRARY_PATH="$$PWD" && \
cd ../../fs-storage/tests && \
javac -d out FileStorage.java && \
Expand Down
8 changes: 5 additions & 3 deletions fs-storage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ cargo run --example cli read /tmp/z

## Java Wrapper
```java
cd tests
javac -h . FileStorage.java
javac FileStorage.java
LD_LIBRARY_PATH=<project-root-path>/target/debug && java FileStorage.java
LD_LIBRARY_PATH=../../target/debug && java FileStorage.java
```

## Steps to test Java Wrapper
```bash
cd tests && make test
```
make test
```

1 change: 1 addition & 0 deletions fs-storage/src/base_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use jnix::{FromJava, IntoJava};
#[cfg_attr(feature = "jni-bindings", derive(FromJava, IntoJava))]
#[jnix(class_name = "SyncStatus")]
/// Represents the synchronization status of the storage.
/// Any changes here should be reflected in the Java class `SyncStatus`.
pub enum SyncStatus {
/// No synchronization needed.
InSync,
Expand Down
35 changes: 35 additions & 0 deletions fs-storage/src/jni/btree_wrapper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::base_storage::BaseStorage;
use jni::sys::jlong;
use std::cell::RefCell;
use std::collections::btree_map::Iter;
use std::rc::Rc;

pub struct WrapperBTreeMap<'a, K, V> {
data: Rc<RefCell<Iter<'a, K, V>>>,
}

impl<'a, K, V> WrapperBTreeMap<'a, K, V>
where
K: Ord + Clone,
V: Clone,
{
pub fn new<S: BaseStorage<K, V>>(storage: &'a S) -> Self {
WrapperBTreeMap {
data: Rc::new(RefCell::new(storage.as_ref().iter())),
}
}

pub fn has_next(&self) -> bool {
let borrow = self.data.borrow_mut();
borrow.clone().peekable().peek().is_some()
}

pub fn native_next(&mut self) -> Option<(K, V)> {
let mut borrow = self.data.borrow_mut();
borrow.next().map(|(k, v)| (k.clone(), v.clone()))
}

pub fn from_jlong(value: jlong) -> &'a mut Self {
unsafe { &mut *(value as *mut WrapperBTreeMap<K, V>) }
}
}
91 changes: 90 additions & 1 deletion fs-storage/src/jni/file_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ use jni::objects::{JClass, JObject, JString, JValue};
// This is just a pointer. We'll be returning it from our function. We
// can't return one of the objects with lifetime information because the
// lifetime checker won't let us.
use jni::sys::{jlong, jobject};
use jni::sys::{jboolean, jlong, jobject, jstring};
use jnix::{IntoJava, JnixEnv};

use crate::base_storage::BaseStorage;

use super::btree_wrapper::WrapperBTreeMap;
use crate::file_storage::FileStorage;

impl FileStorage<String, String> {
Expand Down Expand Up @@ -170,6 +171,30 @@ pub extern "system" fn Java_FileStorage_readFS(
linked_hash_map.as_raw()
}

#[no_mangle]
pub extern "system" fn Java_FileStorage_getValue(
mut env: JNIEnv<'_>,
_class: JClass,
id: JString<'_>,
file_storage_ptr: jlong,
) -> jstring {
let id: String = env.get_string(&id).unwrap().into();
let binding = FileStorage::from_jlong(file_storage_ptr);
let value = binding.as_ref().get(&id);

match value {
Some(value) => env.new_string(value).unwrap().into_raw(),
None => {
env.throw_new(
"java/lang/RuntimeException",
&"no value present for this key".to_string(),
)
.unwrap();
env.new_string("").unwrap().into_raw()
}
}
}

#[no_mangle]
pub extern "system" fn Java_FileStorage_writeFS(
mut env: JNIEnv<'_>,
Expand Down Expand Up @@ -215,3 +240,67 @@ pub extern "system" fn Java_FileStorage_merge(
.unwrap();
});
}

#[no_mangle]
pub extern "system" fn Java_FileStorage_createIterator<'local>(
_env: JNIEnv<'local>,
_class: JClass<'local>,
file_storage_ptr: jlong,
) -> jlong {
let wrapper =
WrapperBTreeMap::new(FileStorage::from_jlong(file_storage_ptr));
Box::into_raw(Box::new(wrapper)) as jlong
}

#[no_mangle]
pub extern "system" fn Java_FileStorageIterator_hasNext<'local>(
_env: JNIEnv<'local>,
_class: JClass<'local>,
iterator_ptr: jlong,
) -> jboolean {
let iterator: &mut WrapperBTreeMap<String, String> =
WrapperBTreeMap::from_jlong(iterator_ptr);
iterator.has_next() as jboolean
}

#[no_mangle]
pub extern "system" fn Java_FileStorageIterator_next<'local>(
mut env: JNIEnv<'local>,
_class: JClass<'local>,
iterator_ptr: jlong,
) -> jobject {
if let Some((key, value)) =
WrapperBTreeMap::<String, String>::from_jlong(iterator_ptr)
.native_next()
{
let entry_class = env
.find_class("java/util/AbstractMap$SimpleEntry")
.unwrap();
let entry = env
.new_object(
entry_class,
"(Ljava/lang/Object;Ljava/lang/Object;)V",
&[
(&JObject::from(env.new_string(key).unwrap())).into(),
(&JObject::from(env.new_string(value).unwrap())).into(),
],
)
.unwrap();

return entry.into_raw();
}
JObject::null().into_raw()
}

#[no_mangle]
pub extern "system" fn Java_FileStorageIterator_destroyIterator<'local>(
_env: JNIEnv<'local>,
_class: JClass<'local>,
iterator_ptr: jlong,
) {
unsafe {
drop(Box::from_raw(
iterator_ptr as *mut WrapperBTreeMap<String, String>,
));
}
}
1 change: 1 addition & 0 deletions fs-storage/src/jni/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod btree_wrapper;
pub mod file_storage;
3 changes: 2 additions & 1 deletion fs-storage/tests/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.jar
*.jar
*.h
13 changes: 13 additions & 0 deletions fs-storage/tests/FileStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class FileStorage {

private static native void set(String id, String value, long file_storage_ptr);

private static native String getValue(String id, long file_storage_ptr);

private static native void remove(String id, long file_storage_ptr);

private static native void sync(long file_storage_ptr);
Expand All @@ -23,6 +25,8 @@ public class FileStorage {

private static native void merge(long file_storage_ptr, long other_file_storage_ptr);

private static native long createIterator(long file_storage_ptr);

public FileStorage(String label, String path) {
this.fileStoragePtr = create(label, path);
}
Expand All @@ -31,6 +35,10 @@ public void set(String id, String value) {
set(id, value, this.fileStoragePtr);
}

public String get(String id) {
return getValue(id, this.fileStoragePtr);
}

public void remove(String id) {
remove(id, this.fileStoragePtr);
}
Expand Down Expand Up @@ -58,4 +66,9 @@ public void erase() {
public void merge(FileStorage other) {
merge(this.fileStoragePtr, other.fileStoragePtr);
}

public FileStorageIterator iterator() {
long iteratorPtr = createIterator(this.fileStoragePtr);
return new FileStorageIterator(iteratorPtr);
}
}
39 changes: 39 additions & 0 deletions fs-storage/tests/FileStorageIterator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;

public class FileStorageIterator implements Iterator<Map.Entry<String, String>>, AutoCloseable {
private long fileStorageIteratorPtr;

private static native boolean hasNext(long file_storage_iterator_ptr);

private static native Object next(long file_storage_iterator_ptr);

private static native void destroyIterator(long file_storage_iterator_ptr);

FileStorageIterator(long fileStorageIteratorPtr) {
this.fileStorageIteratorPtr = fileStorageIteratorPtr;
}

@Override
public boolean hasNext() {
return hasNext(this.fileStorageIteratorPtr);
}

@SuppressWarnings("unchecked")
@Override
public Map.Entry<String, String> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return (Map.Entry<String, String>) next(this.fileStorageIteratorPtr);
}

@Override
public void close() {
if (this.fileStorageIteratorPtr != 0) {
destroyIterator(this.fileStorageIteratorPtr);
this.fileStorageIteratorPtr = 0;
}
}
}
Loading

0 comments on commit dd5700d

Please sign in to comment.