1use super::storage;
2
3use std::ops::Add;
4use std::path;
5use storage::lsm;
6
7#[derive(Clone)]
12pub struct LsmConfig {
13 pub flush_threshold: Size,
14}
15
16#[derive(Clone)]
22pub struct DustDataConfig {
23 pub path: path::PathBuf,
24 pub lsm_config: LsmConfig,
25}
26
27pub struct DustData {
28 pub config: DustDataConfig,
29 pub lsm: storage::lsm::Lsm,
30}
31
32#[derive(Clone, PartialEq, Eq, Debug)]
33pub enum Size {
34 Bytes(usize),
35 Kilobytes(usize),
36 Megabytes(usize),
37 Gigabytes(usize),
38}
39
40impl Add for Size {
41 type Output = Size;
42
43 fn add(self, rhs: Self) -> Self::Output {
44 fn calc(a: usize, b: usize) -> Size {
45 let mut bytes = a + b;
46
47 let mut gigabytes = 0;
48 let mut megabytes = 0;
49 let mut kilobytes = 0;
50
51 while bytes >= 1024 * 1024 * 1024 {
52 gigabytes += 1;
53 bytes -= 1024 * 1024 * 1024;
54 }
55
56 while bytes >= 1024 * 1024 {
57 megabytes += 1;
58 bytes -= 1024 * 1024;
59 }
60
61 while bytes >= 1024 {
62 kilobytes += 1;
63 bytes -= 1024;
64 }
65
66 if gigabytes > 0 {
67 Size::Gigabytes(gigabytes)
68 } else if megabytes > 0 {
69 Size::Megabytes(megabytes)
70 } else if kilobytes > 0 {
71 Size::Kilobytes(kilobytes)
72 } else {
73 Size::Bytes(bytes)
74 }
75 }
76
77 match (self, rhs) {
78 (Size::Bytes(a), Size::Bytes(b)) => calc(a, b),
79 (Size::Bytes(a), Size::Kilobytes(b)) => calc(a, b * 1024),
80 (Size::Bytes(a), Size::Megabytes(b)) => calc(a, b * 1024 * 1024),
81 (Size::Bytes(a), Size::Gigabytes(b)) => calc(a, b * 1024 * 1024 * 1024),
82
83 (Size::Kilobytes(a), Size::Bytes(b)) => calc(a * 1024, b * 1024),
84 (Size::Kilobytes(a), Size::Kilobytes(b)) => calc(a * 1024, b * 1024),
85 (Size::Kilobytes(a), Size::Megabytes(b)) => calc(a * 1024, b * 1024 * 1024),
86 (Size::Kilobytes(a), Size::Gigabytes(b)) => calc(a * 1024, b * 1024 * 1024 * 1024),
87
88 (Size::Megabytes(a), Size::Bytes(b)) => calc(a * 1024 * 1024, b),
89 (Size::Megabytes(a), Size::Kilobytes(b)) => calc(a * 1024 * 1024, b * 1024),
90 (Size::Megabytes(a), Size::Megabytes(b)) => calc(a * 1024 * 1024, b * 1024 * 1024),
91 (Size::Megabytes(a), Size::Gigabytes(b)) => {
92 calc(a * 1024 * 1024, b * 1024 * 1024 * 1024)
93 }
94
95 (Size::Gigabytes(a), Size::Bytes(b)) => calc(a * 1024 * 1024 * 1024, b),
96 (Size::Gigabytes(a), Size::Kilobytes(b)) => calc(a * 1024 * 1024 * 1024, b * 1024),
97 (Size::Gigabytes(a), Size::Megabytes(b)) => {
98 calc(a * 1024 * 1024 * 1024, b * 1024 * 1024)
99 }
100 (Size::Gigabytes(a), Size::Gigabytes(b)) => {
101 calc(a * 1024 * 1024 * 1024, b * 1024 * 1024 * 1024)
102 }
103 }
104 }
105}
106
107pub fn size_to_usize(size: Size) -> usize {
108 match size {
109 Size::Bytes(bytes) => bytes,
110 Size::Kilobytes(kilobytes) => kilobytes * 1024,
111 Size::Megabytes(megabytes) => megabytes * 1024 * 1024,
112 Size::Gigabytes(gigabytes) => gigabytes * 1024 * 1024 * 1024,
113 }
114}
115
116pub type Result<T> = std::result::Result<T, Error>;
117
118#[derive(Debug, Clone)]
119pub struct Error {
120 pub code: ErrorCode,
121 pub message: String,
122}
123
124#[derive(Debug, Clone)]
125pub enum ErrorCode {
126 NotFound,
127 KeyExists,
128 KeyNotExists,
129}
130
131impl std::fmt::Display for Error {
132 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
133 write!(f, "Code: {} - Message: {}", self.code, self.message)
134 }
135}
136
137impl std::fmt::Display for ErrorCode {
138 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
139 match self {
140 ErrorCode::NotFound => write!(f, "NotFound"),
141 ErrorCode::KeyExists => write!(f, "KeyExists"),
142 ErrorCode::KeyNotExists => write!(f, "KeyNotExists"),
143 }
144 }
145}
146
147impl DustData {
148 pub fn new(configuration: DustDataConfig) -> Self {
149 let lsm = storage::lsm::Lsm::new(lsm::LsmConfig {
150 flush_threshold: size_to_usize(configuration.clone().lsm_config.flush_threshold),
151 sstable_path: configuration.clone().path,
152 });
153
154 Self {
155 lsm,
156 config: configuration,
157 }
158 }
159
160 pub fn get(&self, key: &str) -> Result<Option<bson::Bson>> {
166 self.lsm.get(key)
167 }
168
169 pub fn insert(&mut self, key: &str, bson: bson::Bson) -> Result<()> {
174 self.lsm.insert(key, bson)
175 }
176
177 pub fn delete(&mut self, key: &str) -> Result<()> {
181 self.lsm.delete(key)
182 }
183
184 pub fn update(&mut self, key: &str, bson: bson::Bson) -> Result<()> {
189 self.lsm.update(key, bson)
190 }
191
192 pub fn contains(&mut self, key: &str) -> bool {
196 self.lsm.contains(key)
197 }
198
199 pub fn list_keys(&self) -> Result<Vec<String>> {
203 Ok(self.lsm.list_keys())
204 }
205
206 pub fn flush(&mut self) -> Result<()> {
210 self.lsm.flush()
211 }
212}
213
214#[cfg(test)]
215mod size_tests {
216 use super::*;
217
218 #[test]
219 fn add_impl_bytes() {
220 let size = Size::Bytes(1);
221 let size2 = Size::Bytes(2);
222 assert_eq!(size + size2, Size::Bytes(3));
223 }
224
225 #[test]
226 fn add_impl_gb() {
227 let size = Size::Gigabytes(1);
228 let size2 = Size::Gigabytes(2);
229 assert_eq!(size + size2, Size::Gigabytes(3));
230 }
231
232 #[test]
233 fn add_impl_mb() {
234 let size = Size::Megabytes(1);
235 let size2 = Size::Megabytes(2);
236 assert_eq!(size + size2, Size::Megabytes(3));
237 }
238
239 #[test]
240 fn add_impl_kb() {
241 let size = Size::Kilobytes(1);
242 let size2 = Size::Kilobytes(2);
243 assert_eq!(size + size2, Size::Kilobytes(3));
244 }
245}