diff --git a/fs-storage/src/jni/btree_wrapper.rs b/fs-storage/src/jni/btree_wrapper.rs deleted file mode 100644 index 678e19a..0000000 --- a/fs-storage/src/jni/btree_wrapper.rs +++ /dev/null @@ -1,35 +0,0 @@ -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>>, -} - -impl<'a, K, V> WrapperBTreeMap<'a, K, V> -where - K: Ord + Clone, - V: Clone, -{ - pub fn new>(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) } - } -} diff --git a/fs-storage/src/jni/file_storage.rs b/fs-storage/src/jni/file_storage.rs index 0f91adf..0e76a17 100644 --- a/fs-storage/src/jni/file_storage.rs +++ b/fs-storage/src/jni/file_storage.rs @@ -19,11 +19,11 @@ use jnix::{IntoJava, JnixEnv}; use crate::base_storage::BaseStorage; -use super::btree_wrapper::WrapperBTreeMap; +// use super::btree_wrapper::WrapperBTreeMap; use crate::file_storage::FileStorage; impl FileStorage { - fn from_jlong<'a>(value: jlong) -> &'a mut Self { + pub fn from_jlong<'a>(value: jlong) -> &'a mut Self { unsafe { &mut *(value as *mut FileStorage) } } } @@ -241,66 +241,66 @@ pub extern "system" fn Java_FileStorage_merge( }); } -#[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_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 = - WrapperBTreeMap::from_jlong(iterator_ptr); - iterator.has_next() as jboolean -} +// #[no_mangle] +// pub extern "system" fn Java_FileStorageIterator_hasNext<'local>( +// _env: JNIEnv<'local>, +// _class: JClass<'local>, +// iterator_ptr: jlong, +// ) -> jboolean { +// let iterator: &mut WrapperBTreeMap = +// 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::::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(); +// #[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::::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() -} +// 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, - )); - } -} +// #[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, +// )); +// } +// } diff --git a/fs-storage/src/jni/mod.rs b/fs-storage/src/jni/mod.rs index e340b9d..1cbe9d3 100644 --- a/fs-storage/src/jni/mod.rs +++ b/fs-storage/src/jni/mod.rs @@ -1,2 +1,2 @@ -pub mod btree_wrapper; +pub mod wrapper_btreemap; pub mod file_storage; diff --git a/fs-storage/src/jni/wrapper_btreemap.rs b/fs-storage/src/jni/wrapper_btreemap.rs new file mode 100644 index 0000000..23fdbb7 --- /dev/null +++ b/fs-storage/src/jni/wrapper_btreemap.rs @@ -0,0 +1,86 @@ +use crate::wrapper_btreemap::WrapperBTreeMap; +use crate::file_storage::FileStorage; +// This is the interface to the JVM that we'll call the majority of our +// methods on. +use jni::JNIEnv; + +// These objects are what you should use as arguments to your native +// function. They carry extra lifetime information to prevent them escaping +// this context and getting used after being GC'd. +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::{jboolean, jlong, jobject, jstring}; +use jnix::{IntoJava, JnixEnv}; + +impl WrapperBTreeMap { + pub fn from_jlong(value: jlong) -> &'static mut Self { + unsafe { &mut *(value as *mut WrapperBTreeMap) } + } +} + +// JNI bindings + +// #[no_mangle] +// pub extern "system" fn Java_FileStorage_create<'local>( +// mut env: JNIEnv<'local>, +// _class: JClass, +// label: JString<'local>, +// path: JString<'local>, +// ) -> jlong { +// let label: String = env +// .get_string(&label) +// .expect("Couldn't get label!") +// .into(); +// let path: String = env +// .get_string(&path) +// .expect("Couldn't get path!") +// .into(); + +// let file_storage: FileStorage = +// FileStorage::new(label, Path::new(&path)).unwrap_or_else(|err| { +// env.throw_new("java/lang/RuntimeException", &err.to_string()) +// .expect("Failed to throw RuntimeException"); +// FileStorage::new("".to_string(), Path::new("")).unwrap() +// }); +// Box::into_raw(Box::new(file_storage)) as jlong +// } + +#[no_mangle] +pub extern "system" fn Java_WrapperBTreeMap_create<'local>( + mut env: JNIEnv<'local>, + _class: JClass, + storage_ptr: jlong, +) -> jlong { + // currently, only for file_storage + let filestorage = FileStorage::from_jlong(storage_ptr); + let wrapper = WrapperBTreeMap::new(filestorage); + Box::into_raw(Box::new(wrapper)) as jlong +} + +#[no_mangle] +pub extern "system" fn Java_WrapperBTreeMap_get<'local>( + mut env: JNIEnv<'local>, + _class: JClass, + id: JString<'local>, + wrapper_ptr: jlong, +) -> jstring { + let id: String = env.get_string(&id).expect("msg").into(); + let wrapper = WrapperBTreeMap::from_jlong(wrapper_ptr); + let data: String = wrapper.get_data(id); + env.new_string(data).unwrap().into_raw() +} + +// 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() +// } +// } diff --git a/fs-storage/src/lib.rs b/fs-storage/src/lib.rs index adaeafe..d637a87 100644 --- a/fs-storage/src/lib.rs +++ b/fs-storage/src/lib.rs @@ -1,5 +1,6 @@ pub mod base_storage; pub mod file_storage; +pub mod wrapper_btreemap; #[cfg(feature = "jni-bindings")] pub mod jni; pub mod monoid; diff --git a/fs-storage/src/wrapper_btreemap.rs b/fs-storage/src/wrapper_btreemap.rs new file mode 100644 index 0000000..2b041c8 --- /dev/null +++ b/fs-storage/src/wrapper_btreemap.rs @@ -0,0 +1,79 @@ +use crate::base_storage::BaseStorage; +use std::cell::RefCell; +use std::collections::btree_map::{IntoIter, Iter}; +use std::collections::BTreeMap; +use std::rc::Rc; + +pub struct WrapperBTreeMap { + data: Rc>>, + index: usize, +} + +impl WrapperBTreeMap +where + K: Ord + Clone, + V: Clone, +{ + pub fn new>(storage: &S) -> Self { + WrapperBTreeMap { + data: Rc::new(RefCell::new(storage.as_ref().clone())), + index: 0, + } + } + + pub fn get_data(&self, id: K) -> V { + let borrow = self.data.borrow(); + borrow.get(&id).unwrap().clone() + } + + // pub fn has_next(&self) -> bool { + // let borrow = self.data.borrow_mut(); + // let iter = borrow.iter(); + // iter.clone().nth(self.index).is_some() + // } + + // pub fn native_next(&mut self) -> Option<(K, V)> { + // let borrow = self.data.borrow_mut(); + // let mut iter = borrow.iter(); + // iter.nth(self.index).map(|(k, v)| { + // self.index += 1; + // (k.clone(), v.clone()) + // }) + // } +} + +pub struct WrapperBTreeMapIterator<'a, K, V> { + iter: Iter<'a, K, V>, +} + +impl<'a, K, V> WrapperBTreeMapIterator<'a, K, V> +where + K: Ord + Clone, + V: Clone, +{ + pub fn new(storage: WrapperBTreeMap) -> Self { + let binding = storage.data.clone(); + let borrow = binding.borrow(); + // let iter = as Clone>::clone(&borrow) + // .iter(); + WrapperBTreeMapIterator { + iter: borrow.iter(), + } + } + + pub fn has_next(&mut self) -> bool { + // let borrow = self.iter.clone(); + // self.iter.peekable().peek().is_some() + } + + pub fn native_next(&mut self) -> Option<(K, V)> { + self.iter + .next() + .map(|(k, v)| (k.clone(), v.clone())) + } + + // pub fn native_next(&self) -> Option<(K, V)> { + // let borrow = self.iter.borrow_mut(); + // borrow.clone().next().map(|(k, v)| (k.clone(), v.clone())) + // } +} diff --git a/fs-storage/tests/FileStorage.java b/fs-storage/tests/FileStorage.java index 1f639b0..1897271 100644 --- a/fs-storage/tests/FileStorage.java +++ b/fs-storage/tests/FileStorage.java @@ -9,7 +9,7 @@ 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 String getValue(String id, long file_storage_ptr); private static native void remove(String id, long file_storage_ptr); @@ -35,9 +35,9 @@ public void set(String id, String value) { set(id, value, this.fileStoragePtr); } - public String get(String id) { - return getValue(id, this.fileStoragePtr); - } + // public String get(String id) { + // return getValue(id, this.fileStoragePtr); + // } public void remove(String id) { remove(id, this.fileStoragePtr); @@ -66,9 +66,13 @@ 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); + + public WrapperBTreeMap getBTreeWrapper() { + return new WrapperBTreeMap(this.fileStoragePtr); } + + // public FileStorageIterator iterator() { + // long iteratorPtr = createIterator(this.fileStoragePtr); + // return new FileStorageIterator(iteratorPtr); + // } } diff --git a/fs-storage/tests/FileStorageTest.java b/fs-storage/tests/FileStorageTest.java index 119d001..7370b2b 100644 --- a/fs-storage/tests/FileStorageTest.java +++ b/fs-storage/tests/FileStorageTest.java @@ -113,43 +113,52 @@ public void testFileStorageMainScenario() { assertFalse(file.exists()); } - @Test - public void testReadData() { - Path storagePath = tempDir.resolve("test.txt"); - FileStorage fileStorage = new FileStorage("test", storagePath.toString()); - fileStorage.set("key1", "value1"); - fileStorage.set("key2", "value2"); - fileStorage.set("se3", "ni"); - fileStorage.writeFS(); - @SuppressWarnings("unchecked") - LinkedHashMap data = (LinkedHashMap) fileStorage.readFS(); - LinkedHashMap linkedHashMap = new LinkedHashMap<>(); + // @Test + // public void testReadData() { + // Path storagePath = tempDir.resolve("test.txt"); + // FileStorage fileStorage = new FileStorage("test", storagePath.toString()); + // fileStorage.set("key1", "value1"); + // fileStorage.set("key2", "value2"); + // fileStorage.set("se3", "ni"); + // fileStorage.writeFS(); + // @SuppressWarnings("unchecked") + // LinkedHashMap data = (LinkedHashMap) fileStorage.readFS(); + // LinkedHashMap linkedHashMap = new LinkedHashMap<>(); - FileStorageIterator iterator = fileStorage.iterator(); - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - linkedHashMap.put(entry.getKey(), entry.getValue()); - } - assertEquals(data, linkedHashMap); - } - - @Test - public void testHasNext() { - Path storagePath = tempDir.resolve("test.txt"); - FileStorage fileStorage = new FileStorage("test", storagePath.toString()); - fileStorage.set("key1", "value1"); - fileStorage.set("key2", "value2"); - fileStorage.set("se3", "ni"); - FileStorageIterator yo = fileStorage.iterator(); - assertTrue(fileStorage.iterator().hasNext()); - } - - @Test - public void testGetValue() { + // FileStorageIterator iterator = fileStorage.iterator(); + // while (iterator.hasNext()) { + // Map.Entry entry = iterator.next(); + // linkedHashMap.put(entry.getKey(), entry.getValue()); + // } + // assertEquals(data, linkedHashMap); + // } + + // @Test + // public void testHasNext() { + // Path storagePath = tempDir.resolve("test.txt"); + // FileStorage fileStorage = new FileStorage("test", storagePath.toString()); + // fileStorage.set("key1", "value1"); + // fileStorage.set("key2", "value2"); + // fileStorage.set("se3", "ni"); + // FileStorageIterator yo = fileStorage.iterator(); + // assertTrue(fileStorage.iterator().hasNext()); + // } + + // @Test + // public void testGetValue() { + // Path storagePath = tempDir.resolve("test.txt"); + // FileStorage fileStorage = new FileStorage("test", storagePath.toString()); + // fileStorage.set("key", "value"); + // assertEquals("value", fileStorage.get("key")); + // } + + @Test + public void testGetValue(){ Path storagePath = tempDir.resolve("test.txt"); FileStorage fileStorage = new FileStorage("test", storagePath.toString()); fileStorage.set("key", "value"); - assertEquals("value", fileStorage.get("key")); + WrapperBTreeMap bTreeWrapper = fileStorage.getBTreeWrapper(); + assertEquals("value", bTreeWrapper.get("key")); } @Test diff --git a/fs-storage/tests/WrapperBTreeMap.java b/fs-storage/tests/WrapperBTreeMap.java new file mode 100644 index 0000000..c085240 --- /dev/null +++ b/fs-storage/tests/WrapperBTreeMap.java @@ -0,0 +1,56 @@ +public class WrapperBTreeMap { + private long bTreePtr; + + private static native long create(long storage_ptr); + + private static native String get(String id, long b_tree_ptr); + + WrapperBTreeMap(long storagePtr) { + this.bTreePtr = create(storagePtr); + } + + public String get(String id) { + return get(id, this.bTreePtr); + } +} + + +// import java.util.Iterator; +// import java.util.Map; +// import java.util.NoSuchElementException; + +// public class FileStorageIterator implements Iterator>, 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 next() { +// if (!hasNext()) { +// throw new NoSuchElementException(); +// } +// return (Map.Entry) next(this.fileStorageIteratorPtr); +// } + +// @Override +// public void close() { +// if (this.fileStorageIteratorPtr != 0) { +// destroyIterator(this.fileStorageIteratorPtr); +// this.fileStorageIteratorPtr = 0; +// } +// } +// }