55 lines
include/wal_writer.h
Declares WalWriter with the on-disk format contract and size limits.
// WalWriter: append-only write-ahead log for the embedded key-value store.
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
 
// Maximum size of one WAL record payload in bytes.
static constexpr uint16_t kMaxRecordSize = 1024;
 
// On-disk WAL record layout (fixed format):
//   [uint16_t length]  — number of payload bytes that follow
//   [payload bytes]    — raw record data (length bytes)
//   [uint32_t crc32]   — CRC32 over the payload bytes only
//
// Recovery reads the length field first to determine the read size.
// Any deviation from this field order makes recovery read garbage lengths.
class WalWriter {
public:
  // Parameters:
  //   path - filesystem path to the WAL file; opened in append + read mode
  // Returns: new WalWriter; check isOpen() before first use
  explicit WalWriter(const char* path);
  ~WalWriter();
 
  // Appends one record to the WAL in the documented [length][payload][crc] format.
  // Parameters:
  //   data - payload bytes to append; must not exceed kMaxRecordSize
  // Returns: true if the record was fully written; false on I/O error or size violation
  bool writeRecord(const std::string& data);
 
  // Reads and validates the next record from the current file position.
  // Length fields from corrupted headers must be validated against kMaxRecordSize
  // before any allocation or read to prevent out-of-bounds access.
  // Parameters:
  //   out - receives the payload bytes on success; cleared on failure
  // Returns: true if a complete, CRC-valid record was read; false otherwise
  bool recoverRecord(std::string& out);
 
  // Returns true if the WAL file is open and ready for use.
  bool isOpen() const { return fp_ != nullptr; }
 
  // Rewinds the file position to the beginning for replay.
  void rewind() { if (fp_) std::rewind(fp_); }
 
private:
  std::FILE* fp_ = nullptr;
 
  // Computes CRC32 over the given buffer.
  // Parameters:
  //   data - pointer to the input bytes
  //   len - number of bytes to process
  // Returns: CRC32 checksum of the input
  static uint32_t computeCrc32(const char* data, std::size_t len);
};