1mod types;
2pub use types::*;
3
4mod reader;
5pub use reader::*;
6
7use crate::{
8 fdb_blob, fdb_blob_make_write, fdb_blob_read, fdb_db_t, fdb_tsdb, fdb_tsdb_control_read,
9 fdb_tsdb_control_write, fdb_tsdb_deinit, fdb_tsdb_init, fdb_tsdb_t, fdb_tsl_append_with_ts,
10 fdb_tsl_clean, fdb_tsl_iter, fdb_tsl_iter_by_time, fdb_tsl_iter_reverse, fdb_tsl_query_count,
11 fdb_tsl_set_status, Error, FlashDispatch, RawHandle, FDB_KV_NAME_MAX,
12 FDB_TSDB_CTRL_GET_LAST_TIME, FDB_TSDB_CTRL_GET_ROLLOVER, FDB_TSDB_CTRL_GET_SEC_SIZE,
13 FDB_TSDB_CTRL_SET_MAX_SIZE, FDB_TSDB_CTRL_SET_NOT_FORMAT, FDB_TSDB_CTRL_SET_ROLLOVER,
14 FDB_TSDB_CTRL_SET_SEC_SIZE,
15};
16
17use core::{
18 ffi::{c_char, c_void},
19 marker::PhantomData,
20};
21
22use embedded_storage::nor_flash::NorFlash;
23
24pub struct TSDB<S: NorFlash> {
25 inner: fdb_tsdb,
26 storage: S,
27 user_data: FlashDispatch,
28 #[cfg(feature = "log")]
29 name_buf: [u8; FDB_KV_NAME_MAX as usize + 1],
30 initialized: bool,
31 _marker: PhantomData<*const ()>,
34}
35
36#[cfg(feature = "std")]
37impl TSDB<crate::storage::StdStorage> {
38 pub fn new_file(
50 name: &str,
51 path: &str,
52 sec_size: u32,
53 max_size: u32,
54 entry_max: usize,
55 ) -> Result<Box<Self>, Error> {
56 let storage = crate::storage::StdStorage::new(
57 path,
58 name,
59 sec_size,
60 max_size,
61 crate::storage::FileStrategy::Multi,
62 )?;
63
64 let mut db = Box::new(TSDB::new(storage));
65 db.set_name(name)?;
66 db.init(entry_max)?;
67 Ok(db)
68 }
69}
70
71impl<S: NorFlash> TSDB<S> {
72 pub fn new(storage: S) -> Self {
77 Self {
78 inner: Default::default(),
79 storage,
80 user_data: FlashDispatch::new::<S>(),
81 #[cfg(feature = "log")]
82 name_buf: [0; FDB_KV_NAME_MAX as usize + 1],
83 initialized: false,
84 _marker: PhantomData,
85 }
86 }
87
88 pub fn set_name(&mut self, name: &str) -> Result<(), Error> {
92 if name.len() > FDB_KV_NAME_MAX as usize {
93 return Err(Error::KvNameError);
94 }
95 #[cfg(feature = "log")]
96 {
97 self.name_buf[..name.len()].copy_from_slice(name.as_bytes());
98 self.name_buf[name.len()] = b'\0';
99 }
100 Ok(())
101 }
102
103 pub fn set_not_formatable(&mut self, enable: bool) {
108 self.fdb_tsdb_control_write(FDB_TSDB_CTRL_SET_NOT_FORMAT, enable);
109 }
110
111 pub fn not_formatable(&mut self) -> bool {
113 let mut enable = false;
114 self.fdb_tsdb_control_read(FDB_TSDB_CTRL_SET_NOT_FORMAT, &mut enable);
115 return enable;
116 }
117
118 pub fn set_rollover(&mut self, enable: bool) {
124 self.fdb_tsdb_control_write(FDB_TSDB_CTRL_SET_ROLLOVER, enable);
125 }
126
127 pub fn rollover(&self) -> bool {
129 let mut flag = false;
130 self.fdb_tsdb_control_read(FDB_TSDB_CTRL_GET_ROLLOVER, &mut flag);
131 flag
132 }
133
134 pub fn sec_size(&self) -> u32 {
136 let mut size: u32 = 0;
137 self.fdb_tsdb_control_read(FDB_TSDB_CTRL_GET_SEC_SIZE, &mut size);
138 size
139 }
140
141 pub fn last_time(&self) -> i64 {
143 let mut size: i64 = 0;
144 self.fdb_tsdb_control_read(FDB_TSDB_CTRL_GET_LAST_TIME, &mut size);
145 size
146 }
147
148 pub fn init(&mut self, entry_max: usize) -> Result<(), Error> {
157 if self.initialized {
158 return Ok(());
159 }
160 let sec_size = S::ERASE_SIZE as u32;
162 let max_size = self.storage.capacity() as u32;
163
164 unsafe {
165 let db_ptr = self.handle() as fdb_db_t;
166 (*db_ptr).mode = crate::fdb_storage_type_FDB_STORAGE_CUSTOM;
167
168 self.fdb_tsdb_control_write(FDB_TSDB_CTRL_SET_SEC_SIZE, sec_size);
170 self.fdb_tsdb_control_write(FDB_TSDB_CTRL_SET_MAX_SIZE, max_size);
171
172 self.user_data.instance = &mut self.storage as *mut _ as *mut c_void;
174
175 #[cfg(feature = "log")]
176 let name = self.name_buf.as_ptr() as *const c_char;
177 #[cfg(not(feature = "log"))]
178 let name = b"\0".as_ptr() as *const c_char;
179
180 let result = fdb_tsdb_init(
181 db_ptr as *mut fdb_tsdb,
182 name,
183 core::ptr::null(),
184 None,
185 entry_max,
186 &mut self.user_data as *mut _ as *mut c_void,
187 );
188
189 if result == crate::fdb_err_t_FDB_NO_ERR {
190 self.initialized = true;
191 Ok(())
192 } else {
193 Err(result.into())
194 }
195 }
196 }
197}
198
199impl<S: NorFlash> TSDB<S> {
200 #[inline]
201 fn fdb_blob_read(&mut self, blob: &mut fdb_blob) -> usize {
202 unsafe { fdb_blob_read(self.handle() as *mut _, blob) }
203 }
204
205 #[inline]
206 fn fdb_tsdb_control_write<T>(&mut self, cmd: u32, arg: T) {
207 fdb_tsdb_control_write(self.handle(), cmd, arg)
208 }
209
210 #[inline]
211 fn fdb_tsdb_control_read<T>(&self, cmd: u32, arg: &mut T) {
212 fdb_tsdb_control_read(self.handle(), cmd, arg)
213 }
214}
215
216impl<S: NorFlash> TSDB<S> {
217 pub fn append_with_timestamp(&mut self, timestamp: i64, data: &[u8]) -> Result<(), Error> {
227 let mut blob = fdb_blob_make_write(data);
229 Error::convert(unsafe { fdb_tsl_append_with_ts(self.handle(), &mut blob, timestamp as _) })
231 }
232
233 pub fn set_status(&mut self, tsl: &mut TSLEntry, status: TSLStatus) -> Result<(), Error> {
243 Error::convert(unsafe { fdb_tsl_set_status(self.handle(), tsl.handle(), status as _) })
245 }
246
247 pub fn count(&mut self, from: i64, to: i64, status: TSLStatus) -> usize {
257 unsafe { fdb_tsl_query_count(self.handle(), from as _, to as _, status as _) }
258 }
259
260 pub fn tsdb_iter<F: FnMut(&mut TSDB<S>, &mut TSLEntry) -> bool + Send>(
267 &mut self,
268 callback: F,
269 reverse: bool,
270 ) {
271 let db = self.handle();
272 let mut callback_data = CallbackData { db: self, callback };
273 unsafe {
274 if reverse {
276 fdb_tsl_iter_reverse(
277 db,
278 Some(iter_callback::<S, F>),
279 &mut callback_data as *mut _ as *mut _,
280 )
281 } else {
282 fdb_tsl_iter(
283 db,
284 Some(iter_callback::<S, F>),
285 &mut callback_data as *mut _ as *mut _,
286 )
287 }
288 }
289 }
290
291 pub fn tsdb_iter_by_time<F: FnMut(&mut TSDB<S>, &mut TSLEntry) -> bool + Send>(
300 &mut self,
301 from: i64,
302 to: i64,
303 callback: F,
304 ) {
305 let db = self.handle();
306 let mut callback_data = CallbackData { db: self, callback };
307 unsafe {
308 fdb_tsl_iter_by_time(
309 db,
310 from as _,
311 to as _,
312 Some(iter_callback::<S, F>),
313 &mut callback_data as *mut _ as *mut _,
314 )
315 };
316 }
317
318 pub fn reset(&mut self) -> Result<(), Error> {
324 unsafe { fdb_tsl_clean(self.handle()) };
325 Ok(())
326 }
327
328 #[cfg(feature = "alloc")]
338 pub fn get_value(&mut self, tsl_obj: &TSLEntry) -> Result<Option<alloc::vec::Vec<u8>>, Error> {
339 let status = unsafe { core::mem::transmute(tsl_obj.status()) };
341 match status {
342 TSLStatus::PRE_WRITE | TSLStatus::Write | TSLStatus::UserStatus1 => {
344 let mut data: alloc::vec::Vec<u8> = alloc::vec::Vec::with_capacity(tsl_obj.value_len());
346 unsafe { data.set_len(tsl_obj.value_len()) };
347 let mut blob = fdb_blob_make_by_tsl(&mut data, tsl_obj, 0);
349
350 let read_len = self.fdb_blob_read(&mut blob);
352 if read_len != data.len() {
353 return Err(Error::ReadError);
354 }
355 Ok(Some(data))
356 }
357 TSLStatus::UNUSED | TSLStatus::Deleted | TSLStatus::UserStatus2 => Ok(None),
359 }
360 }
361
362 pub fn open_read(&mut self, entry: TSLEntry) -> TSDBReader<'_, S> {
370 TSDBReader::new(self, entry)
371 }
372}
373
374impl<S: NorFlash> RawHandle for TSDB<S> {
375 type Handle = fdb_tsdb_t;
376
377 fn handle(&self) -> Self::Handle {
378 &self.inner as *const _ as *mut _
379 }
380}
381
382impl<S: NorFlash> Drop for TSDB<S> {
383 fn drop(&mut self) {
384 if self.initialized {
385 unsafe {
386 fdb_tsdb_deinit(self.handle());
387 };
388 }
389 }
390}