pub enum Error {
Io(Error),
Corrupt {
page_no: u32,
why: &'static str,
},
TooLarge,
ReadOnly,
WriterLocked,
CorruptWal {
offset: u64,
why: &'static str,
},
StorePoisoned,
OutOfBudget,
ResourceLimit(&'static str),
DuplicateKey,
RangeNotEmpty,
UnsupportedFormat {
found: u16,
},
}Variants§
Io(Error)
Corrupt
A page failed verification. Carries the page number that was asked for.
TooLarge
A structural limit was hit, e.g. a record too large for a page.
ReadOnly
A mutation was attempted on a snapshot reader (2f). Readers serve the state of one published generation; every write path refuses.
WriterLocked
Another live writer already owns the data file. The lock is advisory and attached to that writer’s file descriptor, so dropping the handle or process exit releases it; snapshot readers do not take this lock.
CorruptWal
The write-ahead log holds something at offset that cannot be
accepted AND cannot be treated as the log simply ending there –
Wal::scan classified it Stop::Damaged (see that type). open
refuses rather than truncating past it, because the bytes behind it
may be committed frames and a reader that is unsure has no business
deleting them (Law 3).
NOT terminal, and that is half the design rather than a detail (Law
5): a refusal with no way to clear it is as unrecoverable as a
deletion. recover() is the way through – it copies and hashes the
whole log as wal.corrupt.N, resynchronises later committed regions
into a verified live log, and the store opens. A previous round shipped this
refusal without that path and turned 29 of 400 single-bit flips into
stores that would never open again.
Deliberately not Corrupt: a WAL frame has no page number, and
reusing page_no for a byte offset would mislabel what failed.
StorePoisoned
A Store whose logged write or checkpoint failed partway through
refuses every further write. A tree error may escape after a leaf was
compacted or split but before its replacement or parent was installed;
flush_all clears each frame’s dirty bit
BEFORE its barrier is issued, so a barrier that fails does not mean
the writes never happened – those bytes can already be sitting in
the OS page cache, forgotten by our own bookkeeping, and reach the
disk anyway via later, unrelated writeback with no further fsync from
us. The store therefore cannot say whether its last checkpoint took
effect, and the pages it believes clean may not be durable.
What makes continuing actively dangerous rather than merely
uncertain is checkpoint’s last step: Wal::rotate DELETES the log.
A second checkpoint would flush nothing (those frames are marked
clean), issue a barrier that may well return Ok this time – a
failed fsync is reported once and the kernel then forgets it – and
go on to discard the one remaining copy of records whose pages never
reached the medium. That is Law 3 exactly: something that can be
wrong about what exists, deleting. So every writer refuses:
put, delete, commit, checkpoint and bulk_load alike.
NOT a dead end (Law 5). The flag is per-instance and never persisted:
dropping the Store and calling Store::open again clears it, and
that reopen is not a way of ignoring the problem – it re-reads
Meta from disk and replays the log, which is what re-establishes
what is actually durable. recover() is available for the case where
the reopen itself finds damage.
OutOfBudget
A memory reservation could not be granted.
ResourceLimit(&'static str)
A configured resource ceiling refused work. A partially changed writer must be dropped and reopened; committed metadata and readers survive.
DuplicateKey
A bulk load’s input contained two entries with the same key. Not
Corrupt – page 0 is the superblock, and naming it for a condition
that has nothing to do with a page reads as structural damage in a
log when it is really just an input the caller must deduplicate.
RangeNotEmpty
A packed range can only be grafted where the live tree has no key. Overwriting through this path would bypass ordinary update semantics.
UnsupportedFormat
The file is not a sekejap disk format v2 file: an intact page claims
the disk-format version in found at bytes 18-19 and this build
reads 2 and nothing else (page::FORMAT_VERSION,
docs/core/FORMAT_V2.md).
Raised before any byte of the source is changed, and never converted: there is no v1, no e1 file and no silent conversion, so the only honest answer is to name the number the file carries and stop. Zero is what an e4 pre-release file carries.
Trait Implementations§
Source§impl Display for Error
Every variant says what failed AND where the way out is, because these
strings are what a wrapper user sees: a refusal with no route forward
reads as a dead end (Law 5), and the Display text is often the only
part of that law a caller ever meets.
impl Display for Error
Every variant says what failed AND where the way out is, because these
strings are what a wrapper user sees: a refusal with no route forward
reads as a dead end (Law 5), and the Display text is often the only
part of that law a caller ever meets.
Source§impl Error for Error
impl Error for Error
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()