Skip to main content

Writer

Struct Writer 

Source
pub struct Writer<B: Blob, Phase = Append> { /* private fields */ }
Expand description

Unique writer to a cache-wrapped Blob.

Storage-mutating functions consume the writer and return it only on success: an error (or a dropped future) destroys the handle.

Implementations§

Source§

impl<B: Blob> Writer<B, Recovering>

Source

pub async fn open( blob: B, original_blob_size: u64, capacity: usize, cache_ref: CacheRef, ) -> Result<Self, Error>

Open blob for initialization repair.

blob must already hold original_blob_size physical bytes. Reads are cached through cache_ref and appends stage in a write buffer of capacity capacity. Trims any invalid tail so the blob ends at a checksum-validated page. Earlier pages are not scanned.

Before appending, the tail-page contents must be durable: either pass a blob with no writes since it was opened or call Self::sync. Until then, recovery may read or truncate the blob. The discovered checksum slot seeds durable-slot tracking, so appending over a still-volatile tail can overwrite the only durable slot.

Source

pub async fn truncate(self, size: u64) -> Result<Self, Error>

Durably retain at most size logical bytes.

A size above the current length leaves the length unchanged. Pending writes are synchronized even when the length does not change.

Outstanding replays that cover the shortened or rewritten suffix are invalidated and must not be consumed afterward.

Source§

impl<B: Blob> Writer<B>

Source

pub async fn new( blob: B, size: u64, capacity: usize, cache_ref: CacheRef, ) -> Result<Self, Error>

Open a paged blob, repairing incomplete tail pages before publishing its writer. The existing tail must be durable, and no previous writer or disk-backed reader may access this storage incarnation during initialization.

Source

pub async fn snapshot(self) -> Result<(Self, Sealed<B>), Error>

Capture an immutable Sealed view of the logical bytes.

Buffered full pages are written to the blob, and the partial page is copied into the view. Neither is made durable. Call Self::sync if the returned handle’s bytes must survive a crash.

Later appends preserve this view, including its frozen partial page.

Source

pub fn try_snapshot(&self) -> Option<Sealed<B>>

Capture an immutable Sealed view of the logical bytes without writing to the blob.

This is Self::snapshot without its flush. It returns the same view when every full page is already in the blob, and None while the write buffer holds a full page that has not been written.

Source

pub async fn read_range( blob: &B, logical_page_size: NonZeroU16, offset: u64, len: usize, read_options: ReadOptions, ) -> Result<IoBufs, Error>

Read a logical range directly from a raw paged blob, validating every page it spans.

Returns Error::BlobInsufficientLength when valid page contents do not cover the whole range, and Error::OffsetOverflow when its end or page offsets overflow.

Source

pub async fn read_tail( blob: &B, physical_size: u64, logical_page_size: NonZeroU16, len: usize, read_options: ReadOptions, ) -> Result<(u64, IoBufs), Error>

Read the terminal logical range of a raw paged blob and return its logical size.

The blob must contain only complete physical pages. The last page is validated first to determine the logical end. If len crosses a page boundary, preceding pages are validated with Self::read_range.

Source

pub async fn seal(self) -> Result<(Sealed<B>, Handle<()>), Error>

Consume the write handle, flushing buffered bytes and beginning a sync of the blob.

Returns an immutable Sealed read handle plus a completion handle for the started sync. Reads through the Sealed handle observe flushed bytes immediately. Durability isn’t guaranteed until the sync handle completes.

Source§

impl<B: Blob, Phase> Writer<B, Phase>

Source

pub async fn append(self, buf: &[u8]) -> Result<(Self, u64), Error>

Append all bytes in buf to the tip of the blob, returning the logical offset at which the first byte was written.

Source

pub fn try_append(&mut self, buf: &[u8]) -> Option<u64>

Append buf to the write buffer if it fits.

Returns its logical offset on success. Returns None without changing the writer when there is insufficient buffer space. Performs no I/O and does not make the append durable. Callers can fall back to Self::append_owned when it does not fit.

Source

pub fn try_append_value<T: EncodeSize + Write>( &mut self, value: &T, ) -> Option<u64>

Encode a value directly into the write buffer if it fits.

Returns its logical offset on success. Returns None without encoding or changing the writer when there is insufficient buffer space. Performs no I/O and does not make the append durable. Callers can fall back to Self::append_owned when it does not fit.

§Panics

Panics if the encoder writes a different number of bytes than EncodeSize::encode_size.

Source

pub async fn append_owned(self, buf: IoBuf) -> Result<(Self, u64), Error>

Append owned bytes to the tip of the blob.

Large appends fill the current tip to a page boundary, write complete pages directly to the blob, and leave only a sub-page suffix in the write buffer. This avoids copying full-page payloads while preserving the invariant that the buffer starts at current_page.

Source

pub const fn size(&self) -> u64

Returns the size of the blob.

Source

pub fn needs_sync(&self) -> bool

Whether Self::sync would write buffered bytes, sync the blob, or observe a started sync.

Source

pub fn try_read_sync_into(&self, buf: &mut [u8], offset: u64) -> bool

Read into buf if it can be done synchronously without I/O. Returns true only if all buf.len() bytes were satisfied from the page cache and/or the in-memory tail. When false is returned, the contents of buf are unspecified.

Source

pub async fn read_at(&self, offset: u64, len: usize) -> Result<IoBufs, Error>

Read exactly len immutable bytes starting at offset.

Source

pub async fn read_up_to( &self, offset: u64, len: usize, bufs: impl Into<IoBufMut> + Send, ) -> Result<(IoBufMut, usize), Error>

Reads up to len bytes starting at offset, but only as many as are available.

Returns the buffer (truncated to actual bytes read) and the number of bytes read. Returns an error if no bytes are available at the given offset.

Source

pub async fn read_many_into( &self, buf: &mut [u8], offsets: &[u64], item_size: NonZeroUsize, ) -> Result<usize, Error>

Read multiple fixed-size items at sorted byte offsets into a contiguous caller buffer.

buf must be exactly offsets.len() * item_size bytes. All offsets must be sorted, non-overlapping, and within bounds.

Returns the number of items fully served without a blob read (from the in-memory tail and the page cache). The remaining items required at least one blob read.

Source

pub async fn read_ranges_into( &self, buf: &mut [u8], ranges: &[(u64, usize)], ) -> Result<usize, Error>

Like Self::read_many_into, but each (offset, len) range has its own length. buf holds the ranges back to back.

Returns how many ranges were served entirely from the in-memory tail and page cache before any blob read. Empty ranges count as served.

§Panics

Panics if a range starts before the previous range ends, or if buf is not the ranges’ total length.

Source

pub fn try_read_many_sync_into( &self, buf: &mut [u8], offsets: &[u64], item_size: NonZeroUsize, ) -> Vec<usize>

Like Self::read_many_into, but synchronous and cache-only. Returns the indices of items that require a blob read. Their slots in buf hold unspecified bytes.

Source

pub fn try_read_ranges_sync_into( &self, buf: &mut [u8], ranges: &[(u64, usize)], ) -> Vec<usize>

Like Self::try_read_many_sync_into, but for variable-length (offset, len) ranges: buf holds one slot per range, back to back.

Source

pub async fn read_into(&self, buf: &mut [u8], offset: u64) -> Result<(), Error>

Reads bytes starting at offset into buf.

Source

pub async fn replay( self, buffer_size: NonZeroUsize, read_options: ReadOptions, ) -> Result<(Self, Replay<B>), Error>

Flushes any buffered data, then returns the writer with a Replay for the underlying blob.

The returned replay validates that every stored page holds a full page and retains a frozen copy of the current partial page. CRCs are not included in the output. Every underlying blob read performed by the returned replay uses read_options, including refills after seeking.

Pages are read in batches as for Sealed::replay, which describes what buffer_size bounds.

This does not establish durability. Use sync if the replayed bytes must survive a crash.

Source

pub async fn sync(self) -> Result<Self, Error>

Flushes buffered data and makes all pending mutations durable.

A newly flushed write can carry WriteOptions::SYNC when no earlier mutation is pending. Otherwise, Blob::sync provides the barrier for all pending mutations.

Source

pub async fn start_sync(self) -> Result<(Self, Handle<()>), Error>

Flushes buffered data and begins making all pending mutations durable, returning a completion handle.

Awaiting the returned Handle waits for the same durability guarantee as Self::sync for the state flushed by this call. Later calls to Self::sync and writer methods that mutate the blob first wait for any outstanding start_sync handles. A failure of the started sync is reported by the handle and by the next such call. Flush errors are returned directly.

Source

pub async fn recoverable_prefix_len( &self, proven: u64, buffer_size: NonZeroUsize, read_options: ReadOptions, ) -> Result<u64, Error>

Length of the longest contiguous prefix of well-formed pages on the blob.

Recovery::open sizes a blob by scanning backward to its last valid page, which cannot detect an earlier page that was lost or corrupted. This scans forward instead, stopping at the first invalid or short page.

Expects all appended bytes to have reached the blob (as after recovery): a partial page still buffered in this writer is unreadable from the blob and fails the scan. buffer_size bounds each blob read, with a minimum of one physical page. Applies read_options to every blob read.

proven is a logical byte offset already known valid (a durability watermark or a replay-validated prefix). Pages wholly below it are accepted without reading, and the scan starts at the page containing it. A proof past the blob’s content clamps to the full pages that exist. A partial tail must be read to determine its valid length.

Source

pub async fn recoverable_prefix_len_at_most( &self, proven: u64, max_size: u64, buffer_size: NonZeroUsize, read_options: ReadOptions, ) -> Result<u64, Error>

Like Self::recoverable_prefix_len, but returns at most max_size logical bytes.

Reads only pages intersecting the prefix below max_size. A cap inside a page requires validating that entire page’s checksum. Zero requires no reads. A cap above the stored end does not extend the prefix. proven has the same meaning as in the unbounded scan.

Source

pub async fn wait_for_sync(self) -> Result<Self, Error>

Wait for any started sync to complete without starting a new sync.

Trait Implementations§

Source§

impl<B: Blob> From<Writer<B, Recovering>> for Writer<B>

Source§

fn from(recovery: Recovery<B>) -> Self

Convert recovery into a live writer without flushing or syncing.

Truncation is already durable. Bytes appended since the last completed sync remain unsynced.

Auto Trait Implementations§

§

impl<B, Phase = Append> !Freeze for Writer<B, Phase>

§

impl<B, Phase = Append> !RefUnwindSafe for Writer<B, Phase>

§

impl<B, Phase = Append> !UnwindSafe for Writer<B, Phase>

§

impl<B, Phase> Send for Writer<B, Phase>
where PhantomData<Phase>: Send, Arc<B>: Send,

§

impl<B, Phase> Sync for Writer<B, Phase>
where PhantomData<Phase>: Sync, Arc<B>: Sync,

§

impl<B, Phase> Unpin for Writer<B, Phase>
where PhantomData<Phase>: Unpin, Arc<B>: Unpin,

§

impl<B, Phase> UnsafeUnpin for Writer<B, Phase>

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self> ⓘ

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Threaded<T> for T

Source§

type Rest = ()

The outputs beyond the threaded value.
Source§

fn split(self) -> (T, ())

Splits into the threaded value and the extra outputs.
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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more