Skip to content

Commit

Permalink
Don't throw error if the ledger directory exists but is empty on node…
Browse files Browse the repository at this point in the history
… start (#6859)
  • Loading branch information
andpiccione authored Feb 27, 2025
1 parent ace466b commit 6da2606
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/host/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,12 @@ int main(int argc, char** argv)
{
if (config.command.type == StartType::Start)
{
if (files::exists(config.ledger.directory))
if (
files::exists(config.ledger.directory) &&
!fs::is_empty(config.ledger.directory))
{
throw std::logic_error(fmt::format(
"On start, ledger directory should not exist ({})",
"On start, ledger directory should not exist or be empty ({})",
config.ledger.directory));
}

Expand Down
6 changes: 6 additions & 0 deletions src/snapshots/filenames.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ namespace snapshots
continue;
}

if (fs::exists(f.path()) && fs::is_empty(f.path()))
{
LOG_INFO_FMT("Ignoring empty snapshot file {}", file_name);
continue;
}

auto snapshot_idx = get_snapshot_idx_from_file_name(file_name);
if (snapshot_idx > latest_committed_snapshot_idx)
{
Expand Down
77 changes: 77 additions & 0 deletions tests/e2e_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,40 @@ def test_snapshot_access(network, args):
assert err_msg in r.body.json()["error"]["message"], r


def test_empty_snapshot(network, args):

LOG.info("Check that empty snapshot is ignored")

with tempfile.TemporaryDirectory() as snapshots_dir:
LOG.debug(f"Using {snapshots_dir} as snapshots directory")

snapshot_name = "snapshot_1000_1500.committed"

with open(
os.path.join(snapshots_dir, snapshot_name), "wb+"
) as temp_empty_snapshot:

LOG.debug(f"Created empty snapshot {temp_empty_snapshot.name}")

# Check the file is indeed empty
assert (
os.stat(temp_empty_snapshot.name).st_size == 0
), temp_empty_snapshot.name

# Create new node and join network
new_node = network.create_node("local://localhost")
network.join_node(new_node, args.package, args, snapshots_dir=snapshots_dir)
new_node.stop()

# Check that the empty snapshot is correctly skipped
if not new_node.check_log_for_error_message(
f"Ignoring empty snapshot file {snapshot_name}"
):
raise AssertionError(
f"Expected empty snapshot file {snapshot_name} to be skipped in node logs"
)


def split_all_ledger_files_in_dir(input_dir, output_dir):
# A ledger file can only be split at a seqno that contains a signature
# (so that all files end on a signature that verifies their integrity).
Expand Down Expand Up @@ -397,6 +431,7 @@ def run_file_operations(args):
test_forced_snapshot(network, args)
test_large_snapshot(network, args)
test_snapshot_access(network, args)
test_empty_snapshot(network, args)

primary, _ = network.find_primary()
# Scoped transactions are not handled by historical range queries
Expand Down Expand Up @@ -883,6 +918,47 @@ def try_historical_fetch(node, timeout=1):
raise AssertionError(expected_errors)


def run_empty_ledger_dir_check(args):
with infra.network.network(
args.nodes,
args.binary_dir,
args.debug_nodes,
args.perf_nodes,
pdb=args.pdb,
) as network:
LOG.info("Check that empty ledger directory is handled correctly")
with tempfile.TemporaryDirectory() as tmp_dir:
LOG.debug(f"Using {tmp_dir} as ledger directory")

dir_name = os.path.basename(tmp_dir)

# Check tmp_dir is indeed empty
assert len(os.listdir(tmp_dir)) == 0, tmp_dir

# Start network, this should not fail
network.start_and_open(args, ledger_dir=tmp_dir)
primary, _ = network.find_primary()
network.stop_all_nodes()

# Now write a file in the directory
with open(os.path.join(tmp_dir, "ledger_1000_1500.committed"), "wb") as f:
f.write(b"bar")

# Start new network, this should fail
try:
network.start(args, ledger_dir=tmp_dir)
except Exception:
pass

# Check that the node has failed with the expected error message
if not primary.check_log_for_error_message(
f"On start, ledger directory should not exist or be empty ({dir_name})"
):
raise AssertionError(
f"Expected node error message with non-empty ledger directory {dir_name}"
)


def run(args):
run_max_uncommitted_tx_count(args)
run_file_operations(args)
Expand All @@ -895,3 +971,4 @@ def run(args):
run_service_subject_name_check(args)
run_cose_signatures_config_check(args)
run_late_mounted_ledger_check(args)
run_empty_ledger_dir_check(args)
1 change: 1 addition & 0 deletions tests/infra/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ def _start_all_nodes(
workspace=args.workspace,
label=args.label,
common_dir=self.common_dir,
ledger_dir=ledger_dir,
members_info=self.consortium.get_members_info(),
**forwarded_args_with_overrides,
**kwargs,
Expand Down

0 comments on commit 6da2606

Please sign in to comment.