opendal/services/dashmap/
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::fmt::Debug;
19use std::fmt::Formatter;
20
21use dashmap::DashMap;
22
23use crate::raw::adapters::typed_kv;
24use crate::raw::Access;
25use crate::services::DashmapConfig;
26use crate::*;
27
28impl Configurator for DashmapConfig {
29    type Builder = DashmapBuilder;
30    fn into_builder(self) -> Self::Builder {
31        DashmapBuilder { config: self }
32    }
33}
34
35/// [dashmap](https://github.com/xacrimon/dashmap) backend support.
36#[doc = include_str!("docs.md")]
37#[derive(Default)]
38pub struct DashmapBuilder {
39    config: DashmapConfig,
40}
41
42impl DashmapBuilder {
43    /// Set the root for dashmap.
44    pub fn root(mut self, path: &str) -> Self {
45        self.config.root = if path.is_empty() {
46            None
47        } else {
48            Some(path.to_string())
49        };
50
51        self
52    }
53}
54
55impl Builder for DashmapBuilder {
56    const SCHEME: Scheme = Scheme::Dashmap;
57    type Config = DashmapConfig;
58
59    fn build(self) -> Result<impl Access> {
60        let mut backend = DashmapBackend::new(Adapter {
61            inner: DashMap::default(),
62        });
63        if let Some(v) = self.config.root {
64            backend = backend.with_root(&v);
65        }
66
67        Ok(backend)
68    }
69}
70
71/// Backend is used to serve `Accessor` support in dashmap.
72pub type DashmapBackend = typed_kv::Backend<Adapter>;
73
74#[derive(Clone)]
75pub struct Adapter {
76    inner: DashMap<String, typed_kv::Value>,
77}
78
79impl Debug for Adapter {
80    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
81        f.debug_struct("DashmapAdapter")
82            .field("size", &self.inner.len())
83            .finish_non_exhaustive()
84    }
85}
86
87impl typed_kv::Adapter for Adapter {
88    fn info(&self) -> typed_kv::Info {
89        typed_kv::Info::new(
90            Scheme::Dashmap,
91            "dashmap",
92            typed_kv::Capability {
93                get: true,
94                set: true,
95                scan: true,
96                delete: true,
97                shared: false,
98            },
99        )
100    }
101
102    async fn get(&self, path: &str) -> Result<Option<typed_kv::Value>> {
103        match self.inner.get(path) {
104            None => Ok(None),
105            Some(bs) => Ok(Some(bs.value().to_owned())),
106        }
107    }
108
109    async fn set(&self, path: &str, value: typed_kv::Value) -> Result<()> {
110        self.inner.insert(path.to_string(), value);
111
112        Ok(())
113    }
114
115    async fn delete(&self, path: &str) -> Result<()> {
116        self.inner.remove(path);
117
118        Ok(())
119    }
120
121    async fn scan(&self, path: &str) -> Result<Vec<String>> {
122        let keys = self.inner.iter().map(|kv| kv.key().to_string());
123        if path.is_empty() {
124            Ok(keys.collect())
125        } else {
126            Ok(keys.filter(|k| k.starts_with(path)).collect())
127        }
128    }
129}