Skip to content

Commit 4225f09

Browse files
committed
feat(client-cli): add --commit option to replace ledger state with converted snapshot
1 parent 3a2b76c commit 4225f09

File tree

1 file changed

+105
-3
lines changed

1 file changed

+105
-3
lines changed

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

Lines changed: 105 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 ledger state 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!(
@@ -197,6 +202,7 @@ impl SnapshotConverterCommand {
197202
distribution_dir: &Path,
198203
cardano_network: &CardanoNetwork,
199204
utxo_hd_flavor: &UTxOHDFlavor,
205+
commit: bool,
200206
) -> MithrilResult<()> {
201207
println!(
202208
"Converting ledger state snapshot to '{}' flavor",
@@ -223,6 +229,14 @@ impl SnapshotConverterCommand {
223229
utxo_hd_flavor,
224230
)?;
225231

232+
if commit {
233+
Self::commit_converted_snapshot(db_dir, &converted_snapshot_path).with_context(
234+
|| "Failed to overwrite the ledger state with the converted snapshot.",
235+
)?;
236+
} else {
237+
println!("Snapshot location: {}", converted_snapshot_path.display());
238+
}
239+
226240
Ok(())
227241
}
228242

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

366426
#[cfg(test)]
367427
mod tests {
428+
use mithril_common::temp_dir_create;
429+
368430
use super::*;
369431

370432
mod download_cardano_node_distribution {
371433
use mockall::predicate::eq;
372434
use reqwest::Url;
373435

374-
use mithril_common::temp_dir_create;
375-
376436
use crate::utils::{GitHubRelease, MockGitHubReleaseRetriever, MockHttpDownloader};
377437

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

0 commit comments

Comments
 (0)