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