Merge pull request #11068

91d851a blockchain_db: resume interrupted pruning (Samy)

ACKs: selsta, jpk68
This commit is contained in:
tobtoht
2026-09-09 19:53:54 +00:00
2 changed files with 272 additions and 2 deletions
+47 -2
View File
@@ -2074,8 +2074,29 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
throw0(DB_ERROR(lmdb_error("Failed to retrieve or create pruning seed: ", result).c_str()));
}
MDB_val_str(pruning_progress_key, "pruning_progress");
crypto::hash pruning_progress{};
bool resume_pruning = false;
if (mode != prune_mode_check)
{
result = mdb_get(txn, m_properties, &pruning_progress_key, &v);
if (result == 0)
{
if (v.mv_size != sizeof(pruning_progress))
throw0(DB_ERROR("Failed to retrieve pruning progress: unexpected value size"));
memcpy(&pruning_progress, v.mv_data, sizeof(pruning_progress));
resume_pruning = true;
}
else if (result != MDB_NOTFOUND)
{
throw0(DB_ERROR(lmdb_error("Failed to retrieve pruning progress: ", result).c_str()));
}
}
if (mode == prune_mode_check)
MINFO("Checking blockchain pruning...");
else if (resume_pruning)
MINFO("Resuming interrupted blockchain pruning...");
else
MINFO("Pruning blockchain...");
@@ -2091,7 +2112,7 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
throw0(DB_ERROR(lmdb_error("Failed to open a cursor for txs_prunable_tip: ", result).c_str()));
const uint64_t blockchain_height = height();
if (prune_tip_table)
if (prune_tip_table || resume_pruning)
{
MDB_cursor_op op = MDB_FIRST;
while (1)
@@ -2152,13 +2173,25 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
}
}
}
else
// A resumed operation still needs the historical pass after pruning newly matured tip records.
if (!prune_tip_table || resume_pruning)
{
MDB_cursor *c_tx_indices;
result = mdb_cursor_open(txn, m_tx_indices, &c_tx_indices);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to open a cursor for tx_indices: ", result).c_str()));
MDB_cursor_op op = MDB_FIRST;
if (resume_pruning)
{
MDB_val_set(progress, pruning_progress);
result = mdb_cursor_get(c_tx_indices, (MDB_val*)&zerokval, &progress, MDB_GET_BOTH);
if (result == 0)
op = MDB_NEXT;
else if (result == MDB_NOTFOUND)
MWARNING("Pruning progress transaction not found, restarting from the beginning");
else
throw0(DB_ERROR(lmdb_error("Failed to restore pruning progress: ", result).c_str()));
}
while (1)
{
int ret = mdb_cursor_get(c_tx_indices, &k, &v, op);
@@ -2239,6 +2272,11 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
if (mode != prune_mode_check && commit_counter >= 4096)
{
MDEBUG("Committing txn at checkpoint...");
// Commit the cursor position with the deletions so a restart cannot skip uncommitted work.
MDB_val_set(progress, ti.key);
result = mdb_put(txn, m_properties, &pruning_progress_key, &progress, 0);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to save pruning progress: ", result).c_str()));
txn.commit();
result = mdb_txn_begin(m_env, NULL, 0, txn);
if (result)
@@ -2265,6 +2303,13 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
}
}
mdb_cursor_close(c_tx_indices);
if (mode != prune_mode_check)
{
result = mdb_del(txn, m_properties, &pruning_progress_key, NULL);
if (result && result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("Failed to clear pruning progress: ", result).c_str()));
}
}
if ((result = mdb_stat(txn, m_txs_prunable, &db_stats)))