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    db::DBAccess, ffi, AsColumnFamilyRef, DBIteratorWithThreadMode, DBPinnableSlice,
17    DBRawIteratorWithThreadMode, Error, IteratorMode, ReadOptions, DB,
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    /// Creates an iterator over the data in this snapshot, using the default read options.
59    pub fn iterator(&self, mode: IteratorMode) -> DBIteratorWithThreadMode<'a, D> {
60        let readopts = ReadOptions::default();
61        self.iterator_opt(mode, readopts)
62    }
63
64    /// Creates an iterator over the data in this snapshot under the given column family, using
65    /// the default read options.
66    pub fn iterator_cf(
67        &'_ self,
68        cf_handle: &impl AsColumnFamilyRef,
69        mode: IteratorMode,
70    ) -> DBIteratorWithThreadMode<'_, D> {
71        let readopts = ReadOptions::default();
72        self.iterator_cf_opt(cf_handle, readopts, mode)
73    }
74
75    /// Creates an iterator over the data in this snapshot, using the given read options.
76    pub fn iterator_opt(
77        &self,
78        mode: IteratorMode,
79        mut readopts: ReadOptions,
80    ) -> DBIteratorWithThreadMode<'a, D> {
81        readopts.set_snapshot(self);
82        DBIteratorWithThreadMode::<D>::new(self.db, readopts, mode)
83    }
84
85    /// Creates an iterator over the data in this snapshot under the given column family, using
86    /// the given read options.
87    pub fn iterator_cf_opt(
88        &'_ self,
89        cf_handle: &impl AsColumnFamilyRef,
90        mut readopts: ReadOptions,
91        mode: IteratorMode,
92    ) -> DBIteratorWithThreadMode<'_, D> {
93        readopts.set_snapshot(self);
94        DBIteratorWithThreadMode::new_cf(self.db, cf_handle.inner(), readopts, mode)
95    }
96
97    /// Creates a raw iterator over the data in this snapshot, using the default read options.
98    pub fn raw_iterator(&'_ self) -> DBRawIteratorWithThreadMode<'_, D> {
99        let readopts = ReadOptions::default();
100        self.raw_iterator_opt(readopts)
101    }
102
103    /// Creates a raw iterator over the data in this snapshot under the given column family, using
104    /// the default read options.
105    pub fn raw_iterator_cf(
106        &'_ self,
107        cf_handle: &impl AsColumnFamilyRef,
108    ) -> DBRawIteratorWithThreadMode<'_, D> {
109        let readopts = ReadOptions::default();
110        self.raw_iterator_cf_opt(cf_handle, readopts)
111    }
112
113    /// Creates a raw iterator over the data in this snapshot, using the given read options.
114    pub fn raw_iterator_opt(
115        &'_ self,
116        mut readopts: ReadOptions,
117    ) -> DBRawIteratorWithThreadMode<'_, D> {
118        readopts.set_snapshot(self);
119        DBRawIteratorWithThreadMode::new(self.db, readopts)
120    }
121
122    /// Creates a raw iterator over the data in this snapshot under the given column family, using
123    /// the given read options.
124    pub fn raw_iterator_cf_opt(
125        &'_ self,
126        cf_handle: &impl AsColumnFamilyRef,
127        mut readopts: ReadOptions,
128    ) -> DBRawIteratorWithThreadMode<'_, D> {
129        readopts.set_snapshot(self);
130        DBRawIteratorWithThreadMode::new_cf(self.db, cf_handle.inner(), readopts)
131    }
132
133    /// Returns the bytes associated with a key value with default read options.
134    pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<Vec<u8>>, Error> {
135        let readopts = ReadOptions::default();
136        self.get_opt(key, readopts)
137    }
138
139    /// Returns the bytes associated with a key value and given column family with default read
140    /// options.
141    pub fn get_cf<K: AsRef<[u8]>>(
142        &self,
143        cf: &impl AsColumnFamilyRef,
144        key: K,
145    ) -> Result<Option<Vec<u8>>, Error> {
146        let readopts = ReadOptions::default();
147        self.get_cf_opt(cf, key.as_ref(), readopts)
148    }
149
150    /// Returns the bytes associated with a key value and given read options.
151    pub fn get_opt<K: AsRef<[u8]>>(
152        &self,
153        key: K,
154        mut readopts: ReadOptions,
155    ) -> Result<Option<Vec<u8>>, Error> {
156        readopts.set_snapshot(self);
157        self.db.get_opt(key.as_ref(), &readopts)
158    }
159
160    /// Returns the bytes associated with a key value, given column family and read options.
161    pub fn get_cf_opt<K: AsRef<[u8]>>(
162        &self,
163        cf: &impl AsColumnFamilyRef,
164        key: K,
165        mut readopts: ReadOptions,
166    ) -> Result<Option<Vec<u8>>, Error> {
167        readopts.set_snapshot(self);
168        self.db.get_cf_opt(cf, key.as_ref(), &readopts)
169    }
170
171    /// Return the value associated with a key using RocksDB's PinnableSlice
172    /// so as to avoid unnecessary memory copy. Similar to get_pinned_opt but
173    /// leverages default options.
174    pub fn get_pinned<K: AsRef<[u8]>>(
175        &'_ self,
176        key: K,
177    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
178        let readopts = ReadOptions::default();
179        self.get_pinned_opt(key, readopts)
180    }
181
182    /// Return the value associated with a key using RocksDB's PinnableSlice
183    /// so as to avoid unnecessary memory copy. Similar to get_pinned_cf_opt but
184    /// leverages default options.
185    pub fn get_pinned_cf<K: AsRef<[u8]>>(
186        &'_ self,
187        cf: &impl AsColumnFamilyRef,
188        key: K,
189    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
190        let readopts = ReadOptions::default();
191        self.get_pinned_cf_opt(cf, key.as_ref(), readopts)
192    }
193
194    /// Return the value associated with a key using RocksDB's PinnableSlice
195    /// so as to avoid unnecessary memory copy.
196    pub fn get_pinned_opt<K: AsRef<[u8]>>(
197        &'_ self,
198        key: K,
199        mut readopts: ReadOptions,
200    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
201        readopts.set_snapshot(self);
202        self.db.get_pinned_opt(key.as_ref(), &readopts)
203    }
204
205    /// Return the value associated with a key using RocksDB's PinnableSlice
206    /// so as to avoid unnecessary memory copy. Similar to get_pinned_opt but
207    /// allows specifying ColumnFamily.
208    pub fn get_pinned_cf_opt<K: AsRef<[u8]>>(
209        &'_ self,
210        cf: &impl AsColumnFamilyRef,
211        key: K,
212        mut readopts: ReadOptions,
213    ) -> Result<Option<DBPinnableSlice<'_>>, Error> {
214        readopts.set_snapshot(self);
215        self.db.get_pinned_cf_opt(cf, key.as_ref(), &readopts)
216    }
217
218    /// Returns the bytes associated with the given key values and default read options.
219    pub fn multi_get<K: AsRef<[u8]>, I>(&self, keys: I) -> Vec<Result<Option<Vec<u8>>, Error>>
220    where
221        I: IntoIterator<Item = K>,
222    {
223        let readopts = ReadOptions::default();
224        self.multi_get_opt(keys, readopts)
225    }
226
227    /// Returns the bytes associated with the given key values and default read options.
228    pub fn multi_get_cf<'b, K, I, W>(&self, keys_cf: I) -> Vec<Result<Option<Vec<u8>>, Error>>
229    where
230        K: AsRef<[u8]>,
231        I: IntoIterator<Item = (&'b W, K)>,
232        W: AsColumnFamilyRef + 'b,
233    {
234        let readopts = ReadOptions::default();
235        self.multi_get_cf_opt(keys_cf, readopts)
236    }
237
238    /// Returns the bytes associated with the given key values and given read options.
239    pub fn multi_get_opt<K, I>(
240        &self,
241        keys: I,
242        mut readopts: ReadOptions,
243    ) -> Vec<Result<Option<Vec<u8>>, Error>>
244    where
245        K: AsRef<[u8]>,
246        I: IntoIterator<Item = K>,
247    {
248        readopts.set_snapshot(self);
249        self.db.multi_get_opt(keys, &readopts)
250    }
251
252    /// Returns the bytes associated with the given key values, given column family and read options.
253    pub fn multi_get_cf_opt<'b, K, I, W>(
254        &self,
255        keys_cf: I,
256        mut readopts: ReadOptions,
257    ) -> Vec<Result<Option<Vec<u8>>, Error>>
258    where
259        K: AsRef<[u8]>,
260        I: IntoIterator<Item = (&'b W, K)>,
261        W: AsColumnFamilyRef + 'b,
262    {
263        readopts.set_snapshot(self);
264        self.db.multi_get_cf_opt(keys_cf, &readopts)
265    }
266}
267
268impl<D: DBAccess> Drop for SnapshotWithThreadMode<'_, D> {
269    fn drop(&mut self) {
270        unsafe {
271            self.db.release_snapshot(self.inner);
272        }
273    }
274}
275
276/// `Send` and `Sync` implementations for `SnapshotWithThreadMode` are safe, because `SnapshotWithThreadMode` is
277/// immutable and can be safely shared between threads.
278unsafe impl<D: DBAccess> Send for SnapshotWithThreadMode<'_, D> {}
279unsafe impl<D: DBAccess> Sync for SnapshotWithThreadMode<'_, D> {}