openSync method
void
openSync()
Loads the manifest and replays the WAL. Call once before serving reads.
Implementation
void openSync() {
final store = ManifestStore(_directory);
final sawManifest = ManifestStore.slotNames.any(_directory.existsSync);
// A single torn slot with a non-empty WAL is the signature of a crash in
// the very first manifest write: the WAL was not truncated yet, so every
// record is still there. Two bad slots are real corruption and stay fatal.
final manifest = store.loadSync(
allowTornSingleSlot: !readOnly && _walFile.lengthSync > 0,
);
if (manifest == null && sawManifest) {
// Keep the database writable: the unusable slots cannot be part of the
// next generation, and the WAL replay below reconstructs the state.
_recoveredFromWal = true;
for (final name in ManifestStore.slotNames) {
if (_directory.existsSync(name)) _directory.deleteSync(name);
}
}
if (manifest != null) {
_manifest = manifest;
for (final info in manifest.segments) {
// The manifest is data; a corrupted or hostile name must never escape
// the database directory through mapSync.
if (!_segmentNamePattern.hasMatch(info.name)) {
throw VelxoCorruptException(
'manifest references an invalid segment name: ${info.name}',
);
}
// Segments are immutable: map them instead of copying. The view stays
// valid until close(), which unmaps after the engine stops serving.
final mapped = _directory.mapSync(info.name);
try {
final reader = SegmentReader(mapped.bytes);
_segmentMaps.add(mapped);
_segments.add(reader);
_segmentInfos.add(info);
_trackSegmentId(info.name);
} on Object catch (error) {
mapped.closeSync();
throw VelxoCorruptException('segment ${info.name} is corrupt', error);
}
}
}
for (final name in _directory.listSync()) {
if (name.startsWith(segmentPrefix) && name.endsWith(segmentSuffix)) {
_trackSegmentId(name);
}
}
_wal.replaySync((payload) {
WalBatch.decode(payload, (kind, key, value) {
if (kind == WalOpKind.put) {
final ref = _arena.append(value!);
_memtable.put(key, ref.chunk, ref.offset, ref.length);
} else {
_memtable.putTombstone(key);
}
});
}, truncateTorn: !readOnly);
}