From 45d54e337450cf21f607352120e8cd3e3504816e Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Tue, 28 Apr 2026 17:20:44 +0200 Subject: [PATCH] Fix LSM snapshot restoration by resolving double path nesting The LSM session was being initialised with the full lsmPath as both the HasBlockIO root and the session's FsPath inside it, producing a doubled on-disk layout like: /lsm//lsm/{active,snapshots,...} instead of: /lsm/{active,snapshots,...}. Effect on snapshots: scripts/postgresql-setup.sh --create-snapshot looks for the LSM tree at /lsm/snapshots/, didn't find it because of the doubled path, silently fell back to the InMemory branch, and produced a tarball missing the LSM tree files. On --restore-snapshot + db-sync startup the snapshot couldn't be loaded (ErrSnapshotDoesNotExist) and sync replayed from genesis. Fix: Pass mkFsPath [] as the session's FsPath so it's rooted at the HasBlockIO root directly. Also harden the snapshot script to abort with a clear error when an lsm/ subtree exists but no LSM snapshot is found at the expected path, instead of producing an incomplete tarball. Files staged for commit: - cardano-db-sync/src/Cardano/DbSync/Ledger/State.hs - scripts/postgresql-setup.sh --- cardano-db-sync/src/Cardano/DbSync/Ledger/State.hs | 10 ++++++++-- scripts/postgresql-setup.sh | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cardano-db-sync/src/Cardano/DbSync/Ledger/State.hs b/cardano-db-sync/src/Cardano/DbSync/Ledger/State.hs index 9690d2c73..11d4e84dc 100644 --- a/cardano-db-sync/src/Cardano/DbSync/Ledger/State.hs +++ b/cardano-db-sync/src/Cardano/DbSync/Ledger/State.hs @@ -118,7 +118,7 @@ import Ouroboros.Network.Block (HeaderHash, pointSlot) import System.FS.API (SomeHasFS (..), mkFsPath) import System.FS.API.Types (MountPoint (..)) import System.FS.IO (ioHasFS) -import System.FilePath (splitDirectories, ()) +import System.FilePath (()) import System.Mem (performMajorGC) import System.Random (genWord64, newStdGen) @@ -227,7 +227,13 @@ mkHasLedgerEnv trce protoInfo dir nw maxLovelaceSupply systemStart syncOptions b LedgerBackendLSM mPath -> do let lsmPath = fromMaybe (unLedgerStateDir dir "lsm") mPath salt <- fst . genWord64 <$> newStdGen - let args = LSM.LSMArgs (mkFsPath $ splitDirectories lsmPath) salt (LSM.stdMkBlockIOFS lsmPath) + -- The HasBlockIO is rooted at lsmPath, so the session's FsPath inside it + -- must be the empty path. Passing the full lsmPath here causes the LSM + -- session to be created at /, which breaks snapshot + -- bundling in scripts/postgresql-setup.sh (it falls back to the InMemory + -- branch and ships an incomplete tarball; on restore db-sync then can't + -- find the snapshot and replays from genesis). + let args = LSM.LSMArgs (mkFsPath []) salt (LSM.stdMkBlockIOFS lsmPath) res <- runWithTempRegistry $ (,()) diff --git a/scripts/postgresql-setup.sh b/scripts/postgresql-setup.sh index fd381b957..f20a80b75 100755 --- a/scripts/postgresql-setup.sh +++ b/scripts/postgresql-setup.sh @@ -176,6 +176,15 @@ function create_snapshot { # The active/ directory is not needed — it gets cleared on session restore. tar czf "${tmp_dir}/${ledger_dir_name}.tar.gz" \ -C "${state_dir}" "${ledger_dir_name}" "lsm/snapshots/${ledger_dir_name}" "lsm/metadata" + elif [ -d "${state_dir}/lsm" ]; then + # State directory contains an lsm/ subtree but the expected snapshot path is missing. + # Refuse to silently fall back to the InMemory branch — the resulting tarball would + # exclude the LSM tree files and restoration would replay from genesis. + echo "ERROR: ${state_dir}/lsm exists but no LSM snapshot found at ${lsm_snap_dir}." >&2 + echo " The LSM session may be using a non-standard layout. Aborting to avoid" >&2 + echo " producing an incomplete snapshot." >&2 + rm "${recursive}" "${force}" "${tmp_dir}" + exit 1 else echo "Detected InMemory backend snapshot at slot ${ledger_dir_name}" # InMemory backend: just the ledger snapshot directory