commit method
Commit pending dirty pages to disk and finalise the transaction.
Protocol:
- fsync the journal (already done incrementally on each undo capture).
- Write every dirty page to the data file at its offset.
- fsync the data file.
- Delete the journal — this is the atomic commit point.
Implementation
Future<void> commit() async {
_ensureOpen();
if (_dirty.isEmpty && _journal == null) return;
// Make sure the data file is large enough for any newly allocated
// pages — if we appended in [allocatePage] but never wrote anything
// beyond their cached buffer, the file may still be short.
final needLen = _pageCount * pageSize;
if (await _data!.length() < needLen) {
await _data!.truncate(needLen);
}
// Flush dirty pages in sorted order for predictable I/O patterns.
// A dirty page may have been evicted (its bytes were written
// through under the journal) — in that case it's already on disk
// and there's nothing to do at commit time.
final sorted = _dirty.toList()..sort();
for (final p in sorted) {
final buf = _cache[p];
if (buf == null) continue; // already flushed via eviction
await _data!.setPosition(p * pageSize);
await _data!.writeFrom(buf);
}
await _data!.flush();
_dirty.clear();
_journaled.clear();
await _closeAndDeleteJournal();
}