1use {
2 crate::{hardened_unpack::UnpackError, snapshot_hash::SnapshotHash},
3 agave_fs::FileInfo,
4 crossbeam_channel::SendError,
5 semver::Version,
6 solana_accounts_db::{accounts_db::AccountsFileId, accounts_file::AccountsFileError},
7 solana_clock::{Epoch, Slot},
8 std::{io, ops::RangeInclusive, path::PathBuf, process::ExitStatus},
9 thiserror::Error,
10};
11
12#[derive(Error, Debug)]
13#[allow(clippy::large_enum_variant)]
14pub enum SnapshotError {
15 #[error("I/O error: {0}")]
16 Io(#[from] io::Error),
17
18 #[error("AccountsFile error: {0}")]
19 AccountsFileError(#[from] AccountsFileError),
20
21 #[error("serialization error: {0}")]
22 Serialize(#[from] bincode::Error),
23
24 #[error("deserialization error: {0}")]
25 DeserializeWincode(#[from] wincode::ReadError),
26
27 #[error("serialization error: {0}")]
28 SerializeWincode(#[from] wincode::WriteError),
29
30 #[error("crossbeam send error: {0}")]
31 CrossbeamSend(#[from] crossbeam_channel::SendError<PathBuf>),
32
33 #[error("archive generation failure {0}")]
34 ArchiveGenerationFailure(ExitStatus),
35
36 #[error("Unpack error: {0}")]
37 UnpackError(#[from] UnpackError),
38
39 #[error("source({1}) - I/O error: {0}")]
40 IoWithSource(io::Error, &'static str),
41
42 #[error("could not get file name from path '{0}'")]
43 PathToFileNameError(PathBuf),
44
45 #[error("could not get str from file name '{0}'")]
46 FileNameToStrError(PathBuf),
47
48 #[error("could not parse snapshot archive's file name '{0}'")]
49 ParseSnapshotArchiveFileNameError(String),
50
51 #[error(
52 "snapshots are incompatible: full snapshot slot ({0}) and incremental snapshot base slot \
53 ({1}) do not match"
54 )]
55 MismatchedBaseSlot(Slot, Slot),
56
57 #[error("no snapshot archives to load from '{0}'")]
58 NoSnapshotArchives(PathBuf),
59
60 #[error("snapshot slot mismatch: deserialized bank: {0}, snapshot archive: {1}")]
61 MismatchedSlot(Slot, Slot),
62
63 #[error("snapshot hash mismatch: deserialized bank: {0:?}, snapshot archive: {1:?}")]
64 MismatchedHash(SnapshotHash, SnapshotHash),
65
66 #[error(
67 "snapshot accounts file id mismatch: deserialized obsolete accounts file id: {0}, \
68 snapshot archive: {1}"
69 )]
70 MismatchedAccountsFileId(AccountsFileId, AccountsFileId),
71
72 #[error("snapshot slot deltas are invalid: {0}")]
73 VerifySlotDeltas(#[from] VerifySlotDeltasError),
74
75 #[error("snapshot epoch stakes are invalid: {0}")]
76 VerifyEpochStakes(#[from] VerifyEpochStakesError),
77
78 #[error("bank_snapshot_info new_from_dir failed: {0}")]
79 NewFromDir(#[from] SnapshotNewFromDirError),
80
81 #[error("invalid snapshot dir path '{0}'")]
82 InvalidSnapshotDirPath(PathBuf),
83
84 #[error("invalid AppendVec path '{0}'")]
85 InvalidAppendVecPath(PathBuf),
86
87 #[error("invalid account path '{0}'")]
88 InvalidAccountPath(PathBuf),
89
90 #[error("no valid snapshot dir found under '{0}'")]
91 NoSnapshotSlotDir(PathBuf),
92
93 #[error("snapshot dir account paths mismatching")]
94 AccountPathsMismatch,
95
96 #[error("failed to add bank snapshot for slot {1}: {0}")]
97 AddBankSnapshot(#[source] AddBankSnapshotError, Slot),
98
99 #[error("failed to archive snapshot package: {0}")]
100 ArchiveSnapshotPackage(#[from] ArchiveSnapshotPackageError),
101
102 #[error("failed to rebuild snapshot storages: {0}")]
103 RebuildStorages(String),
104
105 #[error("capitalization mismatch: expected: {0}, calculated: {1}")]
106 MismatchedCapitalization(u64, u64),
107}
108
109impl From<SendError<FileInfo>> for SnapshotError {
110 fn from(err: SendError<FileInfo>) -> Self {
111 Self::CrossbeamSend(SendError(err.into_inner().path))
112 }
113}
114
115#[derive(Error, Debug)]
116pub enum SnapshotFastbootError {
117 #[error("incompatible fastboot version '{0}'")]
118 IncompatibleVersion(Version),
119}
120
121#[derive(Error, Debug)]
122pub enum SnapshotNewFromDirError {
123 #[error("invalid bank snapshot directory '{0}'")]
124 InvalidBankSnapshotDir(PathBuf),
125
126 #[error("missing status cache file '{0}'")]
127 MissingStatusCacheFile(PathBuf),
128
129 #[error("missing version file '{0}'")]
130 MissingVersionFile(PathBuf),
131
132 #[error("invalid snapshot version '{0}'")]
133 InvalidVersion(String),
134
135 #[error("invalid version string for fastboot '{0}'")]
136 InvalidFastbootVersion(String),
137
138 #[error("snapshot directory incomplete '{1}': {0}")]
139 IncompleteDir(#[source] io::Error, PathBuf),
140
141 #[error("missing snapshot file '{0}'")]
142 MissingSnapshotFile(PathBuf),
143}
144
145#[derive(Error, Debug, PartialEq, Eq)]
147pub enum VerifySlotDeltasError {
148 #[error("too many entries: {0} (max: {1})")]
149 TooManyEntries(usize, usize),
150
151 #[error("slot {0} is not a root")]
152 SlotIsNotRoot(Slot),
153
154 #[error("slot {0} is greater than bank slot {1}")]
155 SlotGreaterThanMaxRoot(Slot, Slot),
156
157 #[error("slot {0} has multiple entries")]
158 SlotHasMultipleEntries(Slot),
159
160 #[error("slot {0} was not found in slot history")]
161 SlotNotFoundInHistory(Slot),
162
163 #[error("slot {0} was in history but missing from slot deltas")]
164 SlotNotFoundInDeltas(Slot),
165
166 #[error("snapshot slot history is invalid: {0}")]
167 VerifySlotHistory(#[from] VerifySlotHistoryError),
168}
169
170#[derive(Error, Debug, PartialEq, Eq)]
172pub enum VerifySlotHistoryError {
173 #[error("newest slot does not match snapshot")]
174 InvalidNewestSlot,
175
176 #[error("invalid number of entries")]
177 InvalidNumEntries,
178}
179
180#[derive(Error, Debug, PartialEq, Eq)]
182pub enum VerifyEpochStakesError {
183 #[error("epoch {0} is greater than the max {1}")]
184 EpochGreaterThanMax(Epoch, Epoch),
185
186 #[error("stakes not found for epoch {0} (required epochs: {1:?})")]
187 StakesNotFound(Epoch, RangeInclusive<Epoch>),
188}
189
190#[derive(Error, Debug)]
192pub enum AddBankSnapshotError {
193 #[error("bank snapshot dir already exists '{0}'")]
194 SnapshotDirAlreadyExists(PathBuf),
195
196 #[error("failed to create snapshot dir '{1}': {0}")]
197 CreateSnapshotDir(#[source] io::Error, PathBuf),
198
199 #[error("failed to flush storage '{1}': {0}")]
200 FlushStorage(#[source] AccountsFileError, PathBuf),
201
202 #[error("failed to serialize bank: {0}")]
203 SerializeBank(#[source] Box<SnapshotError>),
204
205 #[error("failed to serialize status cache: {0}")]
206 SerializeStatusCache(#[source] Box<SnapshotError>),
207
208 #[error("failed to serialize obsolete accounts: {0}")]
209 SerializeObsoleteAccounts(#[source] Box<SnapshotError>),
210
211 #[error("failed to write storages list: {0}")]
212 WriteStoragesList(#[source] Box<SnapshotError>),
213
214 #[error("failed to write snapshot version file '{1}': {0}")]
215 WriteSnapshotVersionFile(#[source] io::Error, PathBuf),
216
217 #[error("failed to mark snapshot as 'loadable': {0}")]
218 MarkSnapshotLoadable(#[source] io::Error),
219}
220
221#[derive(Error, Debug)]
223pub enum ArchiveSnapshotPackageError {
224 #[error("failed to create archive path '{1}': {0}")]
225 CreateArchiveDir(#[source] io::Error, PathBuf),
226
227 #[error("failed to create staging dir inside '{1}': {0}")]
228 CreateStagingDir(#[source] io::Error, PathBuf),
229
230 #[error("failed to create snapshot staging dir '{1}': {0}")]
231 CreateSnapshotStagingDir(#[source] io::Error, PathBuf),
232
233 #[error("failed to canonicalize snapshot source dir '{1}': {0}")]
234 CanonicalizeSnapshotSourceDir(#[source] io::Error, PathBuf),
235
236 #[error("failed to symlink snapshot from '{1}' to '{2}': {0}")]
237 SymlinkSnapshot(#[source] io::Error, PathBuf, PathBuf),
238
239 #[error("failed to symlink status cache from '{1}' to '{2}': {0}")]
240 SymlinkStatusCache(#[source] io::Error, PathBuf, PathBuf),
241
242 #[error("failed to symlink version file from '{1}' to '{2}': {0}")]
243 SymlinkVersionFile(#[source] io::Error, PathBuf, PathBuf),
244
245 #[error("failed to create archive file '{1}': {0}")]
246 CreateArchiveFile(#[source] io::Error, PathBuf),
247
248 #[error("failed to archive version file: {0}")]
249 ArchiveVersionFile(#[source] io::Error),
250
251 #[error("failed to archive snapshots dir: {0}")]
252 ArchiveSnapshotsDir(#[source] io::Error),
253
254 #[error("failed to archive account storage file '{1}': {0}")]
255 ArchiveAccountStorageFile(#[source] io::Error, PathBuf),
256
257 #[error("failed to archive snapshot: {0}")]
258 FinishArchive(#[source] io::Error),
259
260 #[error("failed to create encoder: {0}")]
261 CreateEncoder(#[source] io::Error),
262
263 #[error("failed to encode archive: {0}")]
264 FinishEncoder(#[source] io::Error),
265
266 #[error("failed to query archive metadata '{1}': {0}")]
267 QueryArchiveMetadata(#[source] io::Error, PathBuf),
268
269 #[error("failed to move archive from '{1}' to '{2}': {0}")]
270 MoveArchive(#[source] io::Error, PathBuf, PathBuf),
271
272 #[error("failed to create account storage reader '{1}': {0}")]
273 AccountStorageReaderError(#[source] io::Error, PathBuf),
274
275 #[error("failed to initialize file buffered reader: {0}")]
276 StorageFileBufReaderError(#[source] io::Error),
277}