blob: ab05ce3a7cc1573fac5735e77b3edc212bbba2bf [file]
// 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::ffi::c_void;
use std::time::Duration;
use ::opendal as core;
enum OperatorLayer {
Retry {
jitter: bool,
factor: f32,
min_delay: Duration,
max_delay: Duration,
max_times: u64,
},
Timeout {
timeout: Duration,
io_timeout: Duration,
},
}
impl OperatorLayer {
fn apply(&self, op: core::Operator) -> core::Operator {
match self {
Self::Retry {
jitter,
factor,
min_delay,
max_delay,
max_times,
} => {
let mut layer = core::layers::RetryLayer::new()
.with_factor(*factor)
.with_min_delay(*min_delay)
.with_max_delay(*max_delay)
.with_max_times(*max_times as usize);
if *jitter {
layer = layer.with_jitter();
}
op.layer(layer)
}
Self::Timeout {
timeout,
io_timeout,
} => op.layer(
core::layers::TimeoutLayer::new()
.with_timeout(*timeout)
.with_io_timeout(*io_timeout),
),
}
}
}
/// \brief The layers to apply when initializing an opendal_operator.
///
/// \note This is also a heap-allocated struct, please free it after you use it.
#[repr(C)]
pub struct opendal_operator_layers {
/// The pointer to the Vec<OperatorLayer> in the Rust code.
/// Only touch this on judging whether it is NULL.
inner: *mut c_void,
}
impl opendal_operator_layers {
pub(crate) fn apply(&self, mut op: core::Operator) -> core::Operator {
for layer in self.deref() {
op = layer.apply(op);
}
op
}
fn deref(&self) -> &[OperatorLayer] {
// Safety: the inner should never be null once constructed.
unsafe { &*(self.inner as *mut Vec<OperatorLayer>) }
}
fn deref_mut(&mut self) -> &mut Vec<OperatorLayer> {
// Safety: the inner should never be null once constructed.
unsafe { &mut *(self.inner as *mut Vec<OperatorLayer>) }
}
/// \brief Construct a heap-allocated opendal_operator_layers.
#[no_mangle]
pub extern "C" fn opendal_operator_layers_new() -> *mut Self {
let layers: Vec<OperatorLayer> = Vec::new();
let layers = Self {
inner: Box::into_raw(Box::new(layers)) as _,
};
Box::into_raw(Box::new(layers))
}
/// \brief Add a retry layer.
pub fn add_retry(
&mut self,
jitter: bool,
factor: f32,
min_delay_ns: u64,
max_delay_ns: u64,
max_times: u64,
) {
self.deref_mut().push(OperatorLayer::Retry {
jitter,
factor,
min_delay: Duration::from_nanos(min_delay_ns),
max_delay: Duration::from_nanos(max_delay_ns),
max_times,
});
}
/// \brief Add a retry layer.
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_layers_add_retry(
&mut self,
jitter: bool,
factor: f32,
min_delay_ns: u64,
max_delay_ns: u64,
max_times: u64,
) {
self.add_retry(jitter, factor, min_delay_ns, max_delay_ns, max_times);
}
/// \brief Add a timeout layer.
pub fn add_timeout(&mut self, timeout_ns: u64, io_timeout_ns: u64) {
self.deref_mut().push(OperatorLayer::Timeout {
timeout: Duration::from_nanos(timeout_ns),
io_timeout: Duration::from_nanos(io_timeout_ns),
});
}
/// \brief Add a timeout layer.
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_layers_add_timeout(
&mut self,
timeout_ns: u64,
io_timeout_ns: u64,
) {
self.add_timeout(timeout_ns, io_timeout_ns);
}
/// \brief Free the allocated memory used by opendal_operator_layers.
#[no_mangle]
pub unsafe extern "C" fn opendal_operator_layers_free(ptr: *mut opendal_operator_layers) {
unsafe {
if !ptr.is_null() {
drop(Box::from_raw((*ptr).inner as *mut Vec<OperatorLayer>));
drop(Box::from_raw(ptr));
}
}
}
}