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 leveldb_sys::*;
6
7use super::db::Database;
8use super::error::Error;
9use super::options::{ReadOptions, c_readoptions};
10use super::key::IntoLevelDBKey;
11use super::iterator::{Iterable, Iterator, KeyIterator, ValueIterator};
12use super::bytes::Bytes;
13use std::ptr;
14use libc::{c_char, size_t};
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
37
38impl<'a> Snapshot<'a> {
39    /// fetches a key from the database
40    ///
41    /// Inserts this snapshot into ReadOptions before reading
42
43    pub fn get(&self,
44                  options: &ReadOptions,
45                  key: &dyn IntoLevelDBKey)
46                  -> Result<Option<Vec<u8>>, Error> {
47        key.as_u8_slice_for_get(& |k| {
48            self.get_u8(options, k)
49        })
50    }
51
52
53    /// override the get_u8 of Database. Overriding is for avoiding the snapshot field of ReadOption,
54    /// if so, a lifetime parameter must be added for ReadOption.
55    pub fn get_u8(&self,
56               options: &ReadOptions,
57               key: &[u8])
58               -> Result<Option<Vec<u8>>, Error> {
59        unsafe {
60            let mut error = ptr::null_mut();
61            let mut length: size_t = 0;
62            let c_readoptions = c_readoptions(options);
63
64            // add the extra snapshot information to c_readoptions
65            leveldb_readoptions_set_snapshot(c_readoptions, self.raw_ptr());
66
67            let result = leveldb_get(self.database.database.ptr,
68                                     c_readoptions,
69                                     key.as_ptr() as *mut c_char,
70                                     key.len() as size_t,
71                                     &mut length,
72                                     &mut error);
73
74            leveldb_readoptions_destroy(c_readoptions);
75
76            if error == ptr::null_mut() {
77                let bytes_opt = Bytes::from_raw(result as *mut u8, length);
78
79                Ok(bytes_opt.map(|val| {val.into()}))
80            } else {
81                Err(Error::new_from_char(error))
82            }
83        }
84
85    }
86
87    #[inline]
88    #[allow(missing_docs)]
89    pub fn raw_ptr(&self) -> *mut leveldb_snapshot_t {
90        self.raw.ptr
91    }
92}
93
94/// Structs implementing the Snapshots trait can be
95/// snapshotted.
96pub trait Snapshots {
97    /// Creates a snapshot and returns a struct
98    /// representing it.
99    fn snapshot(&self) -> Snapshot;
100}
101
102impl Snapshots for Database {
103    fn snapshot(&self) -> Snapshot {
104        let db_str = self.database.ptr;
105        let snap = unsafe {
106            leveldb_create_snapshot(db_str)
107        };
108
109        let raw = RawSnapshot {
110            db_ptr: db_str,
111            ptr: snap,
112        };
113
114        Snapshot {
115            raw,
116            database: self
117        }
118    }
119}
120
121impl<'a> Iterable<'a> for Snapshot<'a> {
122    fn iter(&'a self, options: &ReadOptions) -> Iterator<'a> {
123        Iterator::new(self.database, options, Some(self))
124    }
125
126    fn keys_iter(&'a self, options: &ReadOptions) -> KeyIterator<'a> {
127        KeyIterator::new(self.database, options, Some(self))
128    }
129
130    fn value_iter(&'a self, options: &ReadOptions)-> ValueIterator<'a> {
131        ValueIterator::new(self.database, options, Some(self))
132    }
133}
134