pub struct Operator { /* private fields */ }blocking only.Expand description
Use OpenDAL in blocking context.
§Notes
blocking::Operator is a wrapper around AsyncOperator. It calls async runtimes’ block_on API to spawn blocking tasks.
Please avoid using blocking::Operator in async context.
§Examples
§Init in async context
blocking::Operator will use current async context’s runtime to handle the async calls.
This is just for initialization. You must use blocking::Operator in blocking context.
#[tokio::main]
async fn main() -> Result<()> {
// Create fs backend builder.
let builder = services::Memory::default();
let op = Operator::new(builder)?.finish();
// Build an `blocking::Operator` with blocking layer to start operating the storage.
let _: blocking::Operator = blocking::Operator::new(op)?;
Ok(())
}§In async context with blocking functions
If blocking::Operator is called in blocking function, please fetch a [tokio::runtime::EnterGuard]
first. You can use [Handle::try_current] first to get the handle and then call [Handle::enter].
This often happens in the case that async function calls blocking function.
#[tokio::main]
async fn main() -> Result<()> {
let _ = blocking_fn()?;
Ok(())
}
fn blocking_fn() -> Result<blocking::Operator> {
// Create fs backend builder.
let builder = services::Memory::default();
let op = Operator::new(builder)?.finish();
let handle = tokio::runtime::Handle::try_current().unwrap();
let _guard = handle.enter();
// Build an `blocking::Operator` to start operating the storage.
let op: blocking::Operator = blocking::Operator::new(op)?;
Ok(op)
}§In blocking context
In a pure blocking context, we can create a runtime and use it to create the blocking::Operator.
The following code uses a global statically created runtime as an example, please manage the runtime on demand.
static RUNTIME: LazyLock<tokio::runtime::Runtime> = LazyLock::new(|| {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
});
fn main() -> Result<()> {
// Create fs backend builder.
let builder = services::Memory::default();
let op = Operator::new(builder)?.finish();
// Fetch the `EnterGuard` from global runtime.
let _guard = RUNTIME.enter();
// Build an `blocking::Operator` with blocking layer to start operating the storage.
let _: blocking::Operator = blocking::Operator::new(op)?;
Ok(())
}Implementations§
Source§impl Operator
impl Operator
Sourcepub fn new(op: AsyncOperator) -> Result<Self>
pub fn new(op: AsyncOperator) -> Result<Self>
Create a new BlockingLayer with the current runtime’s handle
Sourcepub fn from_uri(uri: impl IntoOperatorUri) -> Result<Self>
pub fn from_uri(uri: impl IntoOperatorUri) -> Result<Self>
Create a blocking operator from URI based configuration.
Sourcepub fn info(&self) -> OperatorInfo
pub fn info(&self) -> OperatorInfo
Get information of underlying accessor.
§Examples
use opendal_core::blocking;
use opendal_core::blocking::Operator;
let info = op.info();Source§impl Operator
§Operator blocking API.
impl Operator
§Operator blocking API.
Sourcepub fn stat(&self, path: &str) -> Result<Metadata>
pub fn stat(&self, path: &str) -> Result<Metadata>
Get given path’s metadata.
§Behavior
§Services that support create_dir
test and test/ may vary in some services such as S3. However, on a local file system,
they’re identical. Therefore, the behavior of stat("test") and stat("test/") might differ
in certain edge cases. Always use stat("test/") when you need to access a directory if possible.
Here are the behavior list:
| Case | Path | Result |
|---|---|---|
| stat existing dir | abc/ | Metadata with dir mode |
| stat existing file | abc/def_file | Metadata with file mode |
stat dir without / | abc/def_dir | Error NotFound or metadata with dir mode |
stat file with / | abc/def_file/ | Error NotFound |
| stat not existing path | xyz | Error NotFound |
Refer to RFC: List Prefix for more details.
§Services that not support create_dir
For services that not support create_dir, stat("test/") will return NotFound even
when test/abc exists since the service won’t have the concept of dir. There is nothing
we can do about this.
§Examples
§Check if file exists
use opendal_core::blocking;
use opendal_core::ErrorKind;
if let Err(e) = op.stat("test") {
if e.kind() == ErrorKind::NotFound {
println!("file not exist")
}
}Sourcepub fn stat_options(&self, path: &str, opts: StatOptions) -> Result<Metadata>
pub fn stat_options(&self, path: &str, opts: StatOptions) -> Result<Metadata>
Get given path’s metadata with extra options.
§Behavior
§Services that support create_dir
test and test/ may vary in some services such as S3. However, on a local file system,
they’re identical. Therefore, the behavior of stat("test") and stat("test/") might differ
in certain edge cases. Always use stat("test/") when you need to access a directory if possible.
Here are the behavior list:
| Case | Path | Result |
|---|---|---|
| stat existing dir | abc/ | Metadata with dir mode |
| stat existing file | abc/def_file | Metadata with file mode |
stat dir without / | abc/def_dir | Error NotFound or metadata with dir mode |
stat file with / | abc/def_file/ | Error NotFound |
| stat not existing path | xyz | Error NotFound |
Refer to RFC: List Prefix for more details.
§Services that not support create_dir
For services that not support create_dir, stat("test/") will return NotFound even
when test/abc exists since the service won’t have the concept of dir. There is nothing
we can do about this.
Sourcepub fn exists(&self, path: &str) -> Result<bool>
pub fn exists(&self, path: &str) -> Result<bool>
Check if this path exists or not.
§Example
use anyhow::Result;
use opendal_core::blocking;
use opendal_core::blocking::Operator;
fn test(op: blocking::Operator) -> Result<()> {
let _ = op.exists("test")?;
Ok(())
}Sourcepub fn create_dir(&self, path: &str) -> Result<()>
pub fn create_dir(&self, path: &str) -> Result<()>
Create a dir at given path.
§Notes
To indicate that a path is a directory, it is compulsory to include
a trailing / in the path. Failure to do so may result in
NotADirectory error being returned by OpenDAL.
§Behavior
- Create on existing dir will succeed.
- Create dir is always recursive, works like
mkdir -p
§Examples
use opendal_core::blocking;
op.create_dir("path/to/dir/")?;Sourcepub fn read(&self, path: &str) -> Result<Buffer>
pub fn read(&self, path: &str) -> Result<Buffer>
Read the whole path into a bytes.
This function will allocate a new bytes internally. For more precise memory control or
reading data lazily, please use blocking::Operator::reader
§Examples
use opendal_core::blocking;
let bs = op.read("path/to/file")?;Sourcepub fn read_options(&self, path: &str, opts: ReadOptions) -> Result<Buffer>
pub fn read_options(&self, path: &str, opts: ReadOptions) -> Result<Buffer>
Read the whole path into a bytes with extra options.
This function will allocate a new bytes internally. For more precise memory control or
reading data lazily, please use blocking::Operator::reader
Sourcepub fn reader(&self, path: &str) -> Result<Reader>
pub fn reader(&self, path: &str) -> Result<Reader>
Create a new reader which can read the whole path.
§Examples
use opendal_core::blocking;
let r = op.reader("path/to/file")?;Sourcepub fn reader_options(&self, path: &str, opts: ReaderOptions) -> Result<Reader>
pub fn reader_options(&self, path: &str, opts: ReaderOptions) -> Result<Reader>
Create a new reader with extra options
Sourcepub fn write_options(
&self,
path: &str,
bs: impl Into<Buffer>,
opts: WriteOptions,
) -> Result<Metadata>
pub fn write_options( &self, path: &str, bs: impl Into<Buffer>, opts: WriteOptions, ) -> Result<Metadata>
Write data with options.
§Notes
- Write will make sure all bytes has been written, or an error will be returned.
Sourcepub fn writer_options(&self, path: &str, opts: WriteOptions) -> Result<Writer>
pub fn writer_options(&self, path: &str, opts: WriteOptions) -> Result<Writer>
Create a new writer with extra options
Sourcepub fn copy(&self, from: &str, to: &str) -> Result<()>
pub fn copy(&self, from: &str, to: &str) -> Result<()>
Copy a file from from to to.
§Notes
fromandtomust be a file.towill be overwritten if it exists.- If
fromandtoare the same, nothing will happen. copyis idempotent. For samefromandtoinput, the result will be the same.
§Examples
use opendal_core::blocking;
op.copy("path/to/file", "path/to/file2")?;Sourcepub fn delete_options(&self, path: &str, opts: DeleteOptions) -> Result<()>
pub fn delete_options(&self, path: &str, opts: DeleteOptions) -> Result<()>
Sourcepub fn delete_iter<I, D>(&self, iter: I) -> Result<()>where
I: IntoIterator<Item = D>,
D: IntoDeleteInput,
pub fn delete_iter<I, D>(&self, iter: I) -> Result<()>where
I: IntoIterator<Item = D>,
D: IntoDeleteInput,
Delete an infallible iterator of paths.
Also see:
blocking::Operator::delete_try_iter: delete an fallible iterator of paths.
Sourcepub fn delete_try_iter<I, D>(&self, try_iter: I) -> Result<()>
pub fn delete_try_iter<I, D>(&self, try_iter: I) -> Result<()>
Delete a fallible iterator of paths.
Also see:
blocking::Operator::delete_iter: delete an infallible iterator of paths.
Sourcepub fn deleter(&self) -> Result<Deleter>
pub fn deleter(&self) -> Result<Deleter>
Create a [BlockingDeleter] to continuously remove content from storage.
It leverages batch deletion capabilities provided by storage services for efficient removal.
Users can have more control over the deletion process by using [BlockingDeleter] directly.
Sourcepub fn remove_all(&self, path: &str) -> Result<()>
pub fn remove_all(&self, path: &str) -> Result<()>
Sourcepub fn list(&self, path: &str) -> Result<Vec<Entry>>
pub fn list(&self, path: &str) -> Result<Vec<Entry>>
List entries whose paths start with the given prefix path.
§Semantics
- Listing is prefix-based; it doesn’t require the parent directory to exist.
- If
pathitself exists, it is returned as an entry along with prefixed children. - If
pathis missing but deeper objects exist, the list succeeds and returns those prefixed entries instead of an error. - Set
recursiveinoptions::ListOptionsvialist_optionsto walk all descendants; the default returns only immediate children when delimiter is supported.
§Streaming List
This function materializes the full result in memory. For large listings, prefer blocking::Operator::lister to stream entries.
§Examples
use opendal_core::blocking;
use opendal_core::blocking::Operator;
use opendal_core::EntryMode;
let mut entries = op.list("path/to/dir/")?;
for entry in entries {
match entry.metadata().mode() {
EntryMode::FILE => {
println!("Handling file")
}
EntryMode::DIR => {
println!("Handling dir {}", entry.path())
}
EntryMode::Unknown => continue,
}
}Sourcepub fn list_options(&self, path: &str, opts: ListOptions) -> Result<Vec<Entry>>
pub fn list_options(&self, path: &str, opts: ListOptions) -> Result<Vec<Entry>>
List entries whose paths start with the given prefix path with additional options.
§Semantics
Inherits the prefix semantics described in Operator::list (blocking variant). It returns path itself if present and tolerates missing parents when prefixed objects exist.
§Streaming List
This function materializes the full result in memory. For large listings, prefer blocking::Operator::lister to stream entries.
§Options
See options::ListOptions for the full set. Common knobs: traversal (recursive), pagination (limit, start_after), and versioning (versions, deleted).
Sourcepub fn lister(&self, path: &str) -> Result<Lister>
pub fn lister(&self, path: &str) -> Result<Lister>
Create a streaming lister for entries whose paths start with the given prefix path.
This function creates a new [BlockingLister]; dropping it stops listing.
§Semantics
Shares the same prefix semantics as blocking::Operator::list: parent directory is optional; path itself is yielded if present; missing parents with deeper objects are accepted.
§Options
Accepts the same options::ListOptions as list_options: traversal (recursive), pagination (limit, start_after), and versioning (versions, deleted).
§Examples
use futures::TryStreamExt;
use opendal_core::blocking;
use opendal_core::blocking::Operator;
use opendal_core::EntryMode;
let mut ds = op.lister("path/to/dir/")?;
for de in ds {
let de = de?;
match de.metadata().mode() {
EntryMode::FILE => {
println!("Handling file")
}
EntryMode::DIR => {
println!("Handling dir like start a new list via meta.path()")
}
EntryMode::Unknown => continue,
}
}Sourcepub fn lister_options(&self, path: &str, opts: ListOptions) -> Result<Lister>
pub fn lister_options(&self, path: &str, opts: ListOptions) -> Result<Lister>
List entries under a prefix as an iterator with options.
This function creates a new handle to stream entries and inherits the prefix semantics of blocking::Operator::list.
§Options
Same as lister; see options::ListOptions for traversal, pagination, and versioning knobs.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Operator
impl !RefUnwindSafe for Operator
impl Send for Operator
impl Sync for Operator
impl Unpin for Operator
impl !UnwindSafe for Operator
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.