clone_solana_download_utils/
lib.rs

1pub use clone_solana_file_download::DownloadProgressRecord;
2use {
3    clone_solana_clock::Slot,
4    clone_solana_file_download::{download_file, DownloadProgressCallbackOption},
5    clone_solana_genesis_config::DEFAULT_GENESIS_ARCHIVE,
6    clone_solana_runtime::{
7        snapshot_hash::SnapshotHash,
8        snapshot_package::SnapshotKind,
9        snapshot_utils::{self, ArchiveFormat, ZstdConfig},
10    },
11    log::*,
12    std::{
13        fs,
14        net::SocketAddr,
15        num::NonZeroUsize,
16        path::{Path, PathBuf},
17    },
18};
19
20pub fn download_genesis_if_missing(
21    rpc_addr: &SocketAddr,
22    genesis_package: &Path,
23    use_progress_bar: bool,
24) -> Result<PathBuf, String> {
25    if !genesis_package.exists() {
26        let tmp_genesis_path = genesis_package.parent().unwrap().join("tmp-genesis");
27        let tmp_genesis_package = tmp_genesis_path.join(DEFAULT_GENESIS_ARCHIVE);
28
29        let _ignored = fs::remove_dir_all(&tmp_genesis_path);
30        download_file(
31            &format!("http://{rpc_addr}/{DEFAULT_GENESIS_ARCHIVE}"),
32            &tmp_genesis_package,
33            use_progress_bar,
34            &mut None,
35        )?;
36
37        Ok(tmp_genesis_package)
38    } else {
39        Err("genesis already exists".to_string())
40    }
41}
42
43/// Download a snapshot archive from `rpc_addr`.  Use `snapshot_kind` to specify downloading either
44/// a full snapshot or an incremental snapshot.
45pub fn download_snapshot_archive(
46    rpc_addr: &SocketAddr,
47    full_snapshot_archives_dir: &Path,
48    incremental_snapshot_archives_dir: &Path,
49    desired_snapshot_hash: (Slot, SnapshotHash),
50    snapshot_kind: SnapshotKind,
51    maximum_full_snapshot_archives_to_retain: NonZeroUsize,
52    maximum_incremental_snapshot_archives_to_retain: NonZeroUsize,
53    use_progress_bar: bool,
54    progress_notify_callback: &mut DownloadProgressCallbackOption<'_>,
55) -> Result<(), String> {
56    snapshot_utils::purge_old_snapshot_archives(
57        full_snapshot_archives_dir,
58        incremental_snapshot_archives_dir,
59        maximum_full_snapshot_archives_to_retain,
60        maximum_incremental_snapshot_archives_to_retain,
61    );
62
63    let snapshot_archives_remote_dir =
64        snapshot_utils::build_snapshot_archives_remote_dir(match snapshot_kind {
65            SnapshotKind::FullSnapshot => full_snapshot_archives_dir,
66            SnapshotKind::IncrementalSnapshot(_) => incremental_snapshot_archives_dir,
67        });
68    fs::create_dir_all(&snapshot_archives_remote_dir).unwrap();
69
70    for archive_format in [
71        ArchiveFormat::TarZstd {
72            config: ZstdConfig::default(),
73        },
74        ArchiveFormat::TarGzip,
75        ArchiveFormat::TarBzip2,
76        ArchiveFormat::TarLz4,
77        ArchiveFormat::Tar,
78    ] {
79        let destination_path = match snapshot_kind {
80            SnapshotKind::FullSnapshot => snapshot_utils::build_full_snapshot_archive_path(
81                &snapshot_archives_remote_dir,
82                desired_snapshot_hash.0,
83                &desired_snapshot_hash.1,
84                archive_format,
85            ),
86            SnapshotKind::IncrementalSnapshot(base_slot) => {
87                snapshot_utils::build_incremental_snapshot_archive_path(
88                    &snapshot_archives_remote_dir,
89                    base_slot,
90                    desired_snapshot_hash.0,
91                    &desired_snapshot_hash.1,
92                    archive_format,
93                )
94            }
95        };
96
97        if destination_path.is_file() {
98            return Ok(());
99        }
100
101        match download_file(
102            &format!(
103                "http://{}/{}",
104                rpc_addr,
105                destination_path.file_name().unwrap().to_str().unwrap()
106            ),
107            &destination_path,
108            use_progress_bar,
109            progress_notify_callback,
110        ) {
111            Ok(()) => return Ok(()),
112            Err(err) => info!("{}", err),
113        }
114    }
115    Err(format!(
116        "Failed to download a snapshot archive for slot {} from {}",
117        desired_snapshot_hash.0, rpc_addr
118    ))
119}