Fix WAL correctness: persist votes, fix crash recovery and view changes
Several bugs found via deterministic simulation testing (500 seeds, 30s each): WAL format: Store full WALEntry on disk (including votes and checksum) instead of a separate WALEntryDisk. This eliminates the need to reconstruct transient vote bits after restart, and adds wal_update_entry() for persisting in-place vote modifications. Crash recovery: Restore 3-case startup logic (empty=normal, corrupt=recovery, clean=replay). Fix last_normal_view initialization on clean restart. Call adopt_view() after replay to reinitialize leader vote bits that may be stale if a crash interrupted wal_replace before the atomic rename. View change ordering: Move wal_replace before persist_state in process_begin_view so the on-disk log is always at least as recent as the persisted metadata. Reset votes on view_change_log entries before wal_replace in complete_view_change_and_become_primary and complete_recovery. View adoption: Add adopt_view() helper called from process_prepare and process_prepare_ok when a NORMAL node learns of a higher view. Updates last_normal_view and initializes leader vote bits. Invariant checker: Track node liveness across ticks (prev_alive[]) so min_commit monotonicity is correctly relaxed for nodes that just restarted. https://claude.ai/code/session_01X2b5VRntA7LM32kdN9tPAM
This commit is contained in:
@@ -7,20 +7,12 @@
|
||||
|
||||
typedef struct {
|
||||
MetaOper oper;
|
||||
uint32_t votes; // transient, not persisted to disk
|
||||
int view_number;
|
||||
uint64_t client_id;
|
||||
uint64_t request_id;
|
||||
} WALEntry;
|
||||
|
||||
// On-disk representation of a WAL entry (excludes transient 'votes' field).
|
||||
typedef struct {
|
||||
MetaOper oper;
|
||||
uint32_t votes;
|
||||
int view_number;
|
||||
uint64_t client_id;
|
||||
uint64_t request_id;
|
||||
uint32_t checksum; // FNV-1a over all preceding fields
|
||||
} WALEntryDisk;
|
||||
} WALEntry;
|
||||
|
||||
_Static_assert(NODE_LIMIT <= 32, "");
|
||||
|
||||
@@ -53,6 +45,9 @@ void wal_move(WAL *dst, WAL *src);
|
||||
// fsyncs before updating the in-memory buffer.
|
||||
int wal_append(WAL *wal, WALEntry entry);
|
||||
|
||||
// Write a modified in-memory entry back to disk (recomputes checksum).
|
||||
int wal_update_entry(WAL *wal, int idx);
|
||||
|
||||
// Truncate the WAL to new_count entries.
|
||||
int wal_truncate(WAL *wal, int new_count);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user