1#[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 pub snapshot_info_kept_to_provide_sync: SnapshotKeptToProvideSyncStatus,
34 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 #[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 fn open(
149 snapshot_path: &Path, readonly: bool,
150 already_open_snapshots: &AlreadyOpenSnapshots<Self>,
151 open_semaphore: &Arc<Semaphore>,
152 ) -> StorageResult<Self>;
153
154 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;