Skip to content

Commit 5126d95

Browse files
committed
feat(client-cli): add --commit option to replace ledger state with converted snapshot
1 parent 5ab7fa2 commit 5126d95

File tree

1 file changed

+108
-3
lines changed

1 file changed

+108
-3
lines changed

mithril-client-cli/src/commands/tools/snapshot_converter.rs

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
env, fmt,
3-
fs::{create_dir, read_dir},
3+
fs::{create_dir, read_dir, remove_dir_all, rename},
44
path::{Path, PathBuf},
55
process::Command,
66
};
@@ -87,6 +87,10 @@ pub struct SnapshotConverterCommand {
8787
/// UTxO-HD flavor to convert the ledger snapshot to.
8888
#[clap(long)]
8989
utxo_hd_flavor: UTxOHDFlavor,
90+
91+
/// If set, the converted snapshot replaces the current one in the db directory.
92+
#[clap(long)]
93+
commit: bool,
9094
}
9195

9296
impl SnapshotConverterCommand {
@@ -133,6 +137,7 @@ impl SnapshotConverterCommand {
133137
&distribution_dir,
134138
&self.cardano_network,
135139
&self.utxo_hd_flavor,
140+
self.commit,
136141
)
137142
.with_context(|| {
138143
format!(
@@ -188,6 +193,7 @@ impl SnapshotConverterCommand {
188193
distribution_dir: &Path,
189194
cardano_network: &CardanoNetwork,
190195
utxo_hd_flavor: &UTxOHDFlavor,
196+
commit: bool,
191197
) -> MithrilResult<()> {
192198
let snapshots_path = work_dir.join(SNAPSHOTS_DIR);
193199
let copied_snapshot_path =
@@ -210,6 +216,17 @@ impl SnapshotConverterCommand {
210216
utxo_hd_flavor,
211217
)?;
212218

219+
if commit {
220+
Self::commit_converted_snapshot(db_dir, &converted_snapshot_path).with_context(
221+
|| "Failed to overwrite the ledger state with the converted snapshot.",
222+
)?;
223+
} else {
224+
println!(
225+
"Converted snapshot available at: {} (use --commit to replace original)",
226+
converted_snapshot_path.display()
227+
);
228+
}
229+
213230
Ok(())
214231
}
215232

@@ -359,18 +376,64 @@ impl SnapshotConverterCommand {
359376
.parse::<u64>()
360377
.with_context(|| format!("Invalid slot number in path filename: {}", file_name_str))
361378
}
379+
380+
/// Commits the converted snapshot by replacing the current ledger state snapshots in the database directory.
381+
fn commit_converted_snapshot(
382+
db_dir: &Path,
383+
converted_snapshot_path: &Path,
384+
) -> MithrilResult<()> {
385+
let ledger_dir = db_dir.join(LEDGER_DIR);
386+
println!(
387+
"Replacing ledger state snapshots located in '{}' with converted snapshot at: '{}'",
388+
ledger_dir.display(),
389+
converted_snapshot_path.display()
390+
);
391+
392+
let filename = converted_snapshot_path
393+
.file_name()
394+
.ok_or_else(|| anyhow!("Missing filename in converted snapshot path"))?
395+
.to_string_lossy();
396+
397+
let (slot_number, _) = filename
398+
.split_once('_')
399+
.ok_or_else(|| anyhow!("Invalid converted snapshot name format: {}", filename))?;
400+
401+
remove_dir_all(&ledger_dir).with_context(|| {
402+
format!(
403+
"Failed to remove old ledger state snapshot directory: {}",
404+
ledger_dir.display()
405+
)
406+
})?;
407+
408+
create_dir(&ledger_dir).with_context(|| {
409+
format!(
410+
"Failed to recreate ledger state snapshot directory: {}",
411+
ledger_dir.display()
412+
)
413+
})?;
414+
415+
let destination = ledger_dir.join(slot_number);
416+
rename(converted_snapshot_path, &destination).with_context(|| {
417+
format!(
418+
"Failed to move converted snapshot to ledger directory: {}",
419+
destination.display()
420+
)
421+
})?;
422+
423+
Ok(())
424+
}
362425
}
363426

364427
#[cfg(test)]
365428
mod tests {
429+
use mithril_common::temp_dir_create;
430+
366431
use super::*;
367432

368433
mod download_cardano_node_distribution {
369434
use mockall::predicate::eq;
370435
use reqwest::Url;
371436

372-
use mithril_common::temp_dir_create;
373-
374437
use crate::utils::{GitHubRelease, MockGitHubReleaseRetriever, MockHttpDownloader};
375438

376439
use super::*;
@@ -740,4 +803,46 @@ mod tests {
740803
.expect_err("Should return error if no valid ledger snapshot directory found");
741804
}
742805
}
806+
807+
mod commit_converted_snapshot {
808+
use std::fs::File;
809+
810+
use super::*;
811+
812+
#[test]
813+
fn moves_converted_snapshot_to_ledger_directory() {
814+
let tmp_dir = temp_dir_create!();
815+
let ledger_dir = tmp_dir.join(LEDGER_DIR);
816+
create_dir(&ledger_dir).unwrap();
817+
let previous_snapshot = ledger_dir.join("123");
818+
File::create(&previous_snapshot).unwrap();
819+
820+
let converted_snapshot = tmp_dir.join("456_lmdb");
821+
File::create(&converted_snapshot).unwrap();
822+
823+
assert!(previous_snapshot.exists());
824+
SnapshotConverterCommand::commit_converted_snapshot(&tmp_dir, &converted_snapshot)
825+
.unwrap();
826+
827+
assert!(!previous_snapshot.exists());
828+
assert!(ledger_dir.join("456").exists());
829+
}
830+
831+
#[test]
832+
fn fails_if_converted_snapshot_has_invalid_filename() {
833+
let tmp_dir = temp_dir_create!();
834+
let ledger_dir = tmp_dir.join(LEDGER_DIR);
835+
create_dir(&ledger_dir).unwrap();
836+
let previous_snapshot = ledger_dir.join("123");
837+
File::create(&previous_snapshot).unwrap();
838+
839+
let converted_snapshot = tmp_dir.join("456");
840+
File::create(&converted_snapshot).unwrap();
841+
842+
SnapshotConverterCommand::commit_converted_snapshot(&tmp_dir, &converted_snapshot)
843+
.expect_err("Should fail if converted snapshot has invalid filename");
844+
845+
assert!(previous_snapshot.exists());
846+
}
847+
}
743848
}

0 commit comments

Comments
 (0)