|
15 | 15 | // specific language governing permissions and limitations |
16 | 16 | // under the License. |
17 | 17 |
|
18 | | -use std::fmt::Debug; |
19 | | -use std::fmt::Formatter; |
20 | 18 | use std::sync::Arc; |
21 | 19 |
|
22 | 20 | use rocksdb::DB; |
23 | 21 |
|
24 | | -use crate::Result; |
25 | | -use crate::raw::adapters::kv; |
| 22 | +use super::config::RocksdbConfig; |
| 23 | +use super::core::*; |
| 24 | +use super::deleter::RocksdbDeleter; |
| 25 | +use super::lister::RocksdbLister; |
| 26 | +use super::writer::RocksdbWriter; |
26 | 27 | use crate::raw::*; |
27 | | -use crate::services::RocksdbConfig; |
28 | 28 | use crate::*; |
29 | 29 |
|
30 | 30 | /// RocksDB service support. |
@@ -70,83 +70,106 @@ impl Builder for RocksdbBuilder { |
70 | 70 | .set_source(e) |
71 | 71 | })?; |
72 | 72 |
|
73 | | - let root = normalize_root( |
74 | | - self.config |
75 | | - .root |
76 | | - .clone() |
77 | | - .unwrap_or_else(|| "/".to_string()) |
78 | | - .as_str(), |
79 | | - ); |
| 73 | + let root = normalize_root(&self.config.root.unwrap_or_default()); |
80 | 74 |
|
81 | | - Ok(RocksdbBackend::new(Adapter { db: Arc::new(db) }).with_normalized_root(root)) |
| 75 | + Ok(RocksdbBackend::new(RocksdbCore { db: Arc::new(db) }).with_normalized_root(root)) |
82 | 76 | } |
83 | 77 | } |
84 | 78 |
|
85 | 79 | /// Backend for rocksdb services. |
86 | | -pub type RocksdbBackend = kv::Backend<Adapter>; |
87 | | - |
88 | | -#[derive(Clone)] |
89 | | -pub struct Adapter { |
90 | | - db: Arc<DB>, |
| 80 | +#[derive(Clone, Debug)] |
| 81 | +pub struct RocksdbBackend { |
| 82 | + core: Arc<RocksdbCore>, |
| 83 | + root: String, |
| 84 | + info: Arc<AccessorInfo>, |
91 | 85 | } |
92 | 86 |
|
93 | | -impl Debug for Adapter { |
94 | | - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
95 | | - let mut ds = f.debug_struct("Adapter"); |
96 | | - ds.field("path", &self.db.path()); |
97 | | - ds.finish() |
98 | | - } |
99 | | -} |
100 | | - |
101 | | -impl kv::Adapter for Adapter { |
102 | | - type Scanner = kv::Scanner; |
103 | | - |
104 | | - fn info(&self) -> kv::Info { |
105 | | - kv::Info::new( |
106 | | - Scheme::Rocksdb, |
107 | | - &self.db.path().to_string_lossy(), |
108 | | - Capability { |
| 87 | +impl RocksdbBackend { |
| 88 | + pub fn new(core: RocksdbCore) -> Self { |
| 89 | + let info = AccessorInfo::default(); |
| 90 | + info.set_scheme(Scheme::Rocksdb.into_static()) |
| 91 | + .set_name(&core.db.path().to_string_lossy()) |
| 92 | + .set_root("/") |
| 93 | + .set_native_capability(Capability { |
109 | 94 | read: true, |
| 95 | + stat: true, |
110 | 96 | write: true, |
| 97 | + write_can_empty: true, |
| 98 | + delete: true, |
111 | 99 | list: true, |
| 100 | + list_with_recursive: true, |
112 | 101 | shared: false, |
113 | 102 | ..Default::default() |
114 | | - }, |
115 | | - ) |
116 | | - } |
| 103 | + }); |
117 | 104 |
|
118 | | - async fn get(&self, path: &str) -> Result<Option<Buffer>> { |
119 | | - let result = self.db.get(path).map_err(parse_rocksdb_error)?; |
120 | | - Ok(result.map(Buffer::from)) |
| 105 | + Self { |
| 106 | + core: Arc::new(core), |
| 107 | + root: "/".to_string(), |
| 108 | + info: Arc::new(info), |
| 109 | + } |
121 | 110 | } |
122 | 111 |
|
123 | | - async fn set(&self, path: &str, value: Buffer) -> Result<()> { |
124 | | - self.db |
125 | | - .put(path, value.to_vec()) |
126 | | - .map_err(parse_rocksdb_error) |
| 112 | + fn with_normalized_root(mut self, root: String) -> Self { |
| 113 | + self.info.set_root(&root); |
| 114 | + self.root = root; |
| 115 | + self |
127 | 116 | } |
| 117 | +} |
| 118 | + |
| 119 | +impl Access for RocksdbBackend { |
| 120 | + type Reader = Buffer; |
| 121 | + type Writer = RocksdbWriter; |
| 122 | + type Lister = oio::HierarchyLister<RocksdbLister>; |
| 123 | + type Deleter = oio::OneShotDeleter<RocksdbDeleter>; |
128 | 124 |
|
129 | | - async fn delete(&self, path: &str) -> Result<()> { |
130 | | - self.db.delete(path).map_err(parse_rocksdb_error) |
| 125 | + fn info(&self) -> Arc<AccessorInfo> { |
| 126 | + self.info.clone() |
131 | 127 | } |
132 | 128 |
|
133 | | - async fn scan(&self, path: &str) -> Result<Self::Scanner> { |
134 | | - let it = self.db.prefix_iterator(path).map(|r| r.map(|(k, _)| k)); |
135 | | - let mut res = Vec::default(); |
| 129 | + async fn stat(&self, path: &str, _: OpStat) -> Result<RpStat> { |
| 130 | + let p = build_abs_path(&self.root, path); |
136 | 131 |
|
137 | | - for key in it { |
138 | | - let key = key.map_err(parse_rocksdb_error)?; |
139 | | - let key = String::from_utf8_lossy(&key); |
140 | | - if !key.starts_with(path) { |
141 | | - break; |
| 132 | + if p == build_abs_path(&self.root, "") { |
| 133 | + Ok(RpStat::new(Metadata::new(EntryMode::DIR))) |
| 134 | + } else { |
| 135 | + let bs = self.core.get(&p)?; |
| 136 | + match bs { |
| 137 | + Some(bs) => Ok(RpStat::new( |
| 138 | + Metadata::new(EntryMode::FILE).with_content_length(bs.len() as u64), |
| 139 | + )), |
| 140 | + None => Err(Error::new(ErrorKind::NotFound, "kv not found in rocksdb")), |
142 | 141 | } |
143 | | - res.push(key.to_string()); |
144 | 142 | } |
| 143 | + } |
145 | 144 |
|
146 | | - Ok(Box::new(kv::ScanStdIter::new(res.into_iter().map(Ok)))) |
| 145 | + async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> { |
| 146 | + let p = build_abs_path(&self.root, path); |
| 147 | + let bs = match self.core.get(&p)? { |
| 148 | + Some(bs) => bs, |
| 149 | + None => { |
| 150 | + return Err(Error::new(ErrorKind::NotFound, "kv not found in rocksdb")); |
| 151 | + } |
| 152 | + }; |
| 153 | + Ok((RpRead::new(), bs.slice(args.range().to_range_as_usize()))) |
147 | 154 | } |
148 | | -} |
149 | 155 |
|
150 | | -fn parse_rocksdb_error(e: rocksdb::Error) -> Error { |
151 | | - Error::new(ErrorKind::Unexpected, "got rocksdb error").set_source(e) |
| 156 | + async fn write(&self, path: &str, _: OpWrite) -> Result<(RpWrite, Self::Writer)> { |
| 157 | + let p = build_abs_path(&self.root, path); |
| 158 | + let writer = RocksdbWriter::new(self.core.clone(), p); |
| 159 | + Ok((RpWrite::new(), writer)) |
| 160 | + } |
| 161 | + |
| 162 | + async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> { |
| 163 | + let deleter = RocksdbDeleter::new(self.core.clone(), self.root.clone()); |
| 164 | + Ok((RpDelete::default(), oio::OneShotDeleter::new(deleter))) |
| 165 | + } |
| 166 | + |
| 167 | + async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> { |
| 168 | + let p = build_abs_path(&self.root, path); |
| 169 | + let lister = RocksdbLister::new(self.core.clone(), self.root.clone(), p)?; |
| 170 | + Ok(( |
| 171 | + RpList::default(), |
| 172 | + oio::HierarchyLister::new(lister, path, args.recursive()), |
| 173 | + )) |
| 174 | + } |
152 | 175 | } |
0 commit comments