Skip to main content

opendal_service_cacache/
backend.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::sync::Arc;
19
20use super::CACACHE_SCHEME;
21use super::config::CacacheConfig;
22use super::core::CacacheCore;
23use super::deleter::CacacheDeleter;
24use super::reader::*;
25use super::writer::CacacheWriter;
26use opendal_core::raw::*;
27use opendal_core::*;
28
29/// cacache service support.
30#[doc = include_str!("docs.md")]
31#[derive(Debug, Default)]
32pub struct CacacheBuilder {
33    pub(super) config: CacacheConfig,
34}
35
36impl CacacheBuilder {
37    /// Set the path to the cacache data directory. Will create if not exists.
38    pub fn datadir(mut self, path: &str) -> Self {
39        self.config.datadir = Some(path.into());
40        self
41    }
42}
43
44impl Builder for CacacheBuilder {
45    type Config = CacacheConfig;
46
47    fn build(self) -> Result<impl Service> {
48        let datadir_path = self.config.datadir.ok_or_else(|| {
49            Error::new(ErrorKind::ConfigInvalid, "datadir is required but not set")
50                .with_context("service", CACACHE_SCHEME)
51        })?;
52
53        let core = CacacheCore {
54            path: datadir_path.clone(),
55        };
56
57        let info = ServiceInfo::new(CACACHE_SCHEME, "/", &datadir_path);
58        let capability = Capability {
59            read: true,
60            write: true,
61            delete: true,
62            stat: true,
63            rename: false,
64            list: false,
65            ..Default::default()
66        };
67
68        Ok(CacacheBackend {
69            core: Arc::new(core),
70            info,
71            capability,
72        })
73    }
74}
75
76/// Backend for cacache services.
77#[derive(Debug, Clone)]
78pub struct CacacheBackend {
79    pub(crate) core: Arc<CacacheCore>,
80    pub(crate) info: ServiceInfo,
81    pub(crate) capability: Capability,
82}
83
84impl Service for CacacheBackend {
85    type Reader = oio::StreamReader<CacacheReader>;
86    type Writer = CacacheWriter;
87    type Lister = ();
88    type Deleter = oio::OneShotDeleter<CacacheDeleter>;
89    type Copier = ();
90
91    fn info(&self) -> ServiceInfo {
92        self.info.clone()
93    }
94
95    fn capability(&self) -> Capability {
96        self.capability
97    }
98
99    async fn create_dir(
100        &self,
101        _ctx: &OperationContext,
102        _path: &str,
103        _args: OpCreateDir,
104    ) -> Result<RpCreateDir> {
105        Err(Error::new(
106            ErrorKind::Unsupported,
107            "operation is not supported",
108        ))
109    }
110
111    async fn stat(&self, _ctx: &OperationContext, path: &str, _: OpStat) -> Result<RpStat> {
112        let metadata = self.core.metadata(path).await?;
113
114        match metadata {
115            Some(meta) => {
116                let mut md = Metadata::new(EntryMode::FILE);
117                md.set_content_length(meta.size as u64);
118                // Convert u128 milliseconds to Timestamp
119                let millis = meta.time as i64;
120                if let Ok(dt) = Timestamp::from_millisecond(millis) {
121                    md.set_last_modified(dt);
122                }
123                Ok(RpStat::new(md))
124            }
125            None => Err(Error::new(ErrorKind::NotFound, "entry not found")),
126        }
127    }
128    fn read(&self, _ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
129        let output: oio::StreamReader<CacacheReader> = {
130            Ok(oio::StreamReader::new(CacacheReader::new(
131                self.clone(),
132                path,
133                args,
134            )))
135        }?;
136
137        Ok(output)
138    }
139
140    fn write(&self, _ctx: &OperationContext, path: &str, _: OpWrite) -> Result<Self::Writer> {
141        let output: CacacheWriter =
142            { Ok(CacacheWriter::new(self.core.clone(), path.to_string())) }?;
143
144        Ok(output)
145    }
146
147    fn delete(&self, _ctx: &OperationContext) -> Result<Self::Deleter> {
148        let output: oio::OneShotDeleter<CacacheDeleter> = {
149            Ok(oio::OneShotDeleter::new(CacacheDeleter::new(
150                self.core.clone(),
151            )))
152        }?;
153
154        Ok(output)
155    }
156
157    fn list(&self, _ctx: &OperationContext, _path: &str, _args: OpList) -> Result<Self::Lister> {
158        Err(Error::new(
159            ErrorKind::Unsupported,
160            "operation is not supported",
161        ))
162    }
163
164    fn copy(
165        &self,
166        _ctx: &OperationContext,
167        _from: &str,
168        _to: &str,
169        _args: OpCopy,
170        _opts: OpCopier,
171    ) -> Result<Self::Copier> {
172        Err(Error::new(
173            ErrorKind::Unsupported,
174            "operation is not supported",
175        ))
176    }
177
178    async fn rename(
179        &self,
180        _ctx: &OperationContext,
181        _from: &str,
182        _to: &str,
183        _args: OpRename,
184    ) -> Result<RpRename> {
185        Err(Error::new(
186            ErrorKind::Unsupported,
187            "operation is not supported",
188        ))
189    }
190
191    async fn presign(
192        &self,
193        _ctx: &OperationContext,
194        _path: &str,
195        _args: OpPresign,
196    ) -> Result<RpPresign> {
197        Err(Error::new(
198            ErrorKind::Unsupported,
199            "operation is not supported",
200        ))
201    }
202}