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