leveldb/database/
snapshots.rs

1//! leveldb snapshots
2//!
3//! Snapshots give you a reference to the database at a certain
4//! point in time and won't change while you work with them.
5use cruzbit_leveldb_sys::*;
6
7use super::bytes::Bytes;
8use super::db::{Database, DatabaseReader};
9use super::error::Error;
10use super::iterator::{Iterable, Iterator, KeyIterator, ValueIterator};
11use super::key::IntoLevelDBKey;
12use super::options::{c_readoptions, ReadOptions};
13use libc::{c_char, size_t};
14use std::ptr;
15
16#[allow(missing_docs)]
17struct RawSnapshot {
18    db_ptr: *mut leveldb_t,
19    ptr: *mut leveldb_snapshot_t,
20}
21
22impl Drop for RawSnapshot {
23    fn drop(&mut self) {
24        unsafe { leveldb_release_snapshot(self.db_ptr, self.ptr) };
25    }
26}
27
28/// A database snapshot
29///
30/// Represents a database at a certain point in time,
31/// and allows for all read operations (get and iteration).
32pub struct Snapshot<'a> {
33    raw: RawSnapshot,
34    database: &'a Database,
35}
36
37impl<'a> Snapshot<'a> {
38    /// fetches a key from the database
39    ///
40    /// Inserts this snapshot into ReadOptions before reading
41
42    pub fn get(
43        &self,
44        options: &ReadOptions,
45        key: &dyn IntoLevelDBKey,
46    ) -> Result<Option<Vec<u8>>, Error> {
47        key.as_u8_slice_for_get(&|k| self.get_u8(options, k))
48    }
49
50    /// override the get_u8 of Database. Overriding is for avoiding the snapshot field of ReadOption,
51    /// if so, a lifetime parameter must be added for ReadOption.
52    pub fn get_u8(&self, options: &ReadOptions, key: &[u8]) -> Result<Option<Vec<u8>>, Error> {
53        unsafe {
54            let mut error = ptr::null_mut();
55            let mut length: size_t = 0;
56            let c_readoptions = c_readoptions(options);
57
58            // add the extra snapshot information to c_readoptions
59            leveldb_readoptions_set_snapshot(c_readoptions, self.raw_ptr());
60
61            let result = leveldb_get(
62                self.database.database.ptr,
63                c_readoptions,
64                key.as_ptr() as *mut c_char,
65                key.len() as size_t,
66                &mut length,
67                &mut error,
68            );
69
70            leveldb_readoptions_destroy(c_readoptions);
71
72            if error.is_null() {
73                let bytes_opt = Bytes::from_raw(result as *mut u8, length);
74
75                Ok(bytes_opt.map(|val| val.into()))
76            } else {
77                Err(Error::new_from_char(error))
78            }
79        }
80    }
81
82    #[inline]
83    #[allow(missing_docs)]
84    pub fn raw_ptr(&self) -> *mut leveldb_snapshot_t {
85        self.raw.ptr
86    }
87}
88
89/// Structs implementing the Snapshots trait can be
90/// snapshotted.
91pub trait Snapshots {
92    /// Creates a snapshot and returns a struct
93    /// representing it.
94    fn snapshot(&self) -> Snapshot;
95}
96
97impl Snapshots for Database {
98    fn snapshot(&self) -> Snapshot {
99        let db_str = self.database.ptr;
100        let snap = unsafe { leveldb_create_snapshot(db_str) };
101
102        let raw = RawSnapshot {
103            db_ptr: db_str,
104            ptr: snap,
105        };
106
107        Snapshot {
108            raw,
109            database: self,
110        }
111    }
112}
113
114impl<'a> Iterable<'a> for Snapshot<'a> {
115    fn iter(&'a self, options: &ReadOptions) -> Iterator<'a> {
116        Iterator::new(self.database, options, Some(self))
117    }
118
119    fn keys_iter(&'a self, options: &ReadOptions) -> KeyIterator<'a> {
120        KeyIterator::new(self.database, options, Some(self))
121    }
122
123    fn value_iter(&'a self, options: &ReadOptions) -> ValueIterator<'a> {
124        ValueIterator::new(self.database, options, Some(self))
125    }
126}
127
128impl DatabaseReader for Snapshot<'_> {
129    fn get(
130        &self,
131        options: &ReadOptions,
132        key: &dyn IntoLevelDBKey,
133    ) -> Result<Option<Vec<u8>>, Error> {
134        self.get(options, key)
135    }
136
137    fn get_u8(
138        &self,
139        options: &ReadOptions,
140        key: &[u8],
141    ) -> Result<Option<Vec<u8>>, Error> {
142        self.get_u8(options, key)
143    }
144}