Skip to main content

rust_rocksdb/
snapshot.rs

1// Copyright 2020 Tyler Neely
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{
16    AsColumnFamilyRef, DB, DBIteratorWithThreadMode, DBPinnableSlice, DBRawIteratorWithThreadMode,
17    Error, IteratorMode, ReadOptions, db::DBAccess, ffi,
18};
19
20/// A type alias to keep compatibility. See [`SnapshotWithThreadMode`] for details
21pub type Snapshot<'a> = SnapshotWithThreadMode<'a, DB>;
22
23/// A consistent view of the database at the point of creation.
24///
25/// # Examples
26///
27/// ```
28/// use rust_rocksdb::{DB, IteratorMode, Options};
29///
30/// let tempdir = tempfile::Builder::new()
31///     .prefix("_path_for_rocksdb_storage3")
32///     .tempdir()
33///     .expect("Failed to create temporary path for the _path_for_rocksdb_storage3");
34/// let path = tempdir.path();
35/// {
36///     let db = DB::open_default(path).unwrap();
37///     let snapshot = db.snapshot(); // Creates a longer-term snapshot of the DB, but closed when goes out of scope
38///     let mut iter = snapshot.iterator(IteratorMode::Start); // Make as many iterators as you'd like from one snapshot
39/// }
40/// let _ = DB::destroy(&Options::default(), path);
41/// ```
42///
43pub struct SnapshotWithThreadMode<'a, D: DBAccess> {
44    db: &'a D,
45    pub(crate) inner: *const ffi::rocksdb_snapshot_t,
46}
47
48impl<'a, D: DBAccess> SnapshotWithThreadMode<'a, D> {
49    /// Creates a new `SnapshotWithThreadMode` of the database `db`.
50    pub fn new(db: &'a D) -> Self {
51        let snapshot = unsafe { db.create_snapshot() };
52        Self {
53            db,
54            inner: snapshot,
55        }
56    }
57
58    /// Returns the sequence number of the snapshot.
59    pub fn sequence_number(&self) -> u64 {
60        unsafe { ffi::rocksdb_snapshot_get_sequence_number(self.inner) }
61    }
62
63    /// Creates an iterator over the data in this snapshot, using the default read options.
64    pub fn iterator(&self, mode: IteratorMode) -> DBIteratorWithThreadMode<'a, D> {
65        let readopts = ReadOptions::default();
66        self.iterator_opt(mode, readopts)
67    }
68
69    /// Creates an iterator over the data in this snapshot under the given column family, using
70    /// the default read options.
71    pub fn iterator_cf(
72        &'_ self,
73        cf_handle: &impl AsColumnFamilyRef,
74        mode: IteratorMode,
75    ) -> DBIteratorWithThreadMode<'_, D> {
76        let readopts = ReadOptions::default();
77        self.iterator_cf_opt(cf_handle, readopts, mode)
78    }
79
80    /// Creates an iterator over the data in this snapshot, using the given read options.
81    pub fn iterator_opt(
82        &self,
83        mode: IteratorMode,
84        mut readopts: ReadOptions,
85    ) -> DBIteratorWithThreadMode<'a, D> {
86        readopts.set_snapshot(self);
87        DBIteratorWithThreadMode::<D>::new(self.db, readopts, mode)
88    }
89
90    /// Creates an iterator over the data in this snapshot under the given column family, using
91    /// the given read options.
92    pub fn iterator_cf_opt(
93        &'_ self,
94        cf_handle: &impl AsColumnFamilyRef,
95        mut readopts: ReadOptions,
96        mode: IteratorMode,
97    ) -> DBIteratorWithThreadMode<'_, D> {
98        readopts.set_snapshot(self);
99        DBIteratorWithThreadMode::new_cf(self.db, cf_handle.inner(), readopts, mode)
100    }
101
102    /// Creates a raw iterator over the data in this snapshot, using the default read options.
103    pub fn raw_iterator(&'_ self) -> DBRawIteratorWithThreadMode<'_, D> {
104        let readopts = ReadOptions::default();
105        self.raw_iterator_opt(readopts)
106    }
107
108    /// Creates a raw iterator over the data in this snapshot under the given column family, using
109    /// the default read options.
110    pub fn raw_iterator_cf(
111        &'_ self,
112        cf_handle: &impl AsColumnFamilyRef,
113    ) -> DBRawIteratorWithThreadMode<'_, D> {
114        let readopts = ReadOptions::default();
115        self.raw_iterator_cf_opt(cf_handle, readopts)
116    }
117
118    /// Creates a raw iterator over the data in this snapshot, using the given read options.
119    pub fn raw_iterator_opt(
120        &'_ self,
121        mut readopts: ReadOptions,
122    ) -> DBRawIteratorWithThreadMode<'_, D> {
123        readopts.set_snapshot(self);
124        DBRawIteratorWithThreadMode::new(self.db, readopts)
125    }
126
127    /// Creates a raw iterator over the data in this snapshot under the given column family, using
128    /// the given read options.
129    pub fn raw_iterator_cf_opt(
130        &'_ self,
131        cf_handle: &impl AsColumnFamilyRef,
132        mut readopts: ReadOptions,
133    ) -> DBRawIteratorWithThreadMode<'_, D> {
134        readopts.set_snapshot(self);
135        DBRawIteratorWithThreadMode::new_cf(self.db, cf_handle.inner(), readopts)
136    }
137
138    /// Returns the bytes associated with a key value with default read options.
139    pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<Vec<u8>>, Error> {
140        let readopts = ReadOptions::default();
141        self.get_opt(key, readopts)
142    }
143
144    /// Returns the bytes associated with a key value and given column family with default read
145    /// options.
146    pub fn get_cf<K: AsRef<[u8]>>(
147        &self,
148        cf: &impl AsColumnFamilyRef,
149        key: K,
150    ) -> Result<Option<Vec<u8>>, Error> {
151        let readopts = ReadOptions::default();
152        self.get_cf_opt(cf, key.as_ref(), readopts)
153    }
154
155    /// Returns the bytes associated with a key value and given read options.
156    pub fn get_opt<K: AsRef<[u8]>>(
157        &self,
158        key: K,
159        mut readopts: ReadOptions,
160    ) -> Result<Option<Vec<u8>>, Error> {
161        readopts.set_snapshot(self);
162        self.db.get_opt(key.as_ref(), &readopts)
163    }
164
165    /// Returns the bytes associated with a key value, given column family and read options.
166    pub fn get_cf_opt<K: AsRef<[u8]>>(
167        &self,
168        cf: &impl AsColumnFamilyRef,
169        key: K,
170        mut readopts: ReadOptions,
171    ) -> Result<Option<Vec<u8>>, Error> {
172        readopts.set_snapshot(self);
173        self.db.get_cf_opt(cf, key.as_ref(), &readopts)
174    }
175
176    /// Return the value associated with a key using RocksDB's PinnableSlice
177    /// so as to avoid unnecessary memory copy. Similar to get_pinned_opt but
178    /// leverages default options.
179    pub fn get_pinned<K: AsRef<[u8]>>(
180        &'_ self,
181        key: K,
182    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
183        let readopts = ReadOptions::default();
184        self.get_pinned_opt(key, readopts)
185    }
186
187    /// Return the value associated with a key using RocksDB's PinnableSlice
188    /// so as to avoid unnecessary memory copy. Similar to get_pinned_cf_opt but
189    /// leverages default options.
190    pub fn get_pinned_cf<K: AsRef<[u8]>>(
191        &'_ self,
192        cf: &impl AsColumnFamilyRef,
193        key: K,
194    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
195        let readopts = ReadOptions::default();
196        self.get_pinned_cf_opt(cf, key.as_ref(), readopts)
197    }
198
199    /// Return the value associated with a key using RocksDB's PinnableSlice
200    /// so as to avoid unnecessary memory copy.
201    pub fn get_pinned_opt<K: AsRef<[u8]>>(
202        &'_ self,
203        key: K,
204        mut readopts: ReadOptions,
205    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
206        readopts.set_snapshot(self);
207        self.db.get_pinned_opt(key.as_ref(), &readopts)
208    }
209
210    /// Return the value associated with a key using RocksDB's PinnableSlice
211    /// so as to avoid unnecessary memory copy. Similar to get_pinned_opt but
212    /// allows specifying ColumnFamily.
213    pub fn get_pinned_cf_opt<K: AsRef<[u8]>>(
214        &'_ self,
215        cf: &impl AsColumnFamilyRef,
216        key: K,
217        mut readopts: ReadOptions,
218    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
219        readopts.set_snapshot(self);
220        self.db.get_pinned_cf_opt(cf, key.as_ref(), &readopts)
221    }
222
223    /// Returns the bytes associated with the given key values and default read options.
224    pub fn multi_get<K: AsRef<[u8]>, I>(&self, keys: I) -> Vec<Result<Option<Vec<u8>>, Error>>
225    where
226        I: IntoIterator<Item = K>,
227    {
228        let readopts = ReadOptions::default();
229        self.multi_get_opt(keys, readopts)
230    }
231
232    /// Returns the bytes associated with the given key values and default read options.
233    pub fn multi_get_cf<'b, K, I, W>(&self, keys_cf: I) -> Vec<Result<Option<Vec<u8>>, Error>>
234    where
235        K: AsRef<[u8]>,
236        I: IntoIterator<Item = (&'b W, K)>,
237        W: AsColumnFamilyRef + 'b,
238    {
239        let readopts = ReadOptions::default();
240        self.multi_get_cf_opt(keys_cf, readopts)
241    }
242
243    /// Returns the bytes associated with the given key values and given read options.
244    pub fn multi_get_opt<K, I>(
245        &self,
246        keys: I,
247        mut readopts: ReadOptions,
248    ) -> Vec<Result<Option<Vec<u8>>, Error>>
249    where
250        K: AsRef<[u8]>,
251        I: IntoIterator<Item = K>,
252    {
253        readopts.set_snapshot(self);
254        self.db.multi_get_opt(keys, &readopts)
255    }
256
257    /// Returns the bytes associated with the given key values, given column family and read options.
258    pub fn multi_get_cf_opt<'b, K, I, W>(
259        &self,
260        keys_cf: I,
261        mut readopts: ReadOptions,
262    ) -> Vec<Result<Option<Vec<u8>>, Error>>
263    where
264        K: AsRef<[u8]>,
265        I: IntoIterator<Item = (&'b W, K)>,
266        W: AsColumnFamilyRef + 'b,
267    {
268        readopts.set_snapshot(self);
269        self.db.multi_get_cf_opt(keys_cf, &readopts)
270    }
271}
272
273impl<D: DBAccess> Drop for SnapshotWithThreadMode<'_, D> {
274    fn drop(&mut self) {
275        unsafe {
276            self.db.release_snapshot(self.inner);
277        }
278    }
279}
280
281/// `Send` and `Sync` implementations for `SnapshotWithThreadMode` are safe, because `SnapshotWithThreadMode` is
282/// immutable and can be safely shared between threads.
283unsafe impl<D: DBAccess> Send for SnapshotWithThreadMode<'_, D> {}
284unsafe impl<D: DBAccess> Sync for SnapshotWithThreadMode<'_, D> {}