This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 5e0fb9e42 feat(bindings/java): support duplicate operator (#3330)
5e0fb9e42 is described below

commit 5e0fb9e429e389077f0a581da2265d01213b5622
Author: tison <[email protected]>
AuthorDate: Wed Oct 18 11:44:49 2023 +0800

    feat(bindings/java): support duplicate operator (#3330)
    
    Signed-off-by: tison <[email protected]>
---
 bindings/java/src/blocking_operator.rs             | 15 ++++-
 .../java/org/apache/opendal/BlockingOperator.java  | 12 ++++
 .../src/main/java/org/apache/opendal/Operator.java | 16 +++++
 bindings/java/src/operator.rs                      | 13 ++++
 .../apache/opendal/test/OperatorDuplicateTest.java | 74 ++++++++++++++++++++++
 5 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/bindings/java/src/blocking_operator.rs 
b/bindings/java/src/blocking_operator.rs
index 6f84a2fea..8de632dc5 100644
--- a/bindings/java/src/blocking_operator.rs
+++ b/bindings/java/src/blocking_operator.rs
@@ -19,8 +19,8 @@ use jni::objects::JByteArray;
 use jni::objects::JClass;
 use jni::objects::JObject;
 use jni::objects::JString;
-use jni::sys::jbyteArray;
 use jni::sys::jobject;
+use jni::sys::{jbyteArray, jlong};
 use jni::JNIEnv;
 
 use opendal::BlockingOperator;
@@ -41,6 +41,19 @@ pub unsafe extern "system" fn 
Java_org_apache_opendal_BlockingOperator_disposeIn
     drop(Box::from_raw(op));
 }
 
+/// # Safety
+///
+/// This function should not be called before the Operator are 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 are ready.
diff --git 
a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java 
b/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java
index 96f444641..8a3dab8ed 100644
--- a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java
+++ b/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java
@@ -50,6 +50,16 @@ public class BlockingOperator extends NativeObject {
         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));
     }
@@ -85,6 +95,8 @@ public class BlockingOperator extends NativeObject {
     @Override
     protected native void disposeInternal(long handle);
 
+    private static native long duplicate(long nativeHandle);
+
     private static native void write(long nativeHandle, String path, byte[] 
content);
 
     private static native byte[] read(long nativeHandle, 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 54273ee1a..6aa957a5d 100644
--- a/bindings/java/src/main/java/org/apache/opendal/Operator.java
+++ b/bindings/java/src/main/java/org/apache/opendal/Operator.java
@@ -122,6 +122,20 @@ public class Operator extends NativeObject {
         this.info = info;
     }
 
+    /**
+     * Clone a new operator that is identical to this one. The new operator 
has its own lifecycle.
+     *
+     * <p>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 Operator duplicate() {
+        final long nativeHandle = duplicate(this.nativeHandle);
+        return new Operator(nativeHandle, this.info);
+    }
+
     public BlockingOperator blocking() {
         final long nativeHandle = makeBlockingOp(this.nativeHandle);
         final OperatorInfo info = this.info;
@@ -194,6 +208,8 @@ public class Operator extends NativeObject {
     @Override
     protected native void disposeInternal(long handle);
 
+    private static native long duplicate(long nativeHandle);
+
     private static native long constructor(String schema, Map<String, String> 
map);
 
     private static native long read(long nativeHandle, String path);
diff --git a/bindings/java/src/operator.rs b/bindings/java/src/operator.rs
index ccc06edf4..9f5437e57 100644
--- a/bindings/java/src/operator.rs
+++ b/bindings/java/src/operator.rs
@@ -64,6 +64,19 @@ fn intern_constructor(env: &mut JNIEnv, scheme: JString, 
map: JObject) -> Result
     Ok(Box::into_raw(Box::new(op)) as jlong)
 }
 
+/// # Safety
+///
+/// This function should not be called before the Operator are ready.
+#[no_mangle]
+pub unsafe extern "system" fn Java_org_apache_opendal_Operator_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 are ready.
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
new file mode 100644
index 000000000..d4af7bde6
--- /dev/null
+++ 
b/bindings/java/src/test/java/org/apache/opendal/test/OperatorDuplicateTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.opendal.BlockingOperator;
+import org.apache.opendal.Operator;
+import org.junit.jupiter.api.Test;
+
+public class OperatorDuplicateTest {
+    @Test
+    public void testDuplicateOperator() {
+        final Map<String, String> conf = new HashMap<>();
+        conf.put("root", "/opendal/");
+        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 Operator duplicatedOp = op.duplicate()) {
+                assertThat(duplicatedOp.info).isNotNull();
+                assertThat(duplicatedOp.info).isEqualTo(op.info);
+                duplicatedOp.write(key, v0).join();
+                assertThat(duplicatedOp.read(key).join()).isEqualTo(v0);
+            }
+
+            assertThat(op.read(key).join()).isEqualTo(v0);
+            op.write(key, v1).join();
+            assertThat(op.read(key).join()).isEqualTo(v1);
+        }
+    }
+
+    @Test
+    public void testDuplicateBlockingOperator() {
+        final Map<String, String> conf = new HashMap<>();
+        conf.put("root", "/opendal/");
+        try (final BlockingOperator op = BlockingOperator.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()) {
+                assertThat(duplicatedOp.info).isNotNull();
+                assertThat(duplicatedOp.info).isEqualTo(op.info);
+                duplicatedOp.write(key, v0);
+                assertThat(duplicatedOp.read(key)).isEqualTo(v0);
+            }
+
+            assertThat(op.read(key)).isEqualTo(v0);
+            op.write(key, v1);
+            assertThat(op.read(key)).isEqualTo(v1);
+        }
+    }
+}

Reply via email to