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(
30    Clone, Default, DeriveMallocSizeOf, RlpEncodable, RlpDecodable, Debug,
31)]
32pub struct SnapshotInfo {
33    /// This field is true when the snapshot info is kept but the snapshot
34    /// itself is removed, or when
35    pub snapshot_info_kept_to_provide_sync: SnapshotKeptToProvideSyncStatus,
36    // FIXME: update serve_one_step_sync at maintenance.
37    pub serve_one_step_sync: bool,
38
39    pub merkle_root: MerkleHash,
40    pub parent_snapshot_height: u64,
41    pub height: u64,
42    pub parent_snapshot_epoch_id: EpochId,
43    // the last element of pivot_chain_parts is the epoch id of the snapshot
44    // itself.
45    #[debug(skip)]
46    pub pivot_chain_parts: Vec<EpochId>,
47}
48
49impl SnapshotInfo {
50    pub fn genesis_snapshot_info() -> Self {
51        Self {
52            snapshot_info_kept_to_provide_sync: Default::default(),
53            serve_one_step_sync: false,
54            merkle_root: MERKLE_NULL_NODE,
55            parent_snapshot_height: 0,
56            height: 0,
57            parent_snapshot_epoch_id: NULL_EPOCH,
58            pivot_chain_parts: vec![NULL_EPOCH],
59        }
60    }
61
62    pub fn get_snapshot_epoch_id(&self) -> &EpochId {
63        self.pivot_chain_parts.last().unwrap()
64    }
65
66    pub fn get_epoch_id_at_height(&self, height: u64) -> Option<&EpochId> {
67        if height < self.parent_snapshot_height {
68            None
69        } else if height == self.parent_snapshot_height {
70            Some(&self.parent_snapshot_epoch_id)
71        } else if height > self.height {
72            None
73        } else {
74            unsafe {
75                Some(self.pivot_chain_parts.get_unchecked(
76                    (height - self.parent_snapshot_height - 1) as usize,
77                ))
78            }
79        }
80    }
81}
82
83pub trait OpenSnapshotMptTrait<'db> {
84    type SnapshotDbBorrowSharedType: 'db + SnapshotMptTraitRead;
85    type SnapshotDbBorrowMutType: 'db + SnapshotMptTraitRw;
86    type SnapshotDbAsOwnedType: 'db + SnapshotMptTraitRw;
87
88    fn open_snapshot_mpt_owned(
89        &'db mut self,
90    ) -> StorageResult<Self::SnapshotDbBorrowMutType>;
91
92    fn open_snapshot_mpt_as_owned(
93        &'db self,
94    ) -> StorageResult<Self::SnapshotDbAsOwnedType>;
95
96    fn open_snapshot_mpt_shared(
97        &'db self,
98    ) -> StorageResult<Self::SnapshotDbBorrowSharedType>;
99}
100
101pub trait SnapshotDbTrait:
102    KeyValueDbTraitOwnedRead
103    + KeyValueDbTraitRead
104    + KeyValueDbTraitSingleWriter
105    + for<'db> OpenSnapshotMptTrait<'db>
106    + Sized
107{
108    type SnapshotKvdbIterTraitTag;
109
110    type SnapshotKvdbIterType: WrappedTrait<
111        dyn KeyValueDbIterableTrait<
112            MptKeyValue,
113            [u8],
114            Self::SnapshotKvdbIterTraitTag,
115        >,
116    >;
117
118    fn get_null_snapshot() -> Self;
119
120    /// Store already_open_snapshots and open_semaphore to update
121    /// SnapshotDbManager on destructor. SnapshotDb itself does not take
122    /// care of the update on these data.
123    fn open(
124        snapshot_path: &Path, readonly: bool,
125        already_open_snapshots: &AlreadyOpenSnapshots<Self>,
126        open_semaphore: &Arc<Semaphore>,
127    ) -> StorageResult<Self>;
128
129    /// Store already_open_snapshots and open_semaphore to update
130    /// SnapshotDbManager on destructor. SnapshotDb itself does not take
131    /// care of the update on these data.
132    fn create(
133        snapshot_path: &Path,
134        already_open_snapshots: &AlreadyOpenSnapshots<Self>,
135        open_semaphore: &Arc<Semaphore>, mpt_table_in_current_db: bool,
136    ) -> StorageResult<Self>;
137
138    fn direct_merge(
139        &mut self, old_snapshot_db: Option<&Arc<Self>>,
140        mpt_snapshot: &mut Option<SnapshotMptDbSqlite>,
141        recover_mpt_with_kv_snapshot_exist: bool,
142        in_reconstruct_snapshot_state: bool,
143    ) -> StorageResult<MerkleHash>;
144
145    fn copy_and_merge(
146        &mut self, old_snapshot_db: &Arc<Self>,
147        mpt_snapshot_db: &mut Option<SnapshotMptDbSqlite>,
148        in_reconstruct_snapshot_state: bool,
149    ) -> StorageResult<MerkleHash>;
150
151    fn start_transaction(&mut self) -> StorageResult<()>;
152
153    fn commit_transaction(&mut self) -> StorageResult<()>;
154
155    fn is_mpt_table_in_current_db(&self) -> bool;
156
157    fn snapshot_kv_iterator(
158        &self,
159    ) -> StorageResult<
160        Wrap<
161            '_,
162            Self::SnapshotKvdbIterType,
163            dyn KeyValueDbIterableTrait<
164                MptKeyValue,
165                [u8],
166                Self::SnapshotKvdbIterTraitTag,
167            >,
168        >,
169    >;
170}
171
172use crate::{
173    impls::{
174        errors::Result as StorageResult,
175        storage_db::{
176            snapshot_db_manager_sqlite::AlreadyOpenSnapshots,
177            snapshot_mpt_db_sqlite::SnapshotMptDbSqlite,
178        },
179    },
180    storage_db::{
181        KeyValueDbIterableTrait, KeyValueDbTraitOwnedRead, KeyValueDbTraitRead,
182        KeyValueDbTraitSingleWriter, SnapshotMptTraitRead, SnapshotMptTraitRw,
183    },
184    utils::wrap::{Wrap, WrappedTrait},
185    MptKeyValue,
186};
187use derive_more::Debug;
188use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
189use primitives::{EpochId, MerkleHash, MERKLE_NULL_NODE, NULL_EPOCH};
190use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
191use rlp_derive::{RlpDecodable, RlpEncodable};
192use std::{path::Path, sync::Arc};
193use tokio::sync::Semaphore;