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 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 pub snapshot_info_kept_to_provide_sync: SnapshotKeptToProvideSyncStatus,
41 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 #[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 fn open(
155 snapshot_path: &Path, readonly: bool,
156 already_open_snapshots: &AlreadyOpenSnapshots<Self>,
157 open_semaphore: &Arc<Semaphore>,
158 ) -> StorageResult<Self>;
159
160 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;