ckb_rocksdb/
snapshot.rs

1// Copyright 2019 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//
15
16use crate::{
17    ColumnFamily, DB, DBRawIterator, DBVector, Error, ReadOptions, handle::ConstHandle, ops::*,
18};
19
20/// A consistent view of the database at the point of creation.
21///
22/// ```
23/// use ckb_rocksdb::{prelude::*, IteratorMode};
24/// # use ckb_rocksdb::TemporaryDBPath;
25///
26/// let path = "_path_for_rocksdb_storage3";
27/// # let path = TemporaryDBPath::new();
28/// # {
29///
30///     let db = DB::open_default(&path).unwrap();
31///     let snapshot = db.snapshot(); // Creates a longer-term snapshot of the DB, but closed when goes out of scope
32///     let mut iter = snapshot.iterator(IteratorMode::Start); // Make as many iterators as you'd like from one snapshot
33/// # }
34/// ```
35///
36pub struct Snapshot<'a> {
37    pub(crate) db: &'a DB,
38    pub(crate) inner: *const ffi::rocksdb_snapshot_t,
39}
40
41impl ConstHandle<ffi::rocksdb_snapshot_t> for Snapshot<'_> {
42    fn const_handle(&self) -> *const ffi::rocksdb_snapshot_t {
43        self.inner
44    }
45}
46
47impl Read for Snapshot<'_> {}
48
49impl GetCF<ReadOptions> for Snapshot<'_> {
50    fn get_cf_full<K: AsRef<[u8]>>(
51        &self,
52        cf: Option<&ColumnFamily>,
53        key: K,
54        readopts: Option<&ReadOptions>,
55    ) -> Result<Option<DBVector>, Error> {
56        let mut ro = readopts.cloned().unwrap_or_default();
57        ro.set_snapshot(self);
58
59        self.db.get_cf_full(cf, key, Some(&ro))
60    }
61}
62
63impl MultiGet<ReadOptions> for Snapshot<'_> {
64    fn multi_get_full<K, I>(
65        &self,
66        keys: I,
67        readopts: Option<&ReadOptions>,
68    ) -> Vec<Result<Option<DBVector>, Error>>
69    where
70        K: AsRef<[u8]>,
71        I: IntoIterator<Item = K>,
72    {
73        let mut ro = readopts.cloned().unwrap_or_default();
74        ro.set_snapshot(self);
75
76        self.db.multi_get_full(keys, Some(&ro))
77    }
78}
79
80impl MultiGetCF<ReadOptions> for Snapshot<'_> {
81    fn multi_get_cf_full<'m, K, I>(
82        &self,
83        keys: I,
84        readopts: Option<&ReadOptions>,
85    ) -> Vec<Result<Option<DBVector>, Error>>
86    where
87        K: AsRef<[u8]>,
88        I: IntoIterator<Item = (&'m ColumnFamily, K)>,
89    {
90        let mut ro = readopts.cloned().unwrap_or_default();
91        ro.set_snapshot(self);
92
93        self.db.multi_get_cf_full(keys, Some(&ro))
94    }
95}
96
97impl Drop for Snapshot<'_> {
98    fn drop(&mut self) {
99        unsafe {
100            ffi::rocksdb_release_snapshot(self.db.inner, self.inner);
101        }
102    }
103}
104
105impl Iterate for Snapshot<'_> {
106    fn get_raw_iter<'a: 'b, 'b>(&'a self, readopts: &ReadOptions) -> DBRawIterator<'b> {
107        let mut ro = readopts.to_owned();
108        ro.set_snapshot(self);
109        self.db.get_raw_iter(&ro)
110    }
111}
112
113impl IterateCF for Snapshot<'_> {
114    fn get_raw_iter_cf<'a: 'b, 'b>(
115        &'a self,
116        cf_handle: &ColumnFamily,
117        readopts: &ReadOptions,
118    ) -> Result<DBRawIterator<'b>, Error> {
119        let mut ro = readopts.to_owned();
120        ro.set_snapshot(self);
121        self.db.get_raw_iter_cf(cf_handle, &ro)
122    }
123}