From 8d181ef3c6ac78ce409e51eb49e969313e323fb6 Mon Sep 17 00:00:00 2001 From: tison Date: Sun, 26 May 2024 20:20:10 +0800 Subject: [PATCH] refactor(binding/java)!: rename blocking and async operator (#4641) * refactor: Operator to AsyncOperator Signed-off-by: tison * refactor: BlockingOperator to Operator Signed-off-by: tison * follow up refactors in Java code Signed-off-by: tison * follow up refactors in Rust code Signed-off-by: tison * add upgrade guide Signed-off-by: tison --------- Signed-off-by: tison --- bindings/java/README.md | 17 +- bindings/java/src/async_operator.rs | 781 ++++++++++++++++++ bindings/java/src/blocking_operator.rs | 282 ------- bindings/java/src/executor.rs | 2 +- bindings/java/src/lib.rs | 2 +- .../org/apache/opendal/AsyncOperator.java | 282 +++++++ .../org/apache/opendal/BlockingOperator.java | 134 --- .../java/org/apache/opendal/Operator.java | 235 +----- .../apache/opendal/OperatorInputStream.java | 2 +- .../apache/opendal/OperatorOutputStream.java | 2 +- bindings/java/src/operator.rs | 645 ++------------- .../opendal/test/AsyncExecutorTest.java | 4 +- .../org/apache/opendal/test/LayerTest.java | 6 +- .../org/apache/opendal/test/MetadataTest.java | 6 +- .../opendal/test/OperatorDuplicateTest.java | 10 +- .../apache/opendal/test/OperatorInfoTest.java | 6 +- .../test/OperatorInputOutputStreamTest.java | 4 +- .../opendal/test/OperatorUtf8DecodeTest.java | 4 +- .../test/behavior/AsyncAppendTest.java | 10 +- .../opendal/test/behavior/AsyncCopyTest.java | 66 +- .../test/behavior/AsyncCreateDirTest.java | 16 +- .../opendal/test/behavior/AsyncListTest.java | 54 +- .../test/behavior/AsyncPresignTest.java | 20 +- .../test/behavior/AsyncReadOnlyTest.java | 26 +- .../test/behavior/AsyncRenameTest.java | 64 +- .../opendal/test/behavior/AsyncWriteTest.java | 18 +- .../test/behavior/BehaviorExtension.java | 20 +- .../test/behavior/BehaviorTestBase.java | 17 +- .../test/behavior/BlockingCopyTest.java | 58 +- .../test/behavior/BlockingCreateDirTest.java | 16 +- .../test/behavior/BlockingListTest.java | 22 +- .../test/behavior/BlockingReadOnlyTest.java | 18 +- .../test/behavior/BlockingRenameTest.java | 62 +- .../test/behavior/BlockingWriteTest.java | 17 +- bindings/java/upgrade.md | 6 + 35 files changed, 1469 insertions(+), 1465 deletions(-) create mode 100644 bindings/java/src/async_operator.rs delete mode 100644 bindings/java/src/blocking_operator.rs create mode 100644 bindings/java/src/main/java/org/apache/opendal/AsyncOperator.java delete mode 100644 bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java diff --git a/bindings/java/README.md b/bindings/java/README.md index 35d5c34ed4a..dab8f450609 100644 --- a/bindings/java/README.md +++ b/bindings/java/README.md @@ -11,18 +11,19 @@ ```java import java.util.HashMap; import java.util.Map; +import org.apache.opendal.AsyncOperator; import org.apache.opendal.Operator; public class Main { - public static void main(String[] args) { - final Map conf = new HashMap<>(); - conf.put("root", "/tmp"); - - try (Operator op = Operator.of("fs", conf)) { - op.write("/path/to/data","Hello world").join(); - System.out.println(new String(op.read("/path/to/data").join())); - } + public static void main(String[] args) { + final Map conf = new HashMap<>(); + conf.put("root", "/tmp"); + + try (AsyncOperator op = AsyncOperator.of("fs", conf)) { + op.write("/path/to/data", "Hello world").join(); + System.out.println(new String(op.read("/path/to/data").join())); } + } } ``` diff --git a/bindings/java/src/async_operator.rs b/bindings/java/src/async_operator.rs new file mode 100644 index 00000000000..69b5a3f4837 --- /dev/null +++ b/bindings/java/src/async_operator.rs @@ -0,0 +1,781 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +use std::str::FromStr; +use std::time::Duration; + +use jni::objects::JByteArray; +use jni::objects::JClass; +use jni::objects::JObject; +use jni::objects::JString; +use jni::objects::JValue; +use jni::objects::JValueOwned; +use jni::sys::jlong; +use jni::sys::jobject; +use jni::sys::jsize; +use jni::JNIEnv; +use opendal::layers::BlockingLayer; +use opendal::raw::PresignedRequest; +use opendal::Operator; +use opendal::Scheme; + +use crate::convert::jmap_to_hashmap; +use crate::convert::jstring_to_string; +use crate::executor::{executor_or_default, get_current_env, Executor}; +use crate::make_entry; +use crate::make_metadata; +use crate::make_operator_info; +use crate::make_presigned_request; +use crate::Result; + +#[no_mangle] +pub extern "system" fn Java_org_apache_opendal_AsyncOperator_constructor( + mut env: JNIEnv, + _: JClass, + executor: *const Executor, + scheme: JString, + map: JObject, +) -> jlong { + intern_constructor(&mut env, executor, scheme, map).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_constructor( + env: &mut JNIEnv, + executor: *const Executor, + scheme: JString, + map: JObject, +) -> Result { + let scheme = Scheme::from_str(jstring_to_string(env, &scheme)?.as_str())?; + let map = jmap_to_hashmap(env, &map)?; + let mut op = Operator::via_map(scheme, map)?; + if !op.info().full_capability().blocking { + let layer = executor_or_default(env, executor)?.enter_with(BlockingLayer::create)?; + op = op.layer(layer); + } + Ok(Box::into_raw(Box::new(op)) as jlong) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_duplicate( + _: JNIEnv, + _: JClass, + op: *mut Operator, +) -> jlong { + let op = &mut *op; + Box::into_raw(Box::new(op.clone())) as jlong +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_disposeInternal( + _: JNIEnv, + _: JObject, + op: *mut Operator, +) { + drop(Box::from_raw(op)); +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_write( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, + content: JByteArray, +) -> jlong { + intern_write(&mut env, op, executor, path, content).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_write( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, + content: JByteArray, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + let content = env.convert_byte_array(content)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_write(op, path, content).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_write(op: &mut Operator, path: String, content: Vec) -> Result<()> { + Ok(op.write(&path, content).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_append( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, + content: JByteArray, +) -> jlong { + intern_append(&mut env, op, executor, path, content).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_append( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, + content: JByteArray, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + let content = env.convert_byte_array(content)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_append(op, path, content).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_append(op: &mut Operator, path: String, content: Vec) -> Result<()> { + Ok(op.write_with(&path, content).append(true).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_stat( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> jlong { + intern_stat(&mut env, op, executor, path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_stat( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_stat(op, path).await; + complete_future(id, result.map(JValueOwned::Object)) + }); + + Ok(id) +} + +async fn do_stat<'local>(op: &mut Operator, path: String) -> Result> { + let metadata = op.stat(&path).await?; + let mut env = unsafe { get_current_env() }; + make_metadata(&mut env, metadata) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_read( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> jlong { + intern_read(&mut env, op, executor, path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_read( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_read(op, path).await; + complete_future(id, result.map(JValueOwned::Object)) + }); + + Ok(id) +} + +async fn do_read<'local>(op: &mut Operator, path: String) -> Result> { + let content = op.read(&path).await?.to_bytes(); + + let env = unsafe { get_current_env() }; + let result = env.byte_array_from_slice(&content)?; + Ok(result.into()) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_delete( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> jlong { + intern_delete(&mut env, op, executor, path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_delete( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_delete(op, path).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_delete(op: &mut Operator, path: String) -> Result<()> { + Ok(op.delete(&path).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_makeBlockingOp( + _: JNIEnv, + _: JClass, + op: *mut Operator, +) -> jlong { + let op = unsafe { &mut *op }; + Box::into_raw(Box::new(op.blocking())) as jlong +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_makeOperatorInfo( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, +) -> jobject { + intern_make_operator_info(&mut env, op).unwrap_or_else(|e| { + e.throw(&mut env); + JObject::default().into_raw() + }) +} + +fn intern_make_operator_info(env: &mut JNIEnv, op: *mut Operator) -> Result { + let op = unsafe { &mut *op }; + Ok(make_operator_info(env, op.info())?.into_raw()) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_createDir( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> jlong { + intern_create_dir(&mut env, op, executor, path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_create_dir( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_create_dir(op, path).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_create_dir(op: &mut Operator, path: String) -> Result<()> { + Ok(op.create_dir(&path).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_copy( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + source_path: JString, + target_path: JString, +) -> jlong { + intern_copy(&mut env, op, executor, source_path, target_path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_copy( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + source_path: JString, + target_path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let source_path = jstring_to_string(env, &source_path)?; + let target_path = jstring_to_string(env, &target_path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_copy(op, source_path, target_path).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_copy(op: &mut Operator, source_path: String, target_path: String) -> Result<()> { + Ok(op.copy(&source_path, &target_path).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_rename( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + source_path: JString, + target_path: JString, +) -> jlong { + intern_rename(&mut env, op, executor, source_path, target_path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_rename( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + source_path: JString, + target_path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let source_path = jstring_to_string(env, &source_path)?; + let target_path = jstring_to_string(env, &target_path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_rename(op, source_path, target_path).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_rename(op: &mut Operator, source_path: String, target_path: String) -> Result<()> { + Ok(op.rename(&source_path, &target_path).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_removeAll( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> jlong { + intern_remove_all(&mut env, op, executor, path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_remove_all( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_remove_all(op, path).await; + complete_future(id, result.map(|_| JValueOwned::Void)) + }); + + Ok(id) +} + +async fn do_remove_all(op: &mut Operator, path: String) -> Result<()> { + Ok(op.remove_all(&path).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_list( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> jlong { + intern_list(&mut env, op, executor, path).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_list( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + + executor_or_default(env, executor)?.spawn(async move { + let result = do_list(op, path).await; + complete_future(id, result.map(JValueOwned::Object)) + }); + + Ok(id) +} + +async fn do_list<'local>(op: &mut Operator, path: String) -> Result> { + let obs = op.list(&path).await?; + + let mut env = unsafe { get_current_env() }; + let jarray = env.new_object_array( + obs.len() as jsize, + "org/apache/opendal/Entry", + JObject::null(), + )?; + + for (idx, entry) in obs.iter().enumerate() { + let entry = make_entry(&mut env, entry.to_owned())?; + env.set_object_array_element(&jarray, idx as jsize, entry)?; + } + + Ok(jarray.into()) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_presignRead( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, + expire: jlong, +) -> jlong { + intern_presign_read(&mut env, op, executor, path, expire).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_presign_read( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, + expire: jlong, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + let expire = Duration::from_nanos(expire as u64); + + executor_or_default(env, executor)?.spawn(async move { + let result = do_presign_read(op, path, expire).await; + let mut env = unsafe { get_current_env() }; + let result = result.and_then(|req| make_presigned_request(&mut env, req)); + complete_future(id, result.map(JValueOwned::Object)) + }); + + Ok(id) +} + +async fn do_presign_read( + op: &mut Operator, + path: String, + expire: Duration, +) -> Result { + Ok(op.presign_read(&path, expire).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_presignWrite( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, + expire: jlong, +) -> jlong { + intern_presign_write(&mut env, op, executor, path, expire).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_presign_write( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, + expire: jlong, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + let expire = Duration::from_nanos(expire as u64); + + executor_or_default(env, executor)?.spawn(async move { + let result = do_presign_write(op, path, expire).await; + let mut env = unsafe { get_current_env() }; + let result = result.and_then(|req| make_presigned_request(&mut env, req)); + complete_future(id, result.map(JValueOwned::Object)) + }); + + Ok(id) +} + +async fn do_presign_write( + op: &mut Operator, + path: String, + expire: Duration, +) -> Result { + Ok(op.presign_write(&path, expire).await?) +} + +/// # Safety +/// +/// This function should not be called before the Operator is ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_AsyncOperator_presignStat( + mut env: JNIEnv, + _: JClass, + op: *mut Operator, + executor: *const Executor, + path: JString, + expire: jlong, +) -> jlong { + intern_presign_stat(&mut env, op, executor, path, expire).unwrap_or_else(|e| { + e.throw(&mut env); + 0 + }) +} + +fn intern_presign_stat( + env: &mut JNIEnv, + op: *mut Operator, + executor: *const Executor, + path: JString, + expire: jlong, +) -> Result { + let op = unsafe { &mut *op }; + let id = request_id(env)?; + + let path = jstring_to_string(env, &path)?; + let expire = Duration::from_nanos(expire as u64); + + executor_or_default(env, executor)?.spawn(async move { + let result = do_presign_stat(op, path, expire).await; + let mut env = unsafe { get_current_env() }; + let result = result.and_then(|req| make_presigned_request(&mut env, req)); + complete_future(id, result.map(JValueOwned::Object)) + }); + + Ok(id) +} + +async fn do_presign_stat( + op: &mut Operator, + path: String, + expire: Duration, +) -> Result { + Ok(op.presign_stat(&path, expire).await?) +} + +fn make_object<'local>( + env: &mut JNIEnv<'local>, + value: JValueOwned<'local>, +) -> Result> { + let o = match value { + JValueOwned::Object(o) => o, + JValueOwned::Byte(_) => env.new_object("java/lang/Long", "(B)V", &[value.borrow()])?, + JValueOwned::Char(_) => env.new_object("java/lang/Char", "(C)V", &[value.borrow()])?, + JValueOwned::Short(_) => env.new_object("java/lang/Short", "(S)V", &[value.borrow()])?, + JValueOwned::Int(_) => env.new_object("java/lang/Integer", "(I)V", &[value.borrow()])?, + JValueOwned::Long(_) => env.new_object("java/lang/Long", "(J)V", &[value.borrow()])?, + JValueOwned::Bool(_) => env.new_object("java/lang/Boolean", "(Z)V", &[value.borrow()])?, + JValueOwned::Float(_) => env.new_object("java/lang/Float", "(F)V", &[value.borrow()])?, + JValueOwned::Double(_) => env.new_object("java/lang/Double", "(D)V", &[value.borrow()])?, + JValueOwned::Void => JObject::null(), + }; + Ok(o) +} + +fn complete_future(id: jlong, result: Result) { + try_complete_future(id, result).expect("complete future must succeed"); +} + +fn try_complete_future(id: jlong, result: Result) -> Result<()> { + let mut env = unsafe { get_current_env() }; + let future = get_future(&mut env, id)?; + match result { + Ok(result) => { + let result = make_object(&mut env, result)?; + env.call_method( + future, + "complete", + "(Ljava/lang/Object;)Z", + &[JValue::Object(&result)], + )? + } + Err(err) => { + let exception = err.to_exception(&mut env)?; + env.call_method( + future, + "completeExceptionally", + "(Ljava/lang/Throwable;)Z", + &[JValue::Object(&exception)], + )? + } + }; + Ok(()) +} + +fn request_id(env: &mut JNIEnv) -> Result { + Ok(env + .call_static_method( + "org/apache/opendal/AsyncOperator$AsyncRegistry", + "requestId", + "()J", + &[], + )? + .j()?) +} + +fn get_future<'local>(env: &mut JNIEnv<'local>, id: jlong) -> Result> { + Ok(env + .call_static_method( + "org/apache/opendal/AsyncOperator$AsyncRegistry", + "get", + "(J)Ljava/util/concurrent/CompletableFuture;", + &[JValue::Long(id)], + )? + .l()?) +} diff --git a/bindings/java/src/blocking_operator.rs b/bindings/java/src/blocking_operator.rs deleted file mode 100644 index 88d92d1a409..00000000000 --- a/bindings/java/src/blocking_operator.rs +++ /dev/null @@ -1,282 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -use jni::objects::JByteArray; -use jni::objects::JClass; -use jni::objects::JObject; -use jni::objects::JString; -use jni::sys::jbyteArray; -use jni::sys::jlong; -use jni::sys::jobject; -use jni::sys::jobjectArray; -use jni::sys::jsize; -use jni::JNIEnv; - -use opendal::BlockingOperator; - -use crate::convert::jstring_to_string; -use crate::make_entry; -use crate::make_metadata; -use crate::Result; - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_disposeInternal( - _: JNIEnv, - _: JObject, - op: *mut BlockingOperator, -) { - drop(Box::from_raw(op)); -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_duplicate( - _: JNIEnv, - _: JObject, - op: *mut BlockingOperator, -) -> jlong { - let op = &mut *op; - Box::into_raw(Box::new(op.clone())) as jlong -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_read( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - path: JString, -) -> jbyteArray { - intern_read(&mut env, &mut *op, path).unwrap_or_else(|e| { - e.throw(&mut env); - JByteArray::default().into_raw() - }) -} - -fn intern_read(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { - let path = jstring_to_string(env, &path)?; - let content = op.read(&path)?.to_bytes(); - let result = env.byte_array_from_slice(&content)?; - Ok(result.into_raw()) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_write( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - path: JString, - content: JByteArray, -) { - intern_write(&mut env, &mut *op, path, content).unwrap_or_else(|e| { - e.throw(&mut env); - }) -} - -fn intern_write( - env: &mut JNIEnv, - op: &mut BlockingOperator, - path: JString, - content: JByteArray, -) -> Result<()> { - let path = jstring_to_string(env, &path)?; - let content = env.convert_byte_array(content)?; - Ok(op.write(&path, content)?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_stat( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - path: JString, -) -> jobject { - intern_stat(&mut env, &mut *op, path).unwrap_or_else(|e| { - e.throw(&mut env); - JObject::default().into_raw() - }) -} - -fn intern_stat(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { - let path = jstring_to_string(env, &path)?; - let metadata = op.stat(&path)?; - Ok(make_metadata(env, metadata)?.into_raw()) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_delete( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - path: JString, -) { - intern_delete(&mut env, &mut *op, path).unwrap_or_else(|e| { - e.throw(&mut env); - }) -} - -fn intern_delete(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { - let path = jstring_to_string(env, &path)?; - Ok(op.delete(&path)?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_createDir( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - path: JString, -) { - intern_create_dir(&mut env, &mut *op, path).unwrap_or_else(|e| { - e.throw(&mut env); - }) -} - -fn intern_create_dir(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { - let path = jstring_to_string(env, &path)?; - Ok(op.create_dir(&path)?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_copy( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - source_path: JString, - target_path: JString, -) { - intern_copy(&mut env, &mut *op, source_path, target_path).unwrap_or_else(|e| { - e.throw(&mut env); - }) -} - -fn intern_copy( - env: &mut JNIEnv, - op: &mut BlockingOperator, - source_path: JString, - target_path: JString, -) -> Result<()> { - let source_path = jstring_to_string(env, &source_path)?; - let target_path = jstring_to_string(env, &target_path)?; - - Ok(op.copy(&source_path, &target_path)?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_rename( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - source_path: JString, - target_path: JString, -) { - intern_rename(&mut env, &mut *op, source_path, target_path).unwrap_or_else(|e| { - e.throw(&mut env); - }) -} - -fn intern_rename( - env: &mut JNIEnv, - op: &mut BlockingOperator, - source_path: JString, - target_path: JString, -) -> Result<()> { - let source_path = jstring_to_string(env, &source_path)?; - let target_path = jstring_to_string(env, &target_path)?; - - Ok(op.rename(&source_path, &target_path)?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_removeAll( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - path: JString, -) { - intern_remove_all(&mut env, &mut *op, path).unwrap_or_else(|e| { - e.throw(&mut env); - }) -} - -fn intern_remove_all(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { - let path = jstring_to_string(env, &path)?; - - Ok(op.remove_all(&path)?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_list( - mut env: JNIEnv, - _: JClass, - op: *mut BlockingOperator, - path: JString, -) -> jobjectArray { - intern_list(&mut env, &mut *op, path).unwrap_or_else(|e| { - e.throw(&mut env); - JObject::default().into_raw() - }) -} - -fn intern_list(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { - let path = jstring_to_string(env, &path)?; - let obs = op.list(&path)?; - - let jarray = env.new_object_array( - obs.len() as jsize, - "org/apache/opendal/Entry", - JObject::null(), - )?; - - for (idx, entry) in obs.iter().enumerate() { - let entry = make_entry(env, entry.to_owned())?; - env.set_object_array_element(&jarray, idx as jsize, entry)?; - } - - Ok(jarray.into_raw()) -} diff --git a/bindings/java/src/executor.rs b/bindings/java/src/executor.rs index 3fe67f4f7f4..6bda868fa35 100644 --- a/bindings/java/src/executor.rs +++ b/bindings/java/src/executor.rs @@ -29,7 +29,7 @@ use crate::Result; static mut RUNTIME: OnceCell = OnceCell::new(); thread_local! { - static ENV: RefCell> = RefCell::new(None); + static ENV: RefCell> = const { RefCell::new(None) }; } /// # Safety diff --git a/bindings/java/src/lib.rs b/bindings/java/src/lib.rs index 3dde9062226..64fffcab3a3 100644 --- a/bindings/java/src/lib.rs +++ b/bindings/java/src/lib.rs @@ -32,7 +32,7 @@ use opendal::Metadata; use opendal::Metakey; use opendal::OperatorInfo; -mod blocking_operator; +mod async_operator; mod convert; mod error; mod executor; diff --git a/bindings/java/src/main/java/org/apache/opendal/AsyncOperator.java b/bindings/java/src/main/java/org/apache/opendal/AsyncOperator.java new file mode 100644 index 00000000000..06d3fa72a74 --- /dev/null +++ b/bindings/java/src/main/java/org/apache/opendal/AsyncOperator.java @@ -0,0 +1,282 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.opendal; + +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +/** + * AsyncOperator represents an underneath OpenDAL operator that + * accesses data asynchronously. + */ +public class AsyncOperator extends NativeObject { + + /** + * Singleton to hold all outstanding futures. + * + *

+ * This is a trick to avoid using global references to pass {@link CompletableFuture} + * among language boundary and between multiple native threads. + * + * @see Global References + * @see jni::objects::GlobalRef + */ + private enum AsyncRegistry { + INSTANCE; + + private final Map> registry = new ConcurrentHashMap<>(); + + /** + * Request a new {@link CompletableFuture} that is associated with a unique ID. + * + *

+ * This method is called from native code. The return ID is used by: + * + *

  • Rust side: {@link #get(long)} the future when the native async op completed
  • + *
  • Java side: {@link #take(long)} the future to compose with more actions
  • + * + * @return the request ID associated to the obtained future + */ + @SuppressWarnings("unused") + private static long requestId() { + final CompletableFuture f = new CompletableFuture<>(); + while (true) { + final long requestId = Math.abs(UUID.randomUUID().getLeastSignificantBits()); + final CompletableFuture prev = INSTANCE.registry.putIfAbsent(requestId, f); + if (prev == null) { + return requestId; + } + } + } + + /** + * Get the future associated with the request ID. + * + *

    + * This method is called from native code. + * + * @param requestId to identify the future + * @return the future associated with the request ID + */ + private static CompletableFuture get(long requestId) { + return INSTANCE.registry.get(requestId); + } + + /** + * Take the future associated with the request ID. + * + * @param requestId to identify the future + * @return the future associated with the request ID + */ + @SuppressWarnings("unchecked") + private static CompletableFuture take(long requestId) { + final CompletableFuture f = get(requestId); + if (f != null) { + f.whenComplete((r, e) -> INSTANCE.registry.remove(requestId)); + } + return (CompletableFuture) f; + } + } + + public final OperatorInfo info; + + private final long executorHandle; + + /** + * Construct an OpenDAL operator: + * + *

    + * You can find all possible schemes here + * and see what config options each service supports. + * + * @param schema the name of the underneath service to access data from. + * @param map a map of properties to construct the underneath operator. + */ + public static AsyncOperator of(String schema, Map map) { + return of(schema, map, null); + } + + /** + * Construct an OpenDAL operator: + * + *

    + * You can find all possible schemes here + * and see what config options each service supports. + * + * @param schema the name of the underneath service to access data from. + * @param map a map of properties to construct the underneath operator. + * @param executor the underneath executor to run async operations; {@code null} to use a default global executor. + */ + public static AsyncOperator of(String schema, Map map, AsyncExecutor executor) { + final long executorHandle = executor != null ? executor.nativeHandle : 0; + final long nativeHandle = constructor(executorHandle, schema, map); + final OperatorInfo info = makeOperatorInfo(nativeHandle); + return new AsyncOperator(nativeHandle, executorHandle, info); + } + + private AsyncOperator(long nativeHandle, long executorHandle, OperatorInfo info) { + super(nativeHandle); + this.info = info; + this.executorHandle = executorHandle; + } + + /** + * Clone a new operator that is identical to this one. The new operator has its own lifecycle. + * + *

    Since an operator will release all its resource and "flush" on lifecycle end, this method + * is suitable to create a narrowed "scope" while avoiding creating a brand-new operator for each + * scope. + * + * @return the cloned operator. + */ + public AsyncOperator duplicate() { + final long nativeHandle = duplicate(this.nativeHandle); + return new AsyncOperator(nativeHandle, this.executorHandle, this.info); + } + + public AsyncOperator layer(Layer layer) { + final long nativeHandle = layer.layer(this.nativeHandle); + return new AsyncOperator(nativeHandle, this.executorHandle, makeOperatorInfo(nativeHandle)); + } + + public Operator blocking() { + final long nativeHandle = makeBlockingOp(this.nativeHandle); + final OperatorInfo info = this.info; + return new Operator(nativeHandle, info); + } + + public CompletableFuture write(String path, String content) { + return write(path, content.getBytes(StandardCharsets.UTF_8)); + } + + public CompletableFuture write(String path, byte[] content) { + final long requestId = write(nativeHandle, executorHandle, path, content); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture append(String path, String content) { + return append(path, content.getBytes(StandardCharsets.UTF_8)); + } + + public CompletableFuture append(String path, byte[] content) { + final long requestId = append(nativeHandle, executorHandle, path, content); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture stat(String path) { + final long requestId = stat(nativeHandle, executorHandle, path); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture read(String path) { + final long requestId = read(nativeHandle, executorHandle, path); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture presignRead(String path, Duration duration) { + final long requestId = presignRead(nativeHandle, executorHandle, path, duration.toNanos()); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture presignWrite(String path, Duration duration) { + final long requestId = presignWrite(nativeHandle, executorHandle, path, duration.toNanos()); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture presignStat(String path, Duration duration) { + final long requestId = presignStat(nativeHandle, executorHandle, path, duration.toNanos()); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture delete(String path) { + final long requestId = delete(nativeHandle, executorHandle, path); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture createDir(String path) { + final long requestId = createDir(nativeHandle, executorHandle, path); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture copy(String sourcePath, String targetPath) { + final long requestId = copy(nativeHandle, executorHandle, sourcePath, targetPath); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture rename(String sourcePath, String targetPath) { + final long requestId = rename(nativeHandle, executorHandle, sourcePath, targetPath); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture removeAll(String path) { + final long requestId = removeAll(nativeHandle, executorHandle, path); + return AsyncRegistry.take(requestId); + } + + public CompletableFuture> list(String path) { + final long requestId = list(nativeHandle, executorHandle, path); + final CompletableFuture result = AsyncRegistry.take(requestId); + return Objects.requireNonNull(result).thenApplyAsync(Arrays::asList); + } + + @Override + protected native void disposeInternal(long handle); + + private static native long duplicate(long nativeHandle); + + private static native long constructor(long executorHandle, String schema, Map map); + + private static native long read(long nativeHandle, long executorHandle, String path); + + private static native long write(long nativeHandle, long executorHandle, String path, byte[] content); + + private static native long append(long nativeHandle, long executorHandle, String path, byte[] content); + + private static native long delete(long nativeHandle, long executorHandle, String path); + + private static native long stat(long nativeHandle, long executorHandle, String path); + + private static native long presignRead(long nativeHandle, long executorHandle, String path, long duration); + + private static native long presignWrite(long nativeHandle, long executorHandle, String path, long duration); + + private static native long presignStat(long nativeHandle, long executorHandle, String path, long duration); + + private static native OperatorInfo makeOperatorInfo(long nativeHandle); + + private static native long makeBlockingOp(long nativeHandle); + + private static native long createDir(long nativeHandle, long executorHandle, String path); + + private static native long copy(long nativeHandle, long executorHandle, String sourcePath, String targetPath); + + private static native long rename(long nativeHandle, long executorHandle, String sourcePath, String targetPath); + + private static native long removeAll(long nativeHandle, long executorHandle, String path); + + private static native long list(long nativeHandle, long executorHandle, String path); +} diff --git a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java b/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java deleted file mode 100644 index 833e6ac04bb..00000000000 --- a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.opendal; - -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * BlockingOperator represents an underneath OpenDAL operator that - * accesses data synchronously. - */ -public class BlockingOperator extends NativeObject { - public final OperatorInfo info; - - /** - * Construct an OpenDAL blocking operator: - * - *

    - * You can find all possible schemes here - * and see what config options each service supports. - * - * @param schema the name of the underneath service to access data from. - * @param map a map of properties to construct the underneath operator. - */ - public static BlockingOperator of(String schema, Map map) { - try (final Operator operator = Operator.of(schema, map)) { - return operator.blocking(); - } - } - - BlockingOperator(long nativeHandle, OperatorInfo info) { - super(nativeHandle); - this.info = info; - } - - /** - * @return the cloned blocking operator. - * @see Operator#duplicate() - */ - public BlockingOperator duplicate() { - final long nativeHandle = duplicate(this.nativeHandle); - return new BlockingOperator(nativeHandle, this.info); - } - - public void write(String path, String content) { - write(path, content.getBytes(StandardCharsets.UTF_8)); - } - - public void write(String path, byte[] content) { - write(nativeHandle, path, content); - } - - public OperatorOutputStream createOutputStream(String path) { - return new OperatorOutputStream(this, path); - } - - public byte[] read(String path) { - return read(nativeHandle, path); - } - - public OperatorInputStream createInputStream(String path) { - return new OperatorInputStream(this, path); - } - - public void delete(String path) { - delete(nativeHandle, path); - } - - public Metadata stat(String path) { - return stat(nativeHandle, path); - } - - public void createDir(String path) { - createDir(nativeHandle, path); - } - - public void copy(String sourcePath, String targetPath) { - copy(nativeHandle, sourcePath, targetPath); - } - - public void rename(String sourcePath, String targetPath) { - rename(nativeHandle, sourcePath, targetPath); - } - - public void removeAll(String path) { - removeAll(nativeHandle, path); - } - - public List list(String path) { - return Arrays.asList(list(nativeHandle, path)); - } - - @Override - protected native void disposeInternal(long handle); - - private static native long duplicate(long op); - - private static native void write(long op, String path, byte[] content); - - private static native byte[] read(long op, String path); - - private static native void delete(long op, String path); - - private static native Metadata stat(long op, String path); - - private static native long createDir(long op, String path); - - private static native long copy(long op, String sourcePath, String targetPath); - - private static native long rename(long op, String sourcePath, String targetPath); - - private static native void removeAll(long op, String path); - - private static native Entry[] list(long op, String path); -} diff --git a/bindings/java/src/main/java/org/apache/opendal/Operator.java b/bindings/java/src/main/java/org/apache/opendal/Operator.java index a6d84b7b11f..63ede3829ee 100644 --- a/bindings/java/src/main/java/org/apache/opendal/Operator.java +++ b/bindings/java/src/main/java/org/apache/opendal/Operator.java @@ -20,94 +20,18 @@ package org.apache.opendal; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; /** - * Operator represents an underneath OpenDAL operator that - * accesses data asynchronously. + * Operator represents an underneath OpenDAL operator that accesses data synchronously. */ public class Operator extends NativeObject { - - /** - * Singleton to hold all outstanding futures. - * - *

    - * This is a trick to avoid using global references to pass {@link CompletableFuture} - * among language boundary and between multiple native threads. - * - * @see Global References - * @see jni::objects::GlobalRef - */ - private enum AsyncRegistry { - INSTANCE; - - private final Map> registry = new ConcurrentHashMap<>(); - - /** - * Request a new {@link CompletableFuture} that is associated with a unique ID. - * - *

    - * This method is called from native code. The return ID is used by: - * - *

  • Rust side: {@link #get(long)} the future when the native async op completed
  • - *
  • Java side: {@link #take(long)} the future to compose with more actions
  • - * - * @return the request ID associated to the obtained future - */ - @SuppressWarnings("unused") - private static long requestId() { - final CompletableFuture f = new CompletableFuture<>(); - while (true) { - final long requestId = Math.abs(UUID.randomUUID().getLeastSignificantBits()); - final CompletableFuture prev = INSTANCE.registry.putIfAbsent(requestId, f); - if (prev == null) { - return requestId; - } - } - } - - /** - * Get the future associated with the request ID. - * - *

    - * This method is called from native code. - * - * @param requestId to identify the future - * @return the future associated with the request ID - */ - private static CompletableFuture get(long requestId) { - return INSTANCE.registry.get(requestId); - } - - /** - * Take the future associated with the request ID. - * - * @param requestId to identify the future - * @return the future associated with the request ID - */ - @SuppressWarnings("unchecked") - private static CompletableFuture take(long requestId) { - final CompletableFuture f = get(requestId); - if (f != null) { - f.whenComplete((r, e) -> INSTANCE.registry.remove(requestId)); - } - return (CompletableFuture) f; - } - } - public final OperatorInfo info; - private final long executorHandle; - /** - * Construct an OpenDAL operator: + * Construct an OpenDAL blocking operator: * *

    * You can find all possible schemes here @@ -117,166 +41,93 @@ private static CompletableFuture take(long requestId) { * @param map a map of properties to construct the underneath operator. */ public static Operator of(String schema, Map map) { - return of(schema, map, null); - } - - /** - * Construct an OpenDAL operator: - * - *

    - * You can find all possible schemes here - * and see what config options each service supports. - * - * @param schema the name of the underneath service to access data from. - * @param map a map of properties to construct the underneath operator. - * @param executor the underneath executor to run async operations; {@code null} to use a default global executor. - */ - public static Operator of(String schema, Map map, AsyncExecutor executor) { - final long executorHandle = executor != null ? executor.nativeHandle : 0; - final long nativeHandle = constructor(executorHandle, schema, map); - final OperatorInfo info = makeOperatorInfo(nativeHandle); - return new Operator(nativeHandle, executorHandle, info); + try (final AsyncOperator operator = AsyncOperator.of(schema, map)) { + return operator.blocking(); + } } - private Operator(long nativeHandle, long executorHandle, OperatorInfo info) { + Operator(long nativeHandle, OperatorInfo info) { super(nativeHandle); this.info = info; - this.executorHandle = executorHandle; } /** - * Clone a new operator that is identical to this one. The new operator has its own lifecycle. - * - *

    Since an operator will release all its resource and "flush" on lifecycle end, this method - * is suitable to create a narrowed "scope" while avoiding creating a brand-new operator for each - * scope. - * - * @return the cloned operator. + * @return the cloned blocking operator. + * @see AsyncOperator#duplicate() */ public Operator duplicate() { final long nativeHandle = duplicate(this.nativeHandle); - return new Operator(nativeHandle, this.executorHandle, this.info); - } - - public Operator layer(Layer layer) { - final long nativeHandle = layer.layer(this.nativeHandle); - return new Operator(nativeHandle, this.executorHandle, makeOperatorInfo(nativeHandle)); - } - - public BlockingOperator blocking() { - final long nativeHandle = makeBlockingOp(this.nativeHandle); - final OperatorInfo info = this.info; - return new BlockingOperator(nativeHandle, info); - } - - public CompletableFuture write(String path, String content) { - return write(path, content.getBytes(StandardCharsets.UTF_8)); + return new Operator(nativeHandle, this.info); } - public CompletableFuture write(String path, byte[] content) { - final long requestId = write(nativeHandle, executorHandle, path, content); - return AsyncRegistry.take(requestId); + public void write(String path, String content) { + write(path, content.getBytes(StandardCharsets.UTF_8)); } - public CompletableFuture append(String path, String content) { - return append(path, content.getBytes(StandardCharsets.UTF_8)); + public void write(String path, byte[] content) { + write(nativeHandle, path, content); } - public CompletableFuture append(String path, byte[] content) { - final long requestId = append(nativeHandle, executorHandle, path, content); - return AsyncRegistry.take(requestId); + public OperatorOutputStream createOutputStream(String path) { + return new OperatorOutputStream(this, path); } - public CompletableFuture stat(String path) { - final long requestId = stat(nativeHandle, executorHandle, path); - return AsyncRegistry.take(requestId); + public byte[] read(String path) { + return read(nativeHandle, path); } - public CompletableFuture read(String path) { - final long requestId = read(nativeHandle, executorHandle, path); - return AsyncRegistry.take(requestId); + public OperatorInputStream createInputStream(String path) { + return new OperatorInputStream(this, path); } - public CompletableFuture presignRead(String path, Duration duration) { - final long requestId = presignRead(nativeHandle, executorHandle, path, duration.toNanos()); - return AsyncRegistry.take(requestId); + public void delete(String path) { + delete(nativeHandle, path); } - public CompletableFuture presignWrite(String path, Duration duration) { - final long requestId = presignWrite(nativeHandle, executorHandle, path, duration.toNanos()); - return AsyncRegistry.take(requestId); + public Metadata stat(String path) { + return stat(nativeHandle, path); } - public CompletableFuture presignStat(String path, Duration duration) { - final long requestId = presignStat(nativeHandle, executorHandle, path, duration.toNanos()); - return AsyncRegistry.take(requestId); + public void createDir(String path) { + createDir(nativeHandle, path); } - public CompletableFuture delete(String path) { - final long requestId = delete(nativeHandle, executorHandle, path); - return AsyncRegistry.take(requestId); + public void copy(String sourcePath, String targetPath) { + copy(nativeHandle, sourcePath, targetPath); } - public CompletableFuture createDir(String path) { - final long requestId = createDir(nativeHandle, executorHandle, path); - return AsyncRegistry.take(requestId); + public void rename(String sourcePath, String targetPath) { + rename(nativeHandle, sourcePath, targetPath); } - public CompletableFuture copy(String sourcePath, String targetPath) { - final long requestId = copy(nativeHandle, executorHandle, sourcePath, targetPath); - return AsyncRegistry.take(requestId); + public void removeAll(String path) { + removeAll(nativeHandle, path); } - public CompletableFuture rename(String sourcePath, String targetPath) { - final long requestId = rename(nativeHandle, executorHandle, sourcePath, targetPath); - return AsyncRegistry.take(requestId); - } - - public CompletableFuture removeAll(String path) { - final long requestId = removeAll(nativeHandle, executorHandle, path); - return AsyncRegistry.take(requestId); - } - - public CompletableFuture> list(String path) { - final long requestId = list(nativeHandle, executorHandle, path); - final CompletableFuture result = AsyncRegistry.take(requestId); - return Objects.requireNonNull(result).thenApplyAsync(Arrays::asList); + public List list(String path) { + return Arrays.asList(list(nativeHandle, path)); } @Override protected native void disposeInternal(long handle); - private static native long duplicate(long nativeHandle); - - private static native long constructor(long executorHandle, String schema, Map map); - - private static native long read(long nativeHandle, long executorHandle, String path); - - private static native long write(long nativeHandle, long executorHandle, String path, byte[] content); - - private static native long append(long nativeHandle, long executorHandle, String path, byte[] content); - - private static native long delete(long nativeHandle, long executorHandle, String path); - - private static native long stat(long nativeHandle, long executorHandle, String path); - - private static native long presignRead(long nativeHandle, long executorHandle, String path, long duration); + private static native long duplicate(long op); - private static native long presignWrite(long nativeHandle, long executorHandle, String path, long duration); + private static native void write(long op, String path, byte[] content); - private static native long presignStat(long nativeHandle, long executorHandle, String path, long duration); + private static native byte[] read(long op, String path); - private static native OperatorInfo makeOperatorInfo(long nativeHandle); + private static native void delete(long op, String path); - private static native long makeBlockingOp(long nativeHandle); + private static native Metadata stat(long op, String path); - private static native long createDir(long nativeHandle, long executorHandle, String path); + private static native long createDir(long op, String path); - private static native long copy(long nativeHandle, long executorHandle, String sourcePath, String targetPath); + private static native long copy(long op, String sourcePath, String targetPath); - private static native long rename(long nativeHandle, long executorHandle, String sourcePath, String targetPath); + private static native long rename(long op, String sourcePath, String targetPath); - private static native long removeAll(long nativeHandle, long executorHandle, String path); + private static native void removeAll(long op, String path); - private static native long list(long nativeHandle, long executorHandle, String path); + private static native Entry[] list(long op, String path); } diff --git a/bindings/java/src/main/java/org/apache/opendal/OperatorInputStream.java b/bindings/java/src/main/java/org/apache/opendal/OperatorInputStream.java index a9eb6731d80..edb11d26b84 100644 --- a/bindings/java/src/main/java/org/apache/opendal/OperatorInputStream.java +++ b/bindings/java/src/main/java/org/apache/opendal/OperatorInputStream.java @@ -39,7 +39,7 @@ protected void disposeInternal(long handle) { private int offset = 0; private byte[] bytes = new byte[0]; - public OperatorInputStream(BlockingOperator operator, String path) { + public OperatorInputStream(Operator operator, String path) { final long op = operator.nativeHandle; this.reader = new Reader(constructReader(op, path)); } diff --git a/bindings/java/src/main/java/org/apache/opendal/OperatorOutputStream.java b/bindings/java/src/main/java/org/apache/opendal/OperatorOutputStream.java index 119346595ec..0f315174f03 100644 --- a/bindings/java/src/main/java/org/apache/opendal/OperatorOutputStream.java +++ b/bindings/java/src/main/java/org/apache/opendal/OperatorOutputStream.java @@ -42,7 +42,7 @@ protected void disposeInternal(long handle) { private int offset = 0; - public OperatorOutputStream(BlockingOperator operator, String path) { + public OperatorOutputStream(Operator operator, String path) { final long op = operator.nativeHandle; this.writer = new Writer(constructWriter(op, path)); } diff --git a/bindings/java/src/operator.rs b/bindings/java/src/operator.rs index ceb00e04915..e128f82bd8c 100644 --- a/bindings/java/src/operator.rs +++ b/bindings/java/src/operator.rs @@ -15,172 +15,97 @@ // specific language governing permissions and limitations // under the License. -use std::str::FromStr; -use std::time::Duration; - use jni::objects::JByteArray; use jni::objects::JClass; use jni::objects::JObject; use jni::objects::JString; -use jni::objects::JValue; -use jni::objects::JValueOwned; +use jni::sys::jbyteArray; use jni::sys::jlong; use jni::sys::jobject; +use jni::sys::jobjectArray; use jni::sys::jsize; use jni::JNIEnv; -use opendal::layers::BlockingLayer; -use opendal::raw::PresignedRequest; -use opendal::Operator; -use opendal::Scheme; -use crate::convert::jmap_to_hashmap; +use opendal::BlockingOperator; + use crate::convert::jstring_to_string; -use crate::executor::{executor_or_default, get_current_env, Executor}; use crate::make_entry; use crate::make_metadata; -use crate::make_operator_info; -use crate::make_presigned_request; use crate::Result; -#[no_mangle] -pub extern "system" fn Java_org_apache_opendal_Operator_constructor( - mut env: JNIEnv, - _: JClass, - executor: *const Executor, - scheme: JString, - map: JObject, -) -> jlong { - intern_constructor(&mut env, executor, scheme, map).unwrap_or_else(|e| { - e.throw(&mut env); - 0 - }) -} - -fn intern_constructor( - env: &mut JNIEnv, - executor: *const Executor, - scheme: JString, - map: JObject, -) -> Result { - let scheme = Scheme::from_str(jstring_to_string(env, &scheme)?.as_str())?; - let map = jmap_to_hashmap(env, &map)?; - let mut op = Operator::via_map(scheme, map)?; - if !op.info().full_capability().blocking { - let layer = executor_or_default(env, executor)?.enter_with(BlockingLayer::create)?; - op = op.layer(layer); - } - Ok(Box::into_raw(Box::new(op)) as jlong) -} - /// # Safety /// /// This function should not be called before the Operator is ready. #[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_duplicate( +pub unsafe extern "system" fn Java_org_apache_opendal_Operator_disposeInternal( _: JNIEnv, - _: JClass, - op: *mut Operator, -) -> jlong { - let op = &mut *op; - Box::into_raw(Box::new(op.clone())) as jlong + _: JObject, + op: *mut BlockingOperator, +) { + drop(Box::from_raw(op)); } /// # Safety /// /// This function should not be called before the Operator is ready. #[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_disposeInternal( +pub unsafe extern "system" fn Java_org_apache_opendal_Operator_duplicate( _: JNIEnv, _: JObject, - op: *mut Operator, -) { - drop(Box::from_raw(op)); + op: *mut BlockingOperator, +) -> jlong { + let op = &mut *op; + Box::into_raw(Box::new(op.clone())) as jlong } /// # Safety /// /// This function should not be called before the Operator is ready. #[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_write( +pub unsafe extern "system" fn Java_org_apache_opendal_Operator_read( mut env: JNIEnv, _: JClass, - op: *mut Operator, - executor: *const Executor, + op: *mut BlockingOperator, path: JString, - content: JByteArray, -) -> jlong { - intern_write(&mut env, op, executor, path, content).unwrap_or_else(|e| { +) -> jbyteArray { + intern_read(&mut env, &mut *op, path).unwrap_or_else(|e| { e.throw(&mut env); - 0 + JByteArray::default().into_raw() }) } -fn intern_write( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, - content: JByteArray, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +fn intern_read(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { let path = jstring_to_string(env, &path)?; - let content = env.convert_byte_array(content)?; - - executor_or_default(env, executor)?.spawn(async move { - let result = do_write(op, path, content).await; - complete_future(id, result.map(|_| JValueOwned::Void)) - }); - - Ok(id) -} - -async fn do_write(op: &mut Operator, path: String, content: Vec) -> Result<()> { - Ok(op.write(&path, content).await?) + let content = op.read(&path)?.to_bytes(); + let result = env.byte_array_from_slice(&content)?; + Ok(result.into_raw()) } /// # Safety /// /// This function should not be called before the Operator is ready. #[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_append( +pub unsafe extern "system" fn Java_org_apache_opendal_Operator_write( mut env: JNIEnv, _: JClass, - op: *mut Operator, - executor: *const Executor, + op: *mut BlockingOperator, path: JString, content: JByteArray, -) -> jlong { - intern_append(&mut env, op, executor, path, content).unwrap_or_else(|e| { +) { + intern_write(&mut env, &mut *op, path, content).unwrap_or_else(|e| { e.throw(&mut env); - 0 }) } -fn intern_append( +fn intern_write( env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, + op: &mut BlockingOperator, path: JString, content: JByteArray, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +) -> Result<()> { let path = jstring_to_string(env, &path)?; let content = env.convert_byte_array(content)?; - - executor_or_default(env, executor)?.spawn(async move { - let result = do_append(op, path, content).await; - complete_future(id, result.map(|_| JValueOwned::Void)) - }); - - Ok(id) -} - -async fn do_append(op: &mut Operator, path: String, content: Vec) -> Result<()> { - Ok(op.write_with(&path, content).append(true).await?) + Ok(op.write(&path, content)?) } /// # Safety @@ -190,83 +115,19 @@ async fn do_append(op: &mut Operator, path: String, content: Vec) -> Result< pub unsafe extern "system" fn Java_org_apache_opendal_Operator_stat( mut env: JNIEnv, _: JClass, - op: *mut Operator, - executor: *const Executor, - path: JString, -) -> jlong { - intern_stat(&mut env, op, executor, path).unwrap_or_else(|e| { - e.throw(&mut env); - 0 - }) -} - -fn intern_stat( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - - let path = jstring_to_string(env, &path)?; - - executor_or_default(env, executor)?.spawn(async move { - let result = do_stat(op, path).await; - complete_future(id, result.map(JValueOwned::Object)) - }); - - Ok(id) -} - -async fn do_stat<'local>(op: &mut Operator, path: String) -> Result> { - let metadata = op.stat(&path).await?; - let mut env = unsafe { get_current_env() }; - make_metadata(&mut env, metadata) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_read( - mut env: JNIEnv, - _: JClass, - op: *mut Operator, - executor: *const Executor, + op: *mut BlockingOperator, path: JString, -) -> jlong { - intern_read(&mut env, op, executor, path).unwrap_or_else(|e| { +) -> jobject { + intern_stat(&mut env, &mut *op, path).unwrap_or_else(|e| { e.throw(&mut env); - 0 + JObject::default().into_raw() }) } -fn intern_read( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +fn intern_stat(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { let path = jstring_to_string(env, &path)?; - - executor_or_default(env, executor)?.spawn(async move { - let result = do_read(op, path).await; - complete_future(id, result.map(JValueOwned::Object)) - }); - - Ok(id) -} - -async fn do_read<'local>(op: &mut Operator, path: String) -> Result> { - let content = op.read(&path).await?.to_bytes(); - - let env = unsafe { get_current_env() }; - let result = env.byte_array_from_slice(&content)?; - Ok(result.into()) + let metadata = op.stat(&path)?; + Ok(make_metadata(env, metadata)?.into_raw()) } /// # Safety @@ -276,70 +137,17 @@ async fn do_read<'local>(op: &mut Operator, path: String) -> Result jlong { - intern_delete(&mut env, op, executor, path).unwrap_or_else(|e| { +) { + intern_delete(&mut env, &mut *op, path).unwrap_or_else(|e| { e.throw(&mut env); - 0 }) } -fn intern_delete( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +fn intern_delete(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { let path = jstring_to_string(env, &path)?; - - executor_or_default(env, executor)?.spawn(async move { - let result = do_delete(op, path).await; - complete_future(id, result.map(|_| JValueOwned::Void)) - }); - - Ok(id) -} - -async fn do_delete(op: &mut Operator, path: String) -> Result<()> { - Ok(op.delete(&path).await?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_makeBlockingOp( - _: JNIEnv, - _: JClass, - op: *mut Operator, -) -> jlong { - let op = unsafe { &mut *op }; - Box::into_raw(Box::new(op.blocking())) as jlong -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_makeOperatorInfo( - mut env: JNIEnv, - _: JClass, - op: *mut Operator, -) -> jobject { - intern_make_operator_info(&mut env, op).unwrap_or_else(|e| { - e.throw(&mut env); - JObject::default().into_raw() - }) -} - -fn intern_make_operator_info(env: &mut JNIEnv, op: *mut Operator) -> Result { - let op = unsafe { &mut *op }; - Ok(make_operator_info(env, op.info())?.into_raw()) + Ok(op.delete(&path)?) } /// # Safety @@ -349,37 +157,17 @@ fn intern_make_operator_info(env: &mut JNIEnv, op: *mut Operator) -> Result jlong { - intern_create_dir(&mut env, op, executor, path).unwrap_or_else(|e| { +) { + intern_create_dir(&mut env, &mut *op, path).unwrap_or_else(|e| { e.throw(&mut env); - 0 }) } -fn intern_create_dir( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +fn intern_create_dir(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { let path = jstring_to_string(env, &path)?; - - executor_or_default(env, executor)?.spawn(async move { - let result = do_create_dir(op, path).await; - complete_future(id, result.map(|_| JValueOwned::Void)) - }); - - Ok(id) -} - -async fn do_create_dir(op: &mut Operator, path: String) -> Result<()> { - Ok(op.create_dir(&path).await?) + Ok(op.create_dir(&path)?) } /// # Safety @@ -389,40 +177,25 @@ async fn do_create_dir(op: &mut Operator, path: String) -> Result<()> { pub unsafe extern "system" fn Java_org_apache_opendal_Operator_copy( mut env: JNIEnv, _: JClass, - op: *mut Operator, - executor: *const Executor, + op: *mut BlockingOperator, source_path: JString, target_path: JString, -) -> jlong { - intern_copy(&mut env, op, executor, source_path, target_path).unwrap_or_else(|e| { +) { + intern_copy(&mut env, &mut *op, source_path, target_path).unwrap_or_else(|e| { e.throw(&mut env); - 0 }) } fn intern_copy( env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, + op: &mut BlockingOperator, source_path: JString, target_path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +) -> Result<()> { let source_path = jstring_to_string(env, &source_path)?; let target_path = jstring_to_string(env, &target_path)?; - executor_or_default(env, executor)?.spawn(async move { - let result = do_copy(op, source_path, target_path).await; - complete_future(id, result.map(|_| JValueOwned::Void)) - }); - - Ok(id) -} - -async fn do_copy(op: &mut Operator, source_path: String, target_path: String) -> Result<()> { - Ok(op.copy(&source_path, &target_path).await?) + Ok(op.copy(&source_path, &target_path)?) } /// # Safety @@ -432,40 +205,25 @@ async fn do_copy(op: &mut Operator, source_path: String, target_path: String) -> pub unsafe extern "system" fn Java_org_apache_opendal_Operator_rename( mut env: JNIEnv, _: JClass, - op: *mut Operator, - executor: *const Executor, + op: *mut BlockingOperator, source_path: JString, target_path: JString, -) -> jlong { - intern_rename(&mut env, op, executor, source_path, target_path).unwrap_or_else(|e| { +) { + intern_rename(&mut env, &mut *op, source_path, target_path).unwrap_or_else(|e| { e.throw(&mut env); - 0 }) } fn intern_rename( env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, + op: &mut BlockingOperator, source_path: JString, target_path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +) -> Result<()> { let source_path = jstring_to_string(env, &source_path)?; let target_path = jstring_to_string(env, &target_path)?; - executor_or_default(env, executor)?.spawn(async move { - let result = do_rename(op, source_path, target_path).await; - complete_future(id, result.map(|_| JValueOwned::Void)) - }); - - Ok(id) -} - -async fn do_rename(op: &mut Operator, source_path: String, target_path: String) -> Result<()> { - Ok(op.rename(&source_path, &target_path).await?) + Ok(op.rename(&source_path, &target_path)?) } /// # Safety @@ -475,37 +233,18 @@ async fn do_rename(op: &mut Operator, source_path: String, target_path: String) pub unsafe extern "system" fn Java_org_apache_opendal_Operator_removeAll( mut env: JNIEnv, _: JClass, - op: *mut Operator, - executor: *const Executor, + op: *mut BlockingOperator, path: JString, -) -> jlong { - intern_remove_all(&mut env, op, executor, path).unwrap_or_else(|e| { +) { + intern_remove_all(&mut env, &mut *op, path).unwrap_or_else(|e| { e.throw(&mut env); - 0 }) } -fn intern_remove_all( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +fn intern_remove_all(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { let path = jstring_to_string(env, &path)?; - executor_or_default(env, executor)?.spawn(async move { - let result = do_remove_all(op, path).await; - complete_future(id, result.map(|_| JValueOwned::Void)) - }); - - Ok(id) -} - -async fn do_remove_all(op: &mut Operator, path: String) -> Result<()> { - Ok(op.remove_all(&path).await?) + Ok(op.remove_all(&path)?) } /// # Safety @@ -515,39 +254,19 @@ async fn do_remove_all(op: &mut Operator, path: String) -> Result<()> { pub unsafe extern "system" fn Java_org_apache_opendal_Operator_list( mut env: JNIEnv, _: JClass, - op: *mut Operator, - executor: *const Executor, + op: *mut BlockingOperator, path: JString, -) -> jlong { - intern_list(&mut env, op, executor, path).unwrap_or_else(|e| { +) -> jobjectArray { + intern_list(&mut env, &mut *op, path).unwrap_or_else(|e| { e.throw(&mut env); - 0 + JObject::default().into_raw() }) } -fn intern_list( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - +fn intern_list(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { let path = jstring_to_string(env, &path)?; + let obs = op.list(&path)?; - executor_or_default(env, executor)?.spawn(async move { - let result = do_list(op, path).await; - complete_future(id, result.map(JValueOwned::Object)) - }); - - Ok(id) -} - -async fn do_list<'local>(op: &mut Operator, path: String) -> Result> { - let obs = op.list(&path).await?; - - let mut env = unsafe { get_current_env() }; let jarray = env.new_object_array( obs.len() as jsize, "org/apache/opendal/Entry", @@ -555,227 +274,9 @@ async fn do_list<'local>(op: &mut Operator, path: String) -> Result jlong { - intern_presign_read(&mut env, op, executor, path, expire).unwrap_or_else(|e| { - e.throw(&mut env); - 0 - }) -} - -fn intern_presign_read( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, - expire: jlong, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - - let path = jstring_to_string(env, &path)?; - let expire = Duration::from_nanos(expire as u64); - - executor_or_default(env, executor)?.spawn(async move { - let result = do_presign_read(op, path, expire).await; - let mut env = unsafe { get_current_env() }; - let result = result.and_then(|req| make_presigned_request(&mut env, req)); - complete_future(id, result.map(JValueOwned::Object)) - }); - - Ok(id) -} - -async fn do_presign_read( - op: &mut Operator, - path: String, - expire: Duration, -) -> Result { - Ok(op.presign_read(&path, expire).await?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_presignWrite( - mut env: JNIEnv, - _: JClass, - op: *mut Operator, - executor: *const Executor, - path: JString, - expire: jlong, -) -> jlong { - intern_presign_write(&mut env, op, executor, path, expire).unwrap_or_else(|e| { - e.throw(&mut env); - 0 - }) -} - -fn intern_presign_write( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, - expire: jlong, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - - let path = jstring_to_string(env, &path)?; - let expire = Duration::from_nanos(expire as u64); - - executor_or_default(env, executor)?.spawn(async move { - let result = do_presign_write(op, path, expire).await; - let mut env = unsafe { get_current_env() }; - let result = result.and_then(|req| make_presigned_request(&mut env, req)); - complete_future(id, result.map(JValueOwned::Object)) - }); - - Ok(id) -} - -async fn do_presign_write( - op: &mut Operator, - path: String, - expire: Duration, -) -> Result { - Ok(op.presign_write(&path, expire).await?) -} - -/// # Safety -/// -/// This function should not be called before the Operator is ready. -#[no_mangle] -pub unsafe extern "system" fn Java_org_apache_opendal_Operator_presignStat( - mut env: JNIEnv, - _: JClass, - op: *mut Operator, - executor: *const Executor, - path: JString, - expire: jlong, -) -> jlong { - intern_presign_stat(&mut env, op, executor, path, expire).unwrap_or_else(|e| { - e.throw(&mut env); - 0 - }) -} - -fn intern_presign_stat( - env: &mut JNIEnv, - op: *mut Operator, - executor: *const Executor, - path: JString, - expire: jlong, -) -> Result { - let op = unsafe { &mut *op }; - let id = request_id(env)?; - - let path = jstring_to_string(env, &path)?; - let expire = Duration::from_nanos(expire as u64); - - executor_or_default(env, executor)?.spawn(async move { - let result = do_presign_stat(op, path, expire).await; - let mut env = unsafe { get_current_env() }; - let result = result.and_then(|req| make_presigned_request(&mut env, req)); - complete_future(id, result.map(JValueOwned::Object)) - }); - - Ok(id) -} - -async fn do_presign_stat( - op: &mut Operator, - path: String, - expire: Duration, -) -> Result { - Ok(op.presign_stat(&path, expire).await?) -} - -fn make_object<'local>( - env: &mut JNIEnv<'local>, - value: JValueOwned<'local>, -) -> Result> { - let o = match value { - JValueOwned::Object(o) => o, - JValueOwned::Byte(_) => env.new_object("java/lang/Long", "(B)V", &[value.borrow()])?, - JValueOwned::Char(_) => env.new_object("java/lang/Char", "(C)V", &[value.borrow()])?, - JValueOwned::Short(_) => env.new_object("java/lang/Short", "(S)V", &[value.borrow()])?, - JValueOwned::Int(_) => env.new_object("java/lang/Integer", "(I)V", &[value.borrow()])?, - JValueOwned::Long(_) => env.new_object("java/lang/Long", "(J)V", &[value.borrow()])?, - JValueOwned::Bool(_) => env.new_object("java/lang/Boolean", "(Z)V", &[value.borrow()])?, - JValueOwned::Float(_) => env.new_object("java/lang/Float", "(F)V", &[value.borrow()])?, - JValueOwned::Double(_) => env.new_object("java/lang/Double", "(D)V", &[value.borrow()])?, - JValueOwned::Void => JObject::null(), - }; - Ok(o) -} - -fn complete_future(id: jlong, result: Result) { - try_complete_future(id, result).expect("complete future must succeed"); -} - -fn try_complete_future(id: jlong, result: Result) -> Result<()> { - let mut env = unsafe { get_current_env() }; - let future = get_future(&mut env, id)?; - match result { - Ok(result) => { - let result = make_object(&mut env, result)?; - env.call_method( - future, - "complete", - "(Ljava/lang/Object;)Z", - &[JValue::Object(&result)], - )? - } - Err(err) => { - let exception = err.to_exception(&mut env)?; - env.call_method( - future, - "completeExceptionally", - "(Ljava/lang/Throwable;)Z", - &[JValue::Object(&exception)], - )? - } - }; - Ok(()) -} - -fn request_id(env: &mut JNIEnv) -> Result { - Ok(env - .call_static_method( - "org/apache/opendal/Operator$AsyncRegistry", - "requestId", - "()J", - &[], - )? - .j()?) -} - -fn get_future<'local>(env: &mut JNIEnv<'local>, id: jlong) -> Result> { - Ok(env - .call_static_method( - "org/apache/opendal/Operator$AsyncRegistry", - "get", - "(J)Ljava/util/concurrent/CompletableFuture;", - &[JValue::Long(id)], - )? - .l()?) + Ok(jarray.into_raw()) } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/AsyncExecutorTest.java b/bindings/java/src/test/java/org/apache/opendal/test/AsyncExecutorTest.java index 6b797435d30..c776e8b754a 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/AsyncExecutorTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/AsyncExecutorTest.java @@ -25,7 +25,7 @@ import java.util.Map; import lombok.Cleanup; import org.apache.opendal.AsyncExecutor; -import org.apache.opendal.Operator; +import org.apache.opendal.AsyncOperator; import org.junit.jupiter.api.Test; public class AsyncExecutorTest { @@ -35,7 +35,7 @@ void testDedicatedTokioExecutor() { conf.put("root", "/opendal/"); final int cores = Runtime.getRuntime().availableProcessors(); @Cleanup final AsyncExecutor executor = AsyncExecutor.createTokioExecutor(cores); - @Cleanup final Operator op = Operator.of("memory", conf, executor); + @Cleanup final AsyncOperator op = AsyncOperator.of("memory", conf, executor); assertThat(op.info).isNotNull(); final String key = "key"; diff --git a/bindings/java/src/test/java/org/apache/opendal/test/LayerTest.java b/bindings/java/src/test/java/org/apache/opendal/test/LayerTest.java index e99e0b25718..0300bb14199 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/LayerTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/LayerTest.java @@ -23,8 +23,8 @@ import java.util.HashMap; import java.util.Map; import lombok.Cleanup; +import org.apache.opendal.AsyncOperator; import org.apache.opendal.Layer; -import org.apache.opendal.Operator; import org.apache.opendal.layer.RetryLayer; import org.junit.jupiter.api.Test; @@ -34,8 +34,8 @@ void testOperatorWithRetryLayer() { final Map conf = new HashMap<>(); conf.put("root", "/opendal/"); final Layer retryLayer = RetryLayer.builder().build(); - @Cleanup final Operator op = Operator.of("memory", conf); - @Cleanup final Operator layeredOp = op.layer(retryLayer); + @Cleanup final AsyncOperator op = AsyncOperator.of("memory", conf); + @Cleanup final AsyncOperator layeredOp = op.layer(retryLayer); assertThat(layeredOp.info).isNotNull(); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/MetadataTest.java b/bindings/java/src/test/java/org/apache/opendal/test/MetadataTest.java index ae846444d6b..821390a12c4 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/MetadataTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/MetadataTest.java @@ -26,7 +26,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import org.apache.opendal.BlockingOperator; +import org.apache.opendal.AsyncOperator; import org.apache.opendal.Metadata; import org.apache.opendal.Operator; import org.junit.jupiter.api.Test; @@ -41,7 +41,7 @@ public void testAsyncMetadata() { final Map conf = new HashMap<>(); conf.put("root", tempDir.toString()); - try (final Operator op = Operator.of("fs", conf)) { + try (final AsyncOperator op = AsyncOperator.of("fs", conf)) { final String dir = UUID.randomUUID() + "/"; op.createDir(dir).join(); final Metadata dirMetadata = op.stat(dir).join(); @@ -72,7 +72,7 @@ public void testBlockingMetadata() { final Map conf = new HashMap<>(); conf.put("root", tempDir.toString()); - try (final BlockingOperator op = BlockingOperator.of("fs", conf)) { + try (final Operator op = Operator.of("fs", conf)) { final String dir = UUID.randomUUID() + "/"; op.createDir(dir); final Metadata dirMetadata = op.stat(dir); diff --git a/bindings/java/src/test/java/org/apache/opendal/test/OperatorDuplicateTest.java b/bindings/java/src/test/java/org/apache/opendal/test/OperatorDuplicateTest.java index d4af7bde619..65bbf722dd4 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/OperatorDuplicateTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/OperatorDuplicateTest.java @@ -23,7 +23,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -import org.apache.opendal.BlockingOperator; +import org.apache.opendal.AsyncOperator; import org.apache.opendal.Operator; import org.junit.jupiter.api.Test; @@ -32,12 +32,12 @@ public class OperatorDuplicateTest { public void testDuplicateOperator() { final Map conf = new HashMap<>(); conf.put("root", "/opendal/"); - try (final Operator op = Operator.of("memory", conf)) { + try (final AsyncOperator op = AsyncOperator.of("memory", conf)) { final String key = "key"; final byte[] v0 = "v0".getBytes(StandardCharsets.UTF_8); final byte[] v1 = "v1".getBytes(StandardCharsets.UTF_8); - try (final Operator duplicatedOp = op.duplicate()) { + try (final AsyncOperator duplicatedOp = op.duplicate()) { assertThat(duplicatedOp.info).isNotNull(); assertThat(duplicatedOp.info).isEqualTo(op.info); duplicatedOp.write(key, v0).join(); @@ -54,12 +54,12 @@ public void testDuplicateOperator() { public void testDuplicateBlockingOperator() { final Map conf = new HashMap<>(); conf.put("root", "/opendal/"); - try (final BlockingOperator op = BlockingOperator.of("memory", conf)) { + try (final Operator op = Operator.of("memory", conf)) { final String key = "key"; final byte[] v0 = "v0".getBytes(StandardCharsets.UTF_8); final byte[] v1 = "v1".getBytes(StandardCharsets.UTF_8); - try (final BlockingOperator duplicatedOp = op.duplicate()) { + try (final Operator duplicatedOp = op.duplicate()) { assertThat(duplicatedOp.info).isNotNull(); assertThat(duplicatedOp.info).isEqualTo(op.info); duplicatedOp.write(key, v0); diff --git a/bindings/java/src/test/java/org/apache/opendal/test/OperatorInfoTest.java b/bindings/java/src/test/java/org/apache/opendal/test/OperatorInfoTest.java index 2a773fc0672..dc3174cc74c 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/OperatorInfoTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/OperatorInfoTest.java @@ -23,7 +23,7 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import org.apache.opendal.BlockingOperator; +import org.apache.opendal.AsyncOperator; import org.apache.opendal.Operator; import org.apache.opendal.OperatorInfo; import org.junit.jupiter.api.Test; @@ -38,7 +38,7 @@ public void testBlockingOperatorInfo() { final Map conf = new HashMap<>(); conf.put("root", tempDir.toString()); - try (final BlockingOperator op = BlockingOperator.of("fs", conf)) { + try (final Operator op = Operator.of("fs", conf)) { final OperatorInfo info = op.info; assertThat(info).isNotNull(); assertThat(info.scheme).isEqualTo("fs"); @@ -61,7 +61,7 @@ public void testBlockingOperatorInfo() { public void testOperatorInfo() { final Map conf = new HashMap<>(); conf.put("root", "/opendal/"); - try (final Operator op = Operator.of("memory", conf)) { + try (final AsyncOperator op = AsyncOperator.of("memory", conf)) { final OperatorInfo info = op.info; assertThat(info).isNotNull(); assertThat(info.scheme).isEqualTo("memory"); diff --git a/bindings/java/src/test/java/org/apache/opendal/test/OperatorInputOutputStreamTest.java b/bindings/java/src/test/java/org/apache/opendal/test/OperatorInputOutputStreamTest.java index 8cacbe57fff..13de860caf9 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/OperatorInputOutputStreamTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/OperatorInputOutputStreamTest.java @@ -27,7 +27,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; -import org.apache.opendal.BlockingOperator; +import org.apache.opendal.Operator; import org.apache.opendal.OperatorInputStream; import org.apache.opendal.OperatorOutputStream; import org.junit.jupiter.api.Test; @@ -42,7 +42,7 @@ void testReadWriteWithStream() throws Exception { final Map conf = new HashMap<>(); conf.put("root", tempDir.toString()); - try (final BlockingOperator op = BlockingOperator.of("fs", conf)) { + try (final Operator op = Operator.of("fs", conf)) { final String path = "OperatorInputOutputStreamTest.txt"; final long multi = 1024 * 1024; diff --git a/bindings/java/src/test/java/org/apache/opendal/test/OperatorUtf8DecodeTest.java b/bindings/java/src/test/java/org/apache/opendal/test/OperatorUtf8DecodeTest.java index 692672b1a5b..3c7d6fbbfd1 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/OperatorUtf8DecodeTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/OperatorUtf8DecodeTest.java @@ -23,8 +23,8 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import org.apache.opendal.BlockingOperator; import org.apache.opendal.Metadata; +import org.apache.opendal.Operator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -42,7 +42,7 @@ public void testWriteFileWithNonAsciiName() { final Map conf = new HashMap<>(); conf.put("root", tempDir.toString()); - try (final BlockingOperator op = BlockingOperator.of("fs", conf)) { + try (final Operator op = Operator.of("fs", conf)) { final String path = "❌😱中文.test"; final byte[] content = "❌😱中文".getBytes(); op.write(path, content); diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncAppendTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncAppendTest.java index 681bf7c5ac0..f8d53ed88bc 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncAppendTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncAppendTest.java @@ -32,7 +32,7 @@ public class AsyncAppendTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.read && capability.write && capability.writeCanAppend); } @@ -42,15 +42,15 @@ public void testAppendCreateAppend() { final byte[] contentOne = generateBytes(); final byte[] contentTwo = generateBytes(); - op().append(path, contentOne).join(); - op().append(path, contentTwo).join(); + asyncOp().append(path, contentOne).join(); + asyncOp().append(path, contentTwo).join(); - final byte[] actualContent = op().read(path).join(); + final byte[] actualContent = asyncOp().read(path).join(); assertThat(actualContent.length).isEqualTo(contentOne.length + contentTwo.length); assertThat(Arrays.copyOfRange(actualContent, 0, contentOne.length)).isEqualTo(contentOne); assertThat(Arrays.copyOfRange(actualContent, contentOne.length, actualContent.length)) .isEqualTo(contentTwo); - op().delete(path).join(); + asyncOp().delete(path).join(); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCopyTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCopyTest.java index 5944c02ea94..27b046d2dab 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCopyTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCopyTest.java @@ -36,7 +36,7 @@ class AsyncCopyTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.read && capability.write && capability.copy && capability.createDir); } @@ -48,16 +48,16 @@ public void testCopyFileWithAsciiName() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - op().write(sourcePath, sourceContent).join(); + asyncOp().write(sourcePath, sourceContent).join(); final String targetPath = UUID.randomUUID().toString(); - op().copy(sourcePath, targetPath).join(); + asyncOp().copy(sourcePath, targetPath).join(); - Assertions.assertThat(op().read(targetPath).join()).isEqualTo(sourceContent); + Assertions.assertThat(asyncOp().read(targetPath).join()).isEqualTo(sourceContent); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } /** @@ -66,19 +66,19 @@ public void testCopyFileWithAsciiName() { @Test public void testCopyFileWithNonAsciiName() { // Services-koofr doesn't support non-ascii name (https://github.com/apache/opendal/issues/4051) - assumeTrue(!Objects.equals(op().info.scheme, "koofr"), "Services-koofr doesn't support non-ascii name"); + assumeTrue(!Objects.equals(asyncOp().info.scheme, "koofr"), "Services-koofr doesn't support non-ascii name"); final String sourcePath = "🐂🍺中文.docx"; final String targetPath = "😈🐅Français.docx"; final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); - op().copy(sourcePath, targetPath).join(); + asyncOp().write(sourcePath, content).join(); + asyncOp().copy(sourcePath, targetPath).join(); - Assertions.assertThat(op().read(targetPath).join()).isEqualTo(content); + Assertions.assertThat(asyncOp().read(targetPath).join()).isEqualTo(content); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } /** @@ -89,7 +89,7 @@ public void testCopyNonExistingSource() { final String sourcePath = UUID.randomUUID().toString(); final String targetPath = UUID.randomUUID().toString(); - assertThatThrownBy(() -> op().copy(sourcePath, targetPath).join()) + assertThatThrownBy(() -> asyncOp().copy(sourcePath, targetPath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); } @@ -101,7 +101,7 @@ public void testCopySourceDir() { final String sourcePath = UUID.randomUUID() + "/"; final String targetPath = UUID.randomUUID().toString(); - assertThatThrownBy(() -> op().copy(sourcePath, targetPath).join()) + assertThatThrownBy(() -> asyncOp().copy(sourcePath, targetPath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.IsADirectory)); } @@ -113,16 +113,16 @@ public void testCopyTargetDir() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); + asyncOp().write(sourcePath, content).join(); final String targetPath = UUID.randomUUID() + "/"; - op().createDir(targetPath).join(); + asyncOp().createDir(targetPath).join(); - assertThatThrownBy(() -> op().copy(sourcePath, targetPath).join()) + assertThatThrownBy(() -> asyncOp().copy(sourcePath, targetPath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.IsADirectory)); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } /** @@ -133,12 +133,12 @@ public void testCopySelf() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); + asyncOp().write(sourcePath, content).join(); - assertThatThrownBy(() -> op().copy(sourcePath, sourcePath).join()) + assertThatThrownBy(() -> asyncOp().copy(sourcePath, sourcePath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.IsSameFile)); - op().delete(sourcePath).join(); + asyncOp().delete(sourcePath).join(); } /** @@ -149,16 +149,16 @@ public void testCopyNested() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); + asyncOp().write(sourcePath, content).join(); final String targetPath = String.format("%s/%s/%s", UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()); - op().copy(sourcePath, targetPath).join(); + asyncOp().copy(sourcePath, targetPath).join(); - Assertions.assertThat(op().read(targetPath).join()).isEqualTo(content); + Assertions.assertThat(asyncOp().read(targetPath).join()).isEqualTo(content); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } /** @@ -169,19 +169,19 @@ public void testCopyOverwrite() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - op().write(sourcePath, sourceContent).join(); + asyncOp().write(sourcePath, sourceContent).join(); final String targetPath = UUID.randomUUID().toString(); final byte[] targetContent = generateBytes(); assertNotEquals(sourceContent, targetContent); - op().write(targetPath, targetContent).join(); + asyncOp().write(targetPath, targetContent).join(); - op().copy(sourcePath, targetPath).join(); + asyncOp().copy(sourcePath, targetPath).join(); - Assertions.assertThat(op().read(targetPath).join()).isEqualTo(sourceContent); + Assertions.assertThat(asyncOp().read(targetPath).join()).isEqualTo(sourceContent); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCreateDirTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCreateDirTest.java index 6c81bd3a5e6..6ac95cc9486 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCreateDirTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncCreateDirTest.java @@ -32,7 +32,7 @@ class AsyncCreateDirTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.createDir); } @@ -42,12 +42,12 @@ public void precondition() { @Test public void testCreateDir() { final String path = UUID.randomUUID() + "/"; - op().createDir(path).join(); + asyncOp().createDir(path).join(); - final Metadata meta = op().stat(path).join(); + final Metadata meta = asyncOp().stat(path).join(); assertThat(meta.isFile()).isFalse(); - op().delete(path).join(); + asyncOp().delete(path).join(); } /** @@ -56,12 +56,12 @@ public void testCreateDir() { @Test public void testCreateDirExisting() { final String path = UUID.randomUUID() + "/"; - op().createDir(path).join(); - op().createDir(path).join(); + asyncOp().createDir(path).join(); + asyncOp().createDir(path).join(); - final Metadata meta = op().stat(path).join(); + final Metadata meta = asyncOp().stat(path).join(); assertThat(meta.isFile()).isFalse(); - op().delete(path).join(); + asyncOp().delete(path).join(); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncListTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncListTest.java index 9ffe1f3b347..286d93a3877 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncListTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncListTest.java @@ -42,7 +42,7 @@ class AsyncListTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.read && capability.write && capability.list && capability.createDir); } @@ -55,13 +55,13 @@ public void testListDir() { final String path = String.format("%s/%s", parent, UUID.randomUUID()); final byte[] content = generateBytes(); - op().write(path, content).join(); + asyncOp().write(path, content).join(); - final List entries = op().list(parent + "/").join(); + final List entries = asyncOp().list(parent + "/").join(); boolean found = false; for (Entry entry : entries) { if (entry.getPath().equals(path)) { - Metadata meta = op().stat(path).join(); + Metadata meta = asyncOp().stat(path).join(); assertTrue(meta.isFile()); assertThat(meta.getContentLength()).isEqualTo(content.length); @@ -69,7 +69,7 @@ public void testListDir() { } } assertTrue(found); - op().delete(path).join(); + asyncOp().delete(path).join(); } /** @@ -78,23 +78,23 @@ public void testListDir() { @Test public void testListRichDir() { final String parent = "test_list_rich_dir"; - op().createDir(parent + "/").join(); + asyncOp().createDir(parent + "/").join(); final List expected = new ArrayList<>(); for (int i = 0; i < 10; i++) { expected.add(String.format("%s/file-%d", parent, i)); } for (String path : expected) { - op().write(path, parent).join(); + asyncOp().write(path, parent).join(); } - final List entries = op().list(parent + "/").join(); + final List entries = asyncOp().list(parent + "/").join(); final List actual = entries.stream().map(Entry::getPath).sorted().collect(Collectors.toList()); Collections.sort(expected); assertThat(actual).isEqualTo(expected); - op().removeAll(parent + "/").join(); + asyncOp().removeAll(parent + "/").join(); } /** @@ -103,12 +103,12 @@ public void testListRichDir() { @Test public void testListEmptyDir() { final String dir = String.format("%s/", UUID.randomUUID()); - op().createDir(dir).join(); + asyncOp().createDir(dir).join(); - final List entries = op().list(dir).join(); + final List entries = asyncOp().list(dir).join(); assertThat(entries).isEmpty(); - op().delete(dir).join(); + asyncOp().delete(dir).join(); } /** @@ -118,7 +118,7 @@ public void testListEmptyDir() { public void testListNotExistDir() { final String dir = String.format("%s/", UUID.randomUUID()); - final List entries = op().list(dir).join(); + final List entries = asyncOp().list(dir).join(); assertThat(entries).isEmpty(); } @@ -128,9 +128,9 @@ public void testListNotExistDir() { @Test public void testListSubDir() { final String path = String.format("%s/", UUID.randomUUID()); - op().createDir(path).join(); + asyncOp().createDir(path).join(); - final List entries = op().list("/").join(); + final List entries = asyncOp().list("/").join(); boolean found = false; for (Entry entry : entries) { if (entry.getPath().equals(path)) { @@ -141,7 +141,7 @@ public void testListSubDir() { } assertTrue(found); - op().delete(path).join(); + asyncOp().delete(path).join(); } /** @@ -156,11 +156,11 @@ public void testListNestedDir() { final String dirPath = String.format("%s/%s", dir, dirName); final String content = "test_list_nested_dir"; - op().createDir(dir).join(); - op().write(filePath, content).join(); - op().createDir(dirPath).join(); + asyncOp().createDir(dir).join(); + asyncOp().write(filePath, content).join(); + asyncOp().createDir(dirPath).join(); - final List entries = op().list(dir).join(); + final List entries = asyncOp().list(dir).join(); assertThat(entries).hasSize(2); for (Entry entry : entries) { @@ -176,7 +176,7 @@ public void testListNestedDir() { } } - op().removeAll(dir).join(); + asyncOp().removeAll(dir).join(); } /** @@ -190,23 +190,25 @@ public void testRemoveAll() { }; for (String path : expected) { if (path.endsWith("/")) { - op().createDir(String.format("%s/%s", parent, path)).join(); + asyncOp().createDir(String.format("%s/%s", parent, path)).join(); } else { - op().write(String.format("%s/%s", parent, path), "test_scan").join(); + asyncOp() + .write(String.format("%s/%s", parent, path), "test_scan") + .join(); } } - op().removeAll(parent + "/x/").join(); + asyncOp().removeAll(parent + "/x/").join(); for (String path : expected) { if (path.endsWith("/")) { continue; } assertThatThrownBy(() -> - op().stat(String.format("%s/%s", parent, path)).join()) + asyncOp().stat(String.format("%s/%s", parent, path)).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); } - op().removeAll(parent + "/").join(); + asyncOp().removeAll(parent + "/").join(); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncPresignTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncPresignTest.java index 05b129b5901..10578547138 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncPresignTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncPresignTest.java @@ -47,7 +47,7 @@ public class AsyncPresignTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.list && capability.write && capability.presign); } @@ -60,7 +60,7 @@ public void testPresignWrite() throws IOException { final byte[] content = generateBytes(); final PresignedRequest signedReq = - op().presignWrite(path, Duration.ofSeconds(3600)).join(); + asyncOp().presignWrite(path, Duration.ofSeconds(3600)).join(); try (CloseableHttpClient httpclient = HttpClients.createDefault()) { final ClassicRequestBuilder builder = @@ -69,10 +69,10 @@ public void testPresignWrite() throws IOException { httpclient.execute(builder.build(), rsp -> rsp); } - final Metadata meta = op().stat(path).join(); + final Metadata meta = asyncOp().stat(path).join(); assertEquals(content.length, meta.getContentLength()); - op().delete(path).join(); + asyncOp().delete(path).join(); } /** @@ -82,10 +82,10 @@ public void testPresignWrite() throws IOException { public void testPresignStat() throws IOException { final String path = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(path, content).join(); + asyncOp().write(path, content).join(); final PresignedRequest signedReq = - op().presignStat(path, Duration.ofSeconds(3600)).join(); + asyncOp().presignStat(path, Duration.ofSeconds(3600)).join(); try (CloseableHttpClient httpclient = HttpClients.createDefault()) { final ClassicRequestBuilder builder = createRequestBuilder(signedReq); @@ -96,7 +96,7 @@ public void testPresignStat() throws IOException { response.getFirstHeader(HttpHeaders.CONTENT_LENGTH).getValue()); } - op().delete(path).join(); + asyncOp().delete(path).join(); } /** @@ -106,10 +106,10 @@ public void testPresignStat() throws IOException { public void testPresignRead() throws IOException, NoSuchAlgorithmException { final String path = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(path, content).join(); + asyncOp().write(path, content).join(); final PresignedRequest signedReq = - op().presignRead(path, Duration.ofSeconds(3600)).join(); + asyncOp().presignRead(path, Duration.ofSeconds(3600)).join(); try (CloseableHttpClient httpclient = HttpClients.createDefault()) { final ClassicRequestBuilder builder = createRequestBuilder(signedReq); @@ -122,7 +122,7 @@ public void testPresignRead() throws IOException, NoSuchAlgorithmException { assertArrayEquals(digest.digest(content), digest.digest(responseContent)); } - op().delete(path).join(); + asyncOp().delete(path).join(); } private ClassicRequestBuilder createRequestBuilder(final PresignedRequest signedReq) { diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncReadOnlyTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncReadOnlyTest.java index c14c40ee8dd..3eba26cc4d9 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncReadOnlyTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncReadOnlyTest.java @@ -45,7 +45,7 @@ public class AsyncReadOnlyTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.read && !capability.write); } @@ -54,11 +54,11 @@ public void precondition() { */ @Test public void testReadOnlyStatFileAndDir() { - final Metadata fileMeta = op().stat(NORMAL_FILE_NAME).join(); + final Metadata fileMeta = asyncOp().stat(NORMAL_FILE_NAME).join(); assertTrue(fileMeta.isFile()); assertEquals(FILE_LENGTH, fileMeta.getContentLength()); - final Metadata dirMeta = op().stat(NORMAL_DIR_NAME).join(); + final Metadata dirMeta = asyncOp().stat(NORMAL_DIR_NAME).join(); assertTrue(dirMeta.isDir()); } @@ -67,11 +67,11 @@ public void testReadOnlyStatFileAndDir() { */ @Test public void testReadOnlyStatSpecialChars() { - final Metadata fileMeta = op().stat(SPECIAL_FILE_NAME).join(); + final Metadata fileMeta = asyncOp().stat(SPECIAL_FILE_NAME).join(); assertTrue(fileMeta.isFile()); assertEquals(FILE_LENGTH, fileMeta.getContentLength()); - final Metadata dirMeta = op().stat(SPECIAL_DIR_NAME).join(); + final Metadata dirMeta = asyncOp().stat(SPECIAL_DIR_NAME).join(); assertTrue(dirMeta.isDir()); } @@ -80,7 +80,7 @@ public void testReadOnlyStatSpecialChars() { */ @Test public void testReadOnlyStatNotCleanedPath() { - final Metadata fileMeta = op().stat("//" + NORMAL_FILE_NAME).join(); + final Metadata fileMeta = asyncOp().stat("//" + NORMAL_FILE_NAME).join(); assertTrue(fileMeta.isFile()); assertEquals(FILE_LENGTH, fileMeta.getContentLength()); } @@ -92,7 +92,7 @@ public void testReadOnlyStatNotCleanedPath() { public void testReadOnlyStatNotExist() { final String path = UUID.randomUUID().toString(); - assertThatThrownBy(() -> op().stat(path).join()) + assertThatThrownBy(() -> asyncOp().stat(path).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); } @@ -101,10 +101,10 @@ public void testReadOnlyStatNotExist() { */ @Test public void testReadOnlyStatRoot() { - final Metadata meta1 = op().stat("").join(); + final Metadata meta1 = asyncOp().stat("").join(); assertTrue(meta1.isDir()); - final Metadata meta2 = op().stat("/").join(); + final Metadata meta2 = asyncOp().stat("/").join(); assertTrue(meta2.isDir()); } @@ -113,7 +113,7 @@ public void testReadOnlyStatRoot() { */ @Test public void testReadOnlyReadFull() throws NoSuchAlgorithmException { - final byte[] content = op().read(NORMAL_FILE_NAME).join(); + final byte[] content = asyncOp().read(NORMAL_FILE_NAME).join(); assertEquals(FILE_LENGTH, content.length); assertEquals(FILE_SHA256_DIGEST, sha256Digest(content)); @@ -124,7 +124,7 @@ public void testReadOnlyReadFull() throws NoSuchAlgorithmException { */ @Test public void testReadOnlyReadFullWithSpecialChars() throws NoSuchAlgorithmException { - final byte[] content = op().read(SPECIAL_FILE_NAME).join(); + final byte[] content = asyncOp().read(SPECIAL_FILE_NAME).join(); assertEquals(FILE_LENGTH, content.length); assertEquals(FILE_SHA256_DIGEST, sha256Digest(content)); @@ -137,7 +137,7 @@ public void testReadOnlyReadFullWithSpecialChars() throws NoSuchAlgorithmExcepti public void testReadOnlyReadNotExist() { final String path = UUID.randomUUID().toString(); - assertThatThrownBy(() -> op().read(path).join()) + assertThatThrownBy(() -> asyncOp().read(path).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); } @@ -148,7 +148,7 @@ public void testReadOnlyReadNotExist() { public void testReadOnlyReadWithDirPath() { final String path = UUID.randomUUID().toString() + "/"; - assertThatThrownBy(() -> op().read(path).join()) + assertThatThrownBy(() -> asyncOp().read(path).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.IsADirectory)); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncRenameTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncRenameTest.java index a4d20e6d30d..b074c0a04d1 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncRenameTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncRenameTest.java @@ -35,7 +35,7 @@ class AsyncRenameTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.read && capability.write && capability.rename && capability.createDir); } @@ -47,19 +47,19 @@ public void testRenameFile() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); + asyncOp().write(sourcePath, content).join(); final String targetPath = UUID.randomUUID().toString(); - op().rename(sourcePath, targetPath).join(); + asyncOp().rename(sourcePath, targetPath).join(); - assertThatThrownBy(() -> op().stat(sourcePath).join()) + assertThatThrownBy(() -> asyncOp().stat(sourcePath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); - Assertions.assertThat(op().read(targetPath).join()).isEqualTo(content); + Assertions.assertThat(asyncOp().read(targetPath).join()).isEqualTo(content); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } /** @@ -70,7 +70,7 @@ public void testRenameNonExistingSource() { final String sourcePath = UUID.randomUUID().toString(); final String targetPath = UUID.randomUUID().toString(); - assertThatThrownBy(() -> op().rename(sourcePath, targetPath).join()) + assertThatThrownBy(() -> asyncOp().rename(sourcePath, targetPath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); } @@ -82,12 +82,12 @@ public void testRenameSourceDir() { final String sourcePath = UUID.randomUUID() + "/"; final String targetPath = UUID.randomUUID().toString(); - op().createDir(sourcePath).join(); + asyncOp().createDir(sourcePath).join(); - assertThatThrownBy(() -> op().rename(sourcePath, targetPath).join()) + assertThatThrownBy(() -> asyncOp().rename(sourcePath, targetPath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.IsADirectory)); - op().delete(sourcePath).join(); + asyncOp().delete(sourcePath).join(); } /** @@ -98,17 +98,17 @@ public void testRenameTargetDir() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); + asyncOp().write(sourcePath, content).join(); final String targetPath = UUID.randomUUID() + "/"; - op().createDir(targetPath).join(); + asyncOp().createDir(targetPath).join(); - assertThatThrownBy(() -> op().rename(sourcePath, targetPath).join()) + assertThatThrownBy(() -> asyncOp().rename(sourcePath, targetPath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.IsADirectory)); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } /** @@ -119,12 +119,12 @@ public void testRenameSelf() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); + asyncOp().write(sourcePath, content).join(); - assertThatThrownBy(() -> op().rename(sourcePath, sourcePath).join()) + assertThatThrownBy(() -> asyncOp().rename(sourcePath, sourcePath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.IsSameFile)); - op().delete(sourcePath).join(); + asyncOp().delete(sourcePath).join(); } /** @@ -135,19 +135,19 @@ public void testRenameNested() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(sourcePath, content).join(); + asyncOp().write(sourcePath, content).join(); final String targetPath = String.format("%s/%s/%s", UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()); - op().rename(sourcePath, targetPath).join(); + asyncOp().rename(sourcePath, targetPath).join(); - assertThatThrownBy(() -> op().stat(sourcePath).join()) + assertThatThrownBy(() -> asyncOp().stat(sourcePath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); - Assertions.assertThat(op().read(targetPath).join()).isEqualTo(content); + Assertions.assertThat(asyncOp().read(targetPath).join()).isEqualTo(content); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } /** @@ -158,22 +158,22 @@ public void testRenameOverwrite() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - op().write(sourcePath, sourceContent).join(); + asyncOp().write(sourcePath, sourceContent).join(); final String targetPath = UUID.randomUUID().toString(); final byte[] targetContent = generateBytes(); assertNotEquals(sourceContent, targetContent); - op().write(targetPath, targetContent).join(); + asyncOp().write(targetPath, targetContent).join(); - op().rename(sourcePath, targetPath).join(); + asyncOp().rename(sourcePath, targetPath).join(); - assertThatThrownBy(() -> op().stat(sourcePath).join()) + assertThatThrownBy(() -> asyncOp().stat(sourcePath).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); - Assertions.assertThat(op().read(targetPath).join()).isEqualTo(sourceContent); + Assertions.assertThat(asyncOp().read(targetPath).join()).isEqualTo(sourceContent); - op().delete(sourcePath).join(); - op().delete(targetPath).join(); + asyncOp().delete(sourcePath).join(); + asyncOp().delete(targetPath).join(); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncWriteTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncWriteTest.java index 2354152c198..a780cbaf467 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncWriteTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AsyncWriteTest.java @@ -35,7 +35,7 @@ public class AsyncWriteTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = op().info.fullCapability; + final Capability capability = asyncOp().info.fullCapability; assumeTrue(capability.read && capability.write); } @@ -45,7 +45,7 @@ public void precondition() { @Test public void testReadNotExist() { final String path = UUID.randomUUID().toString(); - assertThatThrownBy(() -> op().read(path).join()) + assertThatThrownBy(() -> asyncOp().read(path).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); } @@ -56,10 +56,10 @@ public void testReadNotExist() { public void testReadFull() { final String path = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(path, content).join(); - final byte[] actualContent = op().read(path).join(); + asyncOp().write(path, content).join(); + final byte[] actualContent = asyncOp().read(path).join(); assertThat(actualContent).isEqualTo(content); - op().delete(path).join(); + asyncOp().delete(path).join(); } /** @@ -68,7 +68,7 @@ public void testReadFull() { @Test public void testStatNotExist() { final String path = UUID.randomUUID().toString(); - assertThatThrownBy(() -> op().stat(path).join()) + assertThatThrownBy(() -> asyncOp().stat(path).join()) .is(OpenDALExceptionCondition.ofAsync(OpenDALException.Code.NotFound)); } @@ -79,11 +79,11 @@ public void testStatNotExist() { public void testStatFile() { final String path = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - op().write(path, content).join(); - final Metadata meta = op().stat(path).join(); + asyncOp().write(path, content).join(); + final Metadata meta = asyncOp().stat(path).join(); assertThat(meta.isFile()).isTrue(); assertThat(meta.getContentLength()).isEqualTo(content.length); - op().delete(path).join(); + asyncOp().delete(path).join(); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorExtension.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorExtension.java index 9f5f916445b..6a7c33d1363 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorExtension.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorExtension.java @@ -28,7 +28,7 @@ import java.util.UUID; import lombok.Cleanup; import lombok.extern.slf4j.Slf4j; -import org.apache.opendal.BlockingOperator; +import org.apache.opendal.AsyncOperator; import org.apache.opendal.Operator; import org.apache.opendal.layer.RetryLayer; import org.junit.jupiter.api.extension.AfterAllCallback; @@ -40,8 +40,8 @@ public class BehaviorExtension implements BeforeAllCallback, AfterAllCallback, TestWatcher { private String testName; + public AsyncOperator asyncOperator; public Operator operator; - public BlockingOperator blockingOperator; @Override public void beforeAll(ExtensionContext context) { @@ -63,9 +63,9 @@ public void beforeAll(ExtensionContext context) { config.put("root", root); } - @Cleanup final Operator op = Operator.of(scheme, config); - this.operator = op.layer(RetryLayer.builder().build()); - this.blockingOperator = this.operator.blocking(); + @Cleanup final AsyncOperator op = AsyncOperator.of(scheme, config); + this.asyncOperator = op.layer(RetryLayer.builder().build()); + this.operator = this.asyncOperator.blocking(); this.testName = String.format("%s(%s)", context.getDisplayName(), scheme); log.info( @@ -78,16 +78,16 @@ public void beforeAll(ExtensionContext context) { @Override public void afterAll(ExtensionContext context) { + if (asyncOperator != null) { + asyncOperator.close(); + asyncOperator = null; + } + if (operator != null) { operator.close(); operator = null; } - if (blockingOperator != null) { - blockingOperator.close(); - blockingOperator = null; - } - this.testName = null; } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorTestBase.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorTestBase.java index 57bc718d72b..78a138cf098 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorTestBase.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BehaviorTestBase.java @@ -23,7 +23,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; -import org.apache.opendal.BlockingOperator; +import org.apache.opendal.AsyncOperator; import org.apache.opendal.Operator; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; @@ -34,16 +34,16 @@ public abstract class BehaviorTestBase { @BeforeAll public static void assume() { + assumeTrue(behaviorExtension.asyncOperator != null); assumeTrue(behaviorExtension.operator != null); - assumeTrue(behaviorExtension.blockingOperator != null); } - protected Operator op() { - return behaviorExtension.operator; + protected AsyncOperator asyncOp() { + return behaviorExtension.asyncOperator; } - protected BlockingOperator blockingOp() { - return behaviorExtension.blockingOperator; + protected Operator op() { + return behaviorExtension.operator; } /** @@ -62,14 +62,13 @@ public static byte[] generateBytes() { * * @param input input bytes * @return SHA256 digest string - * @throws NoSuchAlgorithmException */ public static String sha256Digest(final byte[] input) throws NoSuchAlgorithmException { final MessageDigest digest = MessageDigest.getInstance("SHA-256"); final byte[] hash = digest.digest(input); final StringBuilder hexString = new StringBuilder(); - for (int i = 0; i < hash.length; i++) { - final String hex = Integer.toHexString(0xff & hash[i]); + for (byte b : hash) { + final String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) hexString.append('0'); hexString.append(hex); } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCopyTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCopyTest.java index 95b41d48baa..51c9e77a886 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCopyTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCopyTest.java @@ -36,7 +36,7 @@ class BlockingCopyTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = blockingOp().info.fullCapability; + final Capability capability = op().info.fullCapability; assumeTrue(capability.read && capability.write && capability.copy && capability.createDir); } @@ -48,16 +48,16 @@ public void testBlockingCopyFile() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); final String targetPath = UUID.randomUUID().toString(); - blockingOp().copy(sourcePath, targetPath); + op().copy(sourcePath, targetPath); - assertThat(blockingOp().read(targetPath)).isEqualTo(sourceContent); + assertThat(op().read(targetPath)).isEqualTo(sourceContent); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } /** @@ -68,7 +68,7 @@ public void testBlockingCopyNonExistingSource() { final String sourcePath = UUID.randomUUID().toString(); final String targetPath = UUID.randomUUID().toString(); - assertThatThrownBy(() -> blockingOp().copy(sourcePath, targetPath)) + assertThatThrownBy(() -> op().copy(sourcePath, targetPath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); } @@ -80,12 +80,12 @@ public void testBlockingCopySourceDir() { final String sourcePath = UUID.randomUUID() + "/"; final String targetPath = UUID.randomUUID().toString(); - blockingOp().createDir(sourcePath); + op().createDir(sourcePath); - assertThatThrownBy(() -> blockingOp().copy(sourcePath, targetPath)) + assertThatThrownBy(() -> op().copy(sourcePath, targetPath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.IsADirectory)); - blockingOp().delete(sourcePath); + op().delete(sourcePath); } /** @@ -96,17 +96,17 @@ public void testBlockingCopyTargetDir() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); final String targetPath = UUID.randomUUID() + "/"; - blockingOp().createDir(targetPath); + op().createDir(targetPath); - assertThatThrownBy(() -> blockingOp().copy(sourcePath, targetPath)) + assertThatThrownBy(() -> op().copy(sourcePath, targetPath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.IsADirectory)); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } /** @@ -117,12 +117,12 @@ public void testBlockingCopySelf() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); - assertThatThrownBy(() -> blockingOp().copy(sourcePath, sourcePath)) + assertThatThrownBy(() -> op().copy(sourcePath, sourcePath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.IsSameFile)); - blockingOp().delete(sourcePath); + op().delete(sourcePath); } /** @@ -133,16 +133,16 @@ public void testBlockingCopyNested() { final String sourcePath = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - blockingOp().write(sourcePath, content); + op().write(sourcePath, content); final String targetPath = String.format("%s/%s/%s", UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()); - blockingOp().copy(sourcePath, targetPath); + op().copy(sourcePath, targetPath); - assertThat(blockingOp().read(targetPath)).isEqualTo(content); + assertThat(op().read(targetPath)).isEqualTo(content); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } /** @@ -153,19 +153,19 @@ public void testBlockingCopyOverwrite() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); final String targetPath = UUID.randomUUID().toString(); final byte[] targetContent = generateBytes(); assertNotEquals(sourceContent, targetContent); - blockingOp().write(targetPath, targetContent); + op().write(targetPath, targetContent); - blockingOp().copy(sourcePath, targetPath); + op().copy(sourcePath, targetPath); - assertThat(blockingOp().read(targetPath)).isEqualTo(sourceContent); + assertThat(op().read(targetPath)).isEqualTo(sourceContent); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCreateDirTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCreateDirTest.java index 24bb2fb910d..55ec7cb509c 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCreateDirTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingCreateDirTest.java @@ -32,7 +32,7 @@ class BlockingCreateDirTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = blockingOp().info.fullCapability; + final Capability capability = op().info.fullCapability; assumeTrue(capability.createDir); } @@ -42,12 +42,12 @@ public void precondition() { @Test public void testBlockingCreateDir() { final String path = UUID.randomUUID() + "/"; - blockingOp().createDir(path); + op().createDir(path); - final Metadata meta = blockingOp().stat(path); + final Metadata meta = op().stat(path); assertThat(meta.isFile()).isFalse(); - blockingOp().delete(path); + op().delete(path); } /** @@ -56,12 +56,12 @@ public void testBlockingCreateDir() { @Test public void testBlockingDirExisting() { final String path = UUID.randomUUID() + "/"; - blockingOp().createDir(path); - blockingOp().createDir(path); + op().createDir(path); + op().createDir(path); - final Metadata meta = blockingOp().stat(path); + final Metadata meta = op().stat(path); assertThat(meta.isFile()).isFalse(); - blockingOp().delete(path); + op().delete(path); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingListTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingListTest.java index b4b940283ba..8d43249137b 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingListTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingListTest.java @@ -38,7 +38,7 @@ public class BlockingListTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = blockingOp().info.fullCapability; + final Capability capability = op().info.fullCapability; assumeTrue(capability.read && capability.write && capability.copy @@ -53,13 +53,13 @@ public void testBlockingListDir() { final String path = String.format("%s/%s", parent, UUID.randomUUID()); final byte[] content = generateBytes(); - blockingOp().write(path, content); + op().write(path, content); - final List list = blockingOp().list(parent + "/"); + final List list = op().list(parent + "/"); boolean found = false; for (Entry entry : list) { if (entry.getPath().equals(path)) { - Metadata meta = blockingOp().stat(path); + Metadata meta = op().stat(path); assertTrue(meta.isFile()); assertThat(meta.getContentLength()).isEqualTo(content.length); @@ -68,14 +68,14 @@ public void testBlockingListDir() { } assertTrue(found); - blockingOp().delete(path); + op().delete(path); } @Test public void testBlockingListNonExistDir() { final String dir = String.format("%s/", UUID.randomUUID()); - final List list = blockingOp().list(dir); + final List list = op().list(dir); assertTrue(list.isEmpty()); } @@ -90,22 +90,22 @@ public void testBlockingRemoveAll() { }; for (String path : expected) { if (path.endsWith("/")) { - blockingOp().createDir(String.format("%s/%s", parent, path)); + op().createDir(String.format("%s/%s", parent, path)); } else { - blockingOp().write(String.format("%s/%s", parent, path), "test_scan"); + op().write(String.format("%s/%s", parent, path), "test_scan"); } } - blockingOp().removeAll(parent + "/x/"); + op().removeAll(parent + "/x/"); for (String path : expected) { if (path.endsWith("/")) { continue; } - assertThatThrownBy(() -> blockingOp().stat(String.format("%s/%s", parent, path))) + assertThatThrownBy(() -> op().stat(String.format("%s/%s", parent, path))) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); } - blockingOp().removeAll(parent + "/"); + op().removeAll(parent + "/"); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingReadOnlyTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingReadOnlyTest.java index 444dacf9807..d5987af13ee 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingReadOnlyTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingReadOnlyTest.java @@ -45,7 +45,7 @@ public class BlockingReadOnlyTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = blockingOp().info.fullCapability; + final Capability capability = op().info.fullCapability; assumeTrue(capability.read && !capability.write && capability.blocking); } @@ -54,11 +54,11 @@ public void precondition() { */ @Test public void testBlockingReadOnlyStatFileAndDir() { - final Metadata fileMeta = blockingOp().stat(NORMAL_FILE_NAME); + final Metadata fileMeta = op().stat(NORMAL_FILE_NAME); assertTrue(fileMeta.isFile()); assertEquals(FILE_LENGTH, fileMeta.getContentLength()); - final Metadata dirMeta = blockingOp().stat(NORMAL_DIR_NAME); + final Metadata dirMeta = op().stat(NORMAL_DIR_NAME); assertTrue(dirMeta.isDir()); } @@ -67,11 +67,11 @@ public void testBlockingReadOnlyStatFileAndDir() { */ @Test public void testBlockingReadOnlyStatSpecialChars() { - final Metadata fileMeta = blockingOp().stat(SPECIAL_FILE_NAME); + final Metadata fileMeta = op().stat(SPECIAL_FILE_NAME); assertTrue(fileMeta.isFile()); assertEquals(FILE_LENGTH, fileMeta.getContentLength()); - final Metadata dirMeta = blockingOp().stat(SPECIAL_DIR_NAME); + final Metadata dirMeta = op().stat(SPECIAL_DIR_NAME); assertTrue(dirMeta.isDir()); } @@ -81,8 +81,7 @@ public void testBlockingReadOnlyStatSpecialChars() { @Test public void testBlockingReadOnlyStatNotExist() { final String path = UUID.randomUUID().toString(); - assertThatThrownBy(() -> blockingOp().stat(path)) - .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); + assertThatThrownBy(() -> op().stat(path)).is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); } /** @@ -90,7 +89,7 @@ public void testBlockingReadOnlyStatNotExist() { */ @Test public void testBlockingReadonlyReadFull() throws NoSuchAlgorithmException { - final byte[] content = blockingOp().read(NORMAL_FILE_NAME); + final byte[] content = op().read(NORMAL_FILE_NAME); assertEquals(FILE_LENGTH, content.length); assertEquals(FILE_SHA256_DIGEST, sha256Digest(content)); } @@ -101,7 +100,6 @@ public void testBlockingReadonlyReadFull() throws NoSuchAlgorithmException { @Test public void testBlockingReadOnlyReadNotExist() { final String path = UUID.randomUUID().toString(); - assertThatThrownBy(() -> blockingOp().read(path)) - .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); + assertThatThrownBy(() -> op().read(path)).is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingRenameTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingRenameTest.java index c1cdc9a5e62..e72f7732c7a 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingRenameTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingRenameTest.java @@ -35,7 +35,7 @@ class BlockingRenameTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = blockingOp().info.fullCapability; + final Capability capability = op().info.fullCapability; assumeTrue(capability.read && capability.write && capability.blocking @@ -51,19 +51,19 @@ public void testBlockingRenameFile() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); final String targetPath = UUID.randomUUID().toString(); - blockingOp().rename(sourcePath, targetPath); + op().rename(sourcePath, targetPath); - assertThatThrownBy(() -> blockingOp().stat(sourcePath)) + assertThatThrownBy(() -> op().stat(sourcePath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); - assertThat(blockingOp().stat(targetPath).getContentLength()).isEqualTo(sourceContent.length); + assertThat(op().stat(targetPath).getContentLength()).isEqualTo(sourceContent.length); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } /** @@ -74,7 +74,7 @@ public void testBlockingRenameNonExistingSource() { final String sourcePath = UUID.randomUUID().toString(); final String targetPath = UUID.randomUUID().toString(); - assertThatThrownBy(() -> blockingOp().rename(sourcePath, targetPath)) + assertThatThrownBy(() -> op().rename(sourcePath, targetPath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); } @@ -86,9 +86,9 @@ public void testBlockingRenameSourceDir() { final String sourcePath = UUID.randomUUID() + "/"; final String targetPath = UUID.randomUUID().toString(); - blockingOp().createDir(sourcePath); + op().createDir(sourcePath); - assertThatThrownBy(() -> blockingOp().rename(sourcePath, targetPath)) + assertThatThrownBy(() -> op().rename(sourcePath, targetPath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.IsADirectory)); } @@ -100,17 +100,17 @@ public void testBlockingRenameTargetDir() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); final String targetPath = UUID.randomUUID() + "/"; - blockingOp().createDir(targetPath); + op().createDir(targetPath); - assertThatThrownBy(() -> blockingOp().rename(sourcePath, targetPath)) + assertThatThrownBy(() -> op().rename(sourcePath, targetPath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.IsADirectory)); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } /** @@ -121,12 +121,12 @@ public void testBlockingRenameSelf() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); - assertThatThrownBy(() -> blockingOp().rename(sourcePath, sourcePath)) + assertThatThrownBy(() -> op().rename(sourcePath, sourcePath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.IsSameFile)); - blockingOp().delete(sourcePath); + op().delete(sourcePath); } /** @@ -137,19 +137,19 @@ public void testBlockingRenameNested() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); final String targetPath = String.format("%s/%s/%s", UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()); - blockingOp().rename(sourcePath, targetPath); + op().rename(sourcePath, targetPath); - assertThatThrownBy(() -> blockingOp().stat(sourcePath)) + assertThatThrownBy(() -> op().stat(sourcePath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); - assertThat(blockingOp().read(targetPath)).isEqualTo(sourceContent); + assertThat(op().read(targetPath)).isEqualTo(sourceContent); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } /** @@ -160,23 +160,23 @@ public void testBlockingRenameOverwrite() { final String sourcePath = UUID.randomUUID().toString(); final byte[] sourceContent = generateBytes(); - blockingOp().write(sourcePath, sourceContent); + op().write(sourcePath, sourceContent); final String targetPath = UUID.randomUUID().toString(); final byte[] targetContent = generateBytes(); assertNotEquals(sourceContent, targetContent); - blockingOp().write(targetPath, targetContent); + op().write(targetPath, targetContent); - blockingOp().rename(sourcePath, targetPath); + op().rename(sourcePath, targetPath); - assertThatThrownBy(() -> blockingOp().stat(sourcePath)) + assertThatThrownBy(() -> op().stat(sourcePath)) .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); - assertThat(blockingOp().read(targetPath)).isEqualTo(sourceContent); + assertThat(op().read(targetPath)).isEqualTo(sourceContent); - blockingOp().delete(sourcePath); - blockingOp().delete(targetPath); + op().delete(sourcePath); + op().delete(targetPath); } } diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingWriteTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingWriteTest.java index 750a448b27c..ce0be0f5432 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingWriteTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/BlockingWriteTest.java @@ -35,7 +35,7 @@ class BlockingWriteTest extends BehaviorTestBase { @BeforeAll public void precondition() { - final Capability capability = blockingOp().info.fullCapability; + final Capability capability = op().info.fullCapability; assumeTrue(capability.read && capability.write && capability.blocking); } @@ -45,8 +45,7 @@ public void precondition() { @Test public void testBlockingReadNotExist() { final String path = UUID.randomUUID().toString(); - assertThatThrownBy(() -> blockingOp().read(path)) - .is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); + assertThatThrownBy(() -> op().read(path)).is(OpenDALExceptionCondition.ofSync(OpenDALException.Code.NotFound)); } /** @@ -56,10 +55,10 @@ public void testBlockingReadNotExist() { public void testBlockingReadFull() { final String path = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - blockingOp().write(path, content); - final byte[] actualContent = blockingOp().read(path); + op().write(path, content); + final byte[] actualContent = op().read(path); assertThat(actualContent).isEqualTo(content); - blockingOp().delete(path); + op().delete(path); } /** @@ -69,11 +68,11 @@ public void testBlockingReadFull() { public void testBlockingStatFile() { final String path = UUID.randomUUID().toString(); final byte[] content = generateBytes(); - blockingOp().write(path, content); - final Metadata meta = blockingOp().stat(path); + op().write(path, content); + final Metadata meta = op().stat(path); assertThat(meta.isFile()).isTrue(); assertThat(meta.getContentLength()).isEqualTo(content.length); - blockingOp().delete(path); + op().delete(path); } } diff --git a/bindings/java/upgrade.md b/bindings/java/upgrade.md index f61edf61269..88631c837e9 100644 --- a/bindings/java/upgrade.md +++ b/bindings/java/upgrade.md @@ -1,3 +1,9 @@ +# Upgrade to v0.46 + +## Breaking change + +[PR-4641](https://github.com/apache/opendal/pull/4641/) renames async `Operator` to `AsyncOperator` and `BlockingOperator` to `Operator`. + # Upgrade to v0.44 ## Breaking change