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 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(&self, mut readopts: ReadOptions) -> DBRawIteratorWithThreadMode<D> {
115        readopts.set_snapshot(self);
116        DBRawIteratorWithThreadMode::new(self.db, readopts)
117    }
118
119    /// Creates a raw iterator over the data in this snapshot under the given column family, using
120    /// the given read options.
121    pub fn raw_iterator_cf_opt(
122        &self,
123        cf_handle: &impl AsColumnFamilyRef,
124        mut readopts: ReadOptions,
125    ) -> DBRawIteratorWithThreadMode<D> {
126        readopts.set_snapshot(self);
127        DBRawIteratorWithThreadMode::new_cf(self.db, cf_handle.inner(), readopts)
128    }
129
130    /// Returns the bytes associated with a key value with default read options.
131    pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<Vec<u8>>, Error> {
132        let readopts = ReadOptions::default();
133        self.get_opt(key, readopts)
134    }
135
136    /// Returns the bytes associated with a key value and given column family with default read
137    /// options.
138    pub fn get_cf<K: AsRef<[u8]>>(
139        &self,
140        cf: &impl AsColumnFamilyRef,
141        key: K,
142    ) -> Result<Option<Vec<u8>>, Error> {
143        let readopts = ReadOptions::default();
144        self.get_cf_opt(cf, key.as_ref(), readopts)
145    }
146
147    /// Returns the bytes associated with a key value and given read options.
148    pub fn get_opt<K: AsRef<[u8]>>(
149        &self,
150        key: K,
151        mut readopts: ReadOptions,
152    ) -> Result<Option<Vec<u8>>, Error> {
153        readopts.set_snapshot(self);
154        self.db.get_opt(key.as_ref(), &readopts)
155    }
156
157    /// Returns the bytes associated with a key value, given column family and read options.
158    pub fn get_cf_opt<K: AsRef<[u8]>>(
159        &self,
160        cf: &impl AsColumnFamilyRef,
161        key: K,
162        mut readopts: ReadOptions,
163    ) -> Result<Option<Vec<u8>>, Error> {
164        readopts.set_snapshot(self);
165        self.db.get_cf_opt(cf, key.as_ref(), &readopts)
166    }
167
168    /// Return the value associated with a key using RocksDB's PinnableSlice
169    /// so as to avoid unnecessary memory copy. Similar to get_pinned_opt but
170    /// leverages default options.
171    pub fn get_pinned<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<DBPinnableSlice>, Error> {
172        let readopts = ReadOptions::default();
173        self.get_pinned_opt(key, 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_cf_opt but
178    /// leverages default options.
179    pub fn get_pinned_cf<K: AsRef<[u8]>>(
180        &self,
181        cf: &impl AsColumnFamilyRef,
182        key: K,
183    ) -> Result<Option<DBPinnableSlice>, Error> {
184        let readopts = ReadOptions::default();
185        self.get_pinned_cf_opt(cf, key.as_ref(), readopts)
186    }
187
188    /// Return the value associated with a key using RocksDB's PinnableSlice
189    /// so as to avoid unnecessary memory copy.
190    pub fn get_pinned_opt<K: AsRef<[u8]>>(
191        &self,
192        key: K,
193        mut readopts: ReadOptions,
194    ) -> Result<Option<DBPinnableSlice>, Error> {
195        readopts.set_snapshot(self);
196        self.db.get_pinned_opt(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. Similar to get_pinned_opt but
201    /// allows specifying ColumnFamily.
202    pub fn get_pinned_cf_opt<K: AsRef<[u8]>>(
203        &self,
204        cf: &impl AsColumnFamilyRef,
205        key: K,
206        mut readopts: ReadOptions,
207    ) -> Result<Option<DBPinnableSlice>, Error> {
208        readopts.set_snapshot(self);
209        self.db.get_pinned_cf_opt(cf, key.as_ref(), &readopts)
210    }
211
212    /// Returns the bytes associated with the given key values and default read options.
213    pub fn multi_get<K: AsRef<[u8]>, I>(&self, keys: I) -> Vec<Result<Option<Vec<u8>>, Error>>
214    where
215        I: IntoIterator<Item = K>,
216    {
217        let readopts = ReadOptions::default();
218        self.multi_get_opt(keys, readopts)
219    }
220
221    /// Returns the bytes associated with the given key values and default read options.
222    pub fn multi_get_cf<'b, K, I, W>(&self, keys_cf: I) -> Vec<Result<Option<Vec<u8>>, Error>>
223    where
224        K: AsRef<[u8]>,
225        I: IntoIterator<Item = (&'b W, K)>,
226        W: AsColumnFamilyRef + 'b,
227    {
228        let readopts = ReadOptions::default();
229        self.multi_get_cf_opt(keys_cf, readopts)
230    }
231
232    /// Returns the bytes associated with the given key values and given read options.
233    pub fn multi_get_opt<K, I>(
234        &self,
235        keys: I,
236        mut readopts: ReadOptions,
237    ) -> Vec<Result<Option<Vec<u8>>, Error>>
238    where
239        K: AsRef<[u8]>,
240        I: IntoIterator<Item = K>,
241    {
242        readopts.set_snapshot(self);
243        self.db.multi_get_opt(keys, &readopts)
244    }
245
246    /// Returns the bytes associated with the given key values, given column family and read options.
247    pub fn multi_get_cf_opt<'b, K, I, W>(
248        &self,
249        keys_cf: I,
250        mut readopts: ReadOptions,
251    ) -> Vec<Result<Option<Vec<u8>>, Error>>
252    where
253        K: AsRef<[u8]>,
254        I: IntoIterator<Item = (&'b W, K)>,
255        W: AsColumnFamilyRef + 'b,
256    {
257        readopts.set_snapshot(self);
258        self.db.multi_get_cf_opt(keys_cf, &readopts)
259    }
260}
261
262impl<D: DBAccess> Drop for SnapshotWithThreadMode<'_, D> {
263    fn drop(&mut self) {
264        unsafe {
265            self.db.release_snapshot(self.inner);
266        }
267    }
268}
269
270/// `Send` and `Sync` implementations for `SnapshotWithThreadMode` are safe, because `SnapshotWithThreadMode` is
271/// immutable and can be safely shared between threads.
272unsafe impl<D: DBAccess> Send for SnapshotWithThreadMode<'_, D> {}
273unsafe impl<D: DBAccess> Sync for SnapshotWithThreadMode<'_, D> {}