All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.opendal.Operator Maven / Gradle / Ivy

Go to download

Apache OpenDAL™ is a data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way.

There is a newer version: 0.46.4
Show newest version
/*
 * 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;

/**
 * Operator represents an underneath OpenDAL operator that
 * accesses data asynchronously.
 */
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: * *

    * 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 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); } private Operator(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 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)); } 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); }





    © 2015 - 2025 Weber Informatics LLC | Privacy Policy