Skip to main content

LedgerIndex

Struct LedgerIndex 

Source
pub struct LedgerIndex { /* private fields */ }
Expand description

seq → (segment file name, byte offset of the line start).

The maps live in [Folded]; what this type adds is the filesystem seam they are folded from. The seam sits behind a lock so a caller holding &LedgerIndex asks questions without exclusive access, and every question this type answers is a read: nothing here writes.

Implementations§

Source§

impl LedgerIndex

Source

pub fn rebuild(dir: &Path) -> Result<LedgerIndex, StorageError>

Scans the ledger directory into a fresh index.

§Errors

Propagates a ledger directory that cannot be listed or read.

Source

pub fn folding( dir: &Path, each: impl FnMut(&[u8]) -> Result<Option<Located>, AxError>, ) -> Result<LedgerIndex, AxError>

Reads the ledger once for a fold and for the index together: each complete line is lent to each in ledger order, then indexed at its offset. each returns the line’s place when it has read it already, so the index does not parse the line again, or None for the index to locate it by the rule rebuild uses. One segment’s bytes are resident at a time, and the index covers exactly the lines each saw: a line appended during the fold waits for refresh.

§Errors

The first error each returns, or a ledger directory that cannot be listed or read. The lines before it were already lent, so the caller discards what it folded.

Source

pub fn empty() -> LedgerIndex

An index over nothing.

For a holder that wants one before the ledger directory exists: the first refresh fills it, and until then every lookup answers SeqMissing, which is the truth.

Source

pub fn refresh(&mut self, dir: &Path) -> Result<Refreshed, StorageError>

Folds whatever has been appended since the last look.

A resident index is the point: rebuilding one scans every segment and allocates a String for every line in it, which on a fifty thousand record ledger was 14.4 ms charged to every single history query. Refreshing costs one directory listing plus a stat per segment, and reads only the bytes that are new.

The incremental face is here rather than an “index, a record just landed” call on the writer’s side, because a caller holds an EventRecord and segments are this crate’s own business. Handing an offset to an observer would leak the layout to everyone.

A segment that shrank or vanished forces a full rebuild: tail recovery truncates, and after it the offsets held for that segment describe bytes that are no longer there.

The answer reports how many bytes this refresh read, which is what separates seeking to the tail from lifting the segment that holds it.

§Errors

Propagates a ledger directory that cannot be listed, stat’ed or read.

Source

pub fn reader(&self, dir: &Path) -> LineReader<'_>

A cursor for reading lines out of this index.

The unit of work is a stretch of sequences rather than one of them, so the handle belongs to the stretch: a caller asks for a reader once and then for lines as often as it likes.

Source

pub fn run_seqs_before( &self, run: RunId, before: Option<Seq>, ) -> impl Iterator<Item = Seq>

The sequences one run wrote, newest first, below before.

Newest first because what a reader opens a session for is its end; a caller that wants them oldest first takes what it needs and reverses a list it already holds, which also lets it read the segment forwards.

before is exclusive, the same word and the same meaning the wire gives HistoryAnswer::earlier, so paging by handing one answer’s cursor to the next question can neither repeat nor skip a record.

A run this index never saw yields nothing, which is the truth and needs no separate answer.

The walk is lazy: taking n values costs n steps, not the length of the run.

Source

pub fn seqs(&self) -> impl DoubleEndedIterator<Item = Seq> + '_

Every seq the index holds, ascending: the walk a reader takes to read the whole ledger forwards, which is its fast direction.

Source

pub fn seqs_from(&self, from: Seq) -> impl DoubleEndedIterator<Item = Seq> + '_

Every seq the index holds at or after from, ascending: the walk a reader takes to read a stretch forwards from where it starts.

The walk starts at from rather than skipping the seqs before it, so reading a stretch costs the stretch, however long the ledger before it is (crates/storage/Spec.lean §8-38). from need not be a seq anybody wrote; nothing at or after it yields nothing.

Source

pub fn tail_seq(&self) -> Option<Seq>

Source

pub fn len(&self) -> usize

Source

pub fn is_empty(&self) -> bool

Trait Implementations§

Source§

impl<'de> Deserialize<'de> for LedgerIndex

Source§

fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for LedgerIndex

Only the folded maps are written: the seam is this process’s own, and an index read back reaches disk through a new one. A views snapshot carries the index this way (crates/storage/spec/Index.lean §8-4).

Source§

fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.