cfx_storage/storage_db/
snapshot_db.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5#[derive(Clone, Copy, Debug, DeriveMallocSizeOf, PartialEq)]
6#[repr(u8)]
7pub enum SnapshotKeptToProvideSyncStatus {
8    No = 0,
9    InfoOnly = 1,
10    InfoAndSnapshot = 2,
11}
12
13impl Default for SnapshotKeptToProvideSyncStatus {
14    fn default() -> Self { SnapshotKeptToProvideSyncStatus::No }
15}
16
17impl Encodable for SnapshotKeptToProvideSyncStatus {
18    fn rlp_append(&self, s: &mut RlpStream) {
19        s.append_internal(&(*self as u8));
20    }
21}
22
23impl Decodable for SnapshotKeptToProvideSyncStatus {
24    fn decode(rlp: &Rlp) -> std::result::Result<Self, DecoderError> {
25        Ok(unsafe { std::mem::transmute(rlp.as_val::<u8>()?) })
26    }
27}
28
29#[derive(Clone, Default, DeriveMallocSizeOf, Debug)]
30pub struct SnapshotInfo {
31    /// This field is true when the snapshot info is kept but the snapshot
32    /// itself is removed, or when
33    pub snapshot_info_kept_to_provide_sync: SnapshotKeptToProvideSyncStatus,
34    // FIXME: update serve_one_step_sync at maintenance.
35    pub serve_one_step_sync: bool,
36
37    pub merkle_root: MerkleHash,
38    pub parent_snapshot_height: u64,
39    pub height: u64,
40    pub parent_snapshot_epoch_id: EpochId,
41    // the last element of pivot_chain_parts is the epoch id of the snapshot
42    // itself.
43    #[debug(skip)]
44    pub pivot_chain_parts: Vec<EpochId>,
45}
46
47impl Encodable for SnapshotInfo {
48    fn rlp_append(&self, s: &mut RlpStream) {
49        s.begin_list(7)
50            .append(&self.snapshot_info_kept_to_provide_sync)
51            .append(&CompatBool(self.serve_one_step_sync))
52            .append(&self.merkle_root)
53            .append(&self.parent_snapshot_height)
54            .append(&self.height)
55            .append(&self.parent_snapshot_epoch_id)
56            .append_list(&self.pivot_chain_parts);
57    }
58}
59
60impl Decodable for SnapshotInfo {
61    fn decode(rlp: &Rlp) -> std::result::Result<Self, DecoderError> {
62        Ok(SnapshotInfo {
63            snapshot_info_kept_to_provide_sync: rlp.val_at(0)?,
64            serve_one_step_sync: rlp.val_at::<CompatBool>(1)?.0,
65            merkle_root: rlp.val_at(2)?,
66            parent_snapshot_height: rlp.val_at(3)?,
67            height: rlp.val_at(4)?,
68            parent_snapshot_epoch_id: rlp.val_at(5)?,
69            pivot_chain_parts: rlp.list_at(6)?,
70        })
71    }
72}
73
74impl SnapshotInfo {
75    pub fn genesis_snapshot_info() -> Self {
76        Self {
77            snapshot_info_kept_to_provide_sync: Default::default(),
78            serve_one_step_sync: false,
79            merkle_root: MERKLE_NULL_NODE,
80            parent_snapshot_height: 0,
81            height: 0,
82            parent_snapshot_epoch_id: NULL_EPOCH,
83            pivot_chain_parts: vec![NULL_EPOCH],
84        }
85    }
86
87    pub fn get_snapshot_epoch_id(&self) -> &EpochId {
88        self.pivot_chain_parts.last().unwrap()
89    }
90
91    pub fn get_epoch_id_at_height(&self, height: u64) -> Option<&EpochId> {
92        if height < self.parent_snapshot_height {
93            None
94        } else if height == self.parent_snapshot_height {
95            Some(&self.parent_snapshot_epoch_id)
96        } else if height > self.height {
97            None
98        } else {
99            unsafe {
100                Some(self.pivot_chain_parts.get_unchecked(
101                    (height - self.parent_snapshot_height - 1) as usize,
102                ))
103            }
104        }
105    }
106}
107
108pub trait OpenSnapshotMptTrait<'db> {
109    type SnapshotDbBorrowSharedType: 'db + SnapshotMptTraitRead;
110    type SnapshotDbBorrowMutType: 'db + SnapshotMptTraitRw;
111    type SnapshotDbAsOwnedType: 'db + SnapshotMptTraitRw;
112
113    fn open_snapshot_mpt_owned(
114        &'db mut self,
115    ) -> StorageResult<Self::SnapshotDbBorrowMutType>;
116
117    fn open_snapshot_mpt_as_owned(
118        &'db self,
119    ) -> StorageResult<Self::SnapshotDbAsOwnedType>;
120
121    fn open_snapshot_mpt_shared(
122        &'db self,
123    ) -> StorageResult<Self::SnapshotDbBorrowSharedType>;
124}
125
126pub trait SnapshotDbTrait:
127    KeyValueDbTraitOwnedRead
128    + KeyValueDbTraitRead
129    + KeyValueDbTraitSingleWriter
130    + for<'db> OpenSnapshotMptTrait<'db>
131    + Sized
132{
133    type SnapshotKvdbIterTraitTag;
134
135    type SnapshotKvdbIterType: WrappedTrait<
136        dyn KeyValueDbIterableTrait<
137            MptKeyValue,
138            [u8],
139            Self::SnapshotKvdbIterTraitTag,
140        >,
141    >;
142
143    fn get_null_snapshot() -> Self;
144
145    /// Store already_open_snapshots and open_semaphore to update
146    /// SnapshotDbManager on destructor. SnapshotDb itself does not take
147    /// care of the update on these data.
148    fn open(
149        snapshot_path: &Path, readonly: bool,
150        already_open_snapshots: &AlreadyOpenSnapshots<Self>,
151        open_semaphore: &Arc<Semaphore>,
152    ) -> StorageResult<Self>;
153
154    /// Store already_open_snapshots and open_semaphore to update
155    /// SnapshotDbManager on destructor. SnapshotDb itself does not take
156    /// care of the update on these data.
157    fn create(
158        snapshot_path: &Path,
159        already_open_snapshots: &AlreadyOpenSnapshots<Self>,
160        open_semaphore: &Arc<Semaphore>, mpt_table_in_current_db: bool,
161    ) -> StorageResult<Self>;
162
163    fn direct_merge(
164        &mut self, old_snapshot_db: Option<&Arc<Self>>,
165        mpt_snapshot: &mut Option<SnapshotMptDbSqlite>,
166        recover_mpt_with_kv_snapshot_exist: bool,
167        in_reconstruct_snapshot_state: bool,
168    ) -> StorageResult<MerkleHash>;
169
170    fn copy_and_merge(
171        &mut self, old_snapshot_db: &Arc<Self>,
172        mpt_snapshot_db: &mut Option<SnapshotMptDbSqlite>,
173        in_reconstruct_snapshot_state: bool,
174    ) -> StorageResult<MerkleHash>;
175
176    fn start_transaction(&mut self) -> StorageResult<()>;
177
178    fn commit_transaction(&mut self) -> StorageResult<()>;
179
180    fn is_mpt_table_in_current_db(&self) -> bool;
181
182    fn snapshot_kv_iterator(
183        &self,
184    ) -> StorageResult<
185        Wrap<
186            '_,
187            Self::SnapshotKvdbIterType,
188            dyn KeyValueDbIterableTrait<
189                MptKeyValue,
190                [u8],
191                Self::SnapshotKvdbIterTraitTag,
192            >,
193        >,
194    >;
195}
196
197use crate::{
198    impls::{
199        errors::Result as StorageResult,
200        storage_db::{
201            snapshot_db_manager_sqlite::AlreadyOpenSnapshots,
202            snapshot_mpt_db_sqlite::SnapshotMptDbSqlite,
203        },
204    },
205    storage_db::{
206        KeyValueDbIterableTrait, KeyValueDbTraitOwnedRead, KeyValueDbTraitRead,
207        KeyValueDbTraitSingleWriter, SnapshotMptTraitRead, SnapshotMptTraitRw,
208    },
209    utils::wrap::{Wrap, WrappedTrait},
210    MptKeyValue,
211};
212use derive_more::Debug;
213use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
214use primitives::{
215    CompatBool, EpochId, MerkleHash, MERKLE_NULL_NODE, NULL_EPOCH,
216};
217use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
218use std::{path::Path, sync::Arc};
219use tokio::sync::Semaphore;