Recover index state and stale log heads after partial repairs
This commit is contained in:
parent
6ab25361be
commit
624bd29bf9
|
|
@ -11,6 +11,7 @@
|
||||||
#include "amduat/enc/asl_core_index.h"
|
#include "amduat/enc/asl_core_index.h"
|
||||||
#include "amduat/enc/asl_log.h"
|
#include "amduat/enc/asl_log.h"
|
||||||
#include "amduat/hash/asl1.h"
|
#include "amduat/hash/asl1.h"
|
||||||
|
#include "amduat/util/log.h"
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -3821,9 +3822,18 @@ static bool amduat_asl_store_index_fs_current_state_impl(
|
||||||
if (amduat_asl_store_index_fs_find_latest_snapshot_id(fs, &snapshot_id) &&
|
if (amduat_asl_store_index_fs_find_latest_snapshot_id(fs, &snapshot_id) &&
|
||||||
amduat_asl_store_index_fs_load_snapshot_manifest(
|
amduat_asl_store_index_fs_load_snapshot_manifest(
|
||||||
fs->root_path, snapshot_id, &manifest, manifest_hash)) {
|
fs->root_path, snapshot_id, &manifest, manifest_hash)) {
|
||||||
out_state->snapshot_id = manifest.snapshot_id;
|
if (manifest.anchor_logseq <= last_logseq) {
|
||||||
if (manifest.anchor_logseq > out_state->log_position) {
|
out_state->snapshot_id = manifest.snapshot_id;
|
||||||
out_state->log_position = manifest.anchor_logseq;
|
if (manifest.anchor_logseq > out_state->log_position) {
|
||||||
|
out_state->log_position = manifest.anchor_logseq;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
amduat_log(
|
||||||
|
AMDUAT_LOG_WARN,
|
||||||
|
"index snapshot anchor beyond log tail; ignoring snapshot (snapshot=%" PRIu64 " anchor=%" PRIu64 " log_tail=%" PRIu64 ")",
|
||||||
|
(uint64_t)manifest.snapshot_id,
|
||||||
|
(uint64_t)manifest.anchor_logseq,
|
||||||
|
(uint64_t)last_logseq);
|
||||||
}
|
}
|
||||||
amduat_asl_snapshot_manifest_free(&manifest);
|
amduat_asl_snapshot_manifest_free(&manifest);
|
||||||
} else if (record_count != 0u &&
|
} else if (record_count != 0u &&
|
||||||
|
|
|
||||||
|
|
@ -536,6 +536,7 @@ amduat_asl_store_error_t amduat_asl_log_append(
|
||||||
|
|
||||||
for (uint32_t attempt = 0u; attempt < AMDUAT_ASL_LOG_MAX_RETRIES; ++attempt) {
|
for (uint32_t attempt = 0u; attempt < AMDUAT_ASL_LOG_MAX_RETRIES; ++attempt) {
|
||||||
bool head_exists = false;
|
bool head_exists = false;
|
||||||
|
bool head_ref_missing = false;
|
||||||
amduat_reference_t head_ref;
|
amduat_reference_t head_ref;
|
||||||
amduat_artifact_t head_artifact;
|
amduat_artifact_t head_artifact;
|
||||||
amduat_asl_log_chunk_t head_chunk;
|
amduat_asl_log_chunk_t head_chunk;
|
||||||
|
|
@ -560,6 +561,10 @@ amduat_asl_store_error_t amduat_asl_log_append(
|
||||||
store_err = amduat_asl_store_get(log_store->store, head_ref,
|
store_err = amduat_asl_store_get(log_store->store, head_ref,
|
||||||
&head_artifact);
|
&head_artifact);
|
||||||
if (store_err != AMDUAT_ASL_STORE_OK) {
|
if (store_err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
if (store_err == AMDUAT_ASL_STORE_ERR_NOT_FOUND) {
|
||||||
|
/* Recover from a stale head pointer by rebasing to a fresh chunk. */
|
||||||
|
head_ref_missing = true;
|
||||||
|
} else {
|
||||||
char *head_ref_hex = NULL;
|
char *head_ref_hex = NULL;
|
||||||
(void)amduat_asl_ref_encode_hex(head_ref, &head_ref_hex);
|
(void)amduat_asl_ref_encode_hex(head_ref, &head_ref_hex);
|
||||||
amduat_log(AMDUAT_LOG_ERROR,
|
amduat_log(AMDUAT_LOG_ERROR,
|
||||||
|
|
@ -573,37 +578,50 @@ amduat_asl_store_error_t amduat_asl_log_append(
|
||||||
amduat_reference_free(&head_ref);
|
amduat_reference_free(&head_ref);
|
||||||
free(pointer_name);
|
free(pointer_name);
|
||||||
return store_err;
|
return store_err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!head_artifact.has_type_tag ||
|
if (!head_ref_missing) {
|
||||||
head_artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_CHUNK_1) {
|
if (!head_artifact.has_type_tag ||
|
||||||
amduat_reference_free(&head_ref);
|
head_artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_CHUNK_1) {
|
||||||
|
amduat_reference_free(&head_ref);
|
||||||
|
amduat_artifact_free(&head_artifact);
|
||||||
|
free(pointer_name);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
store_err = amduat_asl_log_chunk_decode_v1(head_artifact.bytes,
|
||||||
|
&head_chunk);
|
||||||
amduat_artifact_free(&head_artifact);
|
amduat_artifact_free(&head_artifact);
|
||||||
free(pointer_name);
|
if (store_err != AMDUAT_ASL_STORE_OK) {
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
amduat_log(AMDUAT_LOG_ERROR,
|
||||||
}
|
"asl_log_append: decode head chunk failed (log=%s pointer=%s attempt=%u err=%d)",
|
||||||
store_err = amduat_asl_log_chunk_decode_v1(head_artifact.bytes,
|
log_name != NULL ? log_name : "(null)",
|
||||||
&head_chunk);
|
pointer_name != NULL ? pointer_name : "(null)",
|
||||||
amduat_artifact_free(&head_artifact);
|
(unsigned)attempt,
|
||||||
if (store_err != AMDUAT_ASL_STORE_OK) {
|
(int)store_err);
|
||||||
amduat_log(AMDUAT_LOG_ERROR,
|
amduat_reference_free(&head_ref);
|
||||||
"asl_log_append: decode head chunk failed (log=%s pointer=%s attempt=%u err=%d)",
|
free(pointer_name);
|
||||||
|
return store_err;
|
||||||
|
}
|
||||||
|
if (head_chunk.base_offset >
|
||||||
|
UINT64_MAX - (uint64_t)head_chunk.entry_count) {
|
||||||
|
amduat_asl_log_chunk_free(&head_chunk);
|
||||||
|
amduat_reference_free(&head_ref);
|
||||||
|
free(pointer_name);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
base_offset = head_chunk.base_offset + head_chunk.entry_count;
|
||||||
|
amduat_asl_log_chunk_free(&head_chunk);
|
||||||
|
} else {
|
||||||
|
char *head_ref_hex = NULL;
|
||||||
|
(void)amduat_asl_ref_encode_hex(head_ref, &head_ref_hex);
|
||||||
|
amduat_log(AMDUAT_LOG_WARN,
|
||||||
|
"asl_log_append: stale head pointer missing chunk; rebasing log head (log=%s pointer=%s attempt=%u head_ref=%s)",
|
||||||
log_name != NULL ? log_name : "(null)",
|
log_name != NULL ? log_name : "(null)",
|
||||||
pointer_name != NULL ? pointer_name : "(null)",
|
pointer_name != NULL ? pointer_name : "(null)",
|
||||||
(unsigned)attempt,
|
(unsigned)attempt,
|
||||||
(int)store_err);
|
head_ref_hex != NULL ? head_ref_hex : "(hex-encode-failed)");
|
||||||
amduat_reference_free(&head_ref);
|
free(head_ref_hex);
|
||||||
free(pointer_name);
|
|
||||||
return store_err;
|
|
||||||
}
|
}
|
||||||
if (head_chunk.base_offset >
|
|
||||||
UINT64_MAX - (uint64_t)head_chunk.entry_count) {
|
|
||||||
amduat_asl_log_chunk_free(&head_chunk);
|
|
||||||
amduat_reference_free(&head_ref);
|
|
||||||
free(pointer_name);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
base_offset = head_chunk.base_offset + head_chunk.entry_count;
|
|
||||||
amduat_asl_log_chunk_free(&head_chunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -618,7 +636,7 @@ amduat_asl_store_error_t amduat_asl_log_append(
|
||||||
new_chunk.has_timestamp = has_timestamp;
|
new_chunk.has_timestamp = has_timestamp;
|
||||||
new_chunk.has_actor = has_actor;
|
new_chunk.has_actor = has_actor;
|
||||||
new_chunk.entries = (amduat_asl_log_entry_t *)entries;
|
new_chunk.entries = (amduat_asl_log_entry_t *)entries;
|
||||||
if (head_exists) {
|
if (head_exists && !head_ref_missing) {
|
||||||
new_chunk.has_prev = true;
|
new_chunk.has_prev = true;
|
||||||
new_chunk.prev_ref = head_ref;
|
new_chunk.prev_ref = head_ref;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue