Skip to main content

WrDiskCache

Struct WrDiskCache 

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

Write-back disk cache with LRU eviction and bounded memory usage.

WrDiskCache buffers disk writes before flushing them to persistent storage. It uses an LRU (Least Recently Used) eviction policy that never evicts dirty (unflushed) entries, guaranteeing no data loss under memory pressure.

Entries are keyed by their start offset in a BTreeMap, enabling O(log n) range lookups for read(). LRU ordering is preserved via a per-entry monotonic seq number — during eviction the clean entry with the smallest seq (oldest insertion) is removed first.

Implementations§

Source§

impl WrDiskCache

Source

pub fn new(max_size_mb: usize) -> Self

Create a new WrDiskCache with a maximum size specified in megabytes.

§Arguments
  • max_size_mb - Maximum cache capacity in megabytes
§Example
let cache = WrDiskCache::new(16); // 16 MB max
Source

pub fn with_max_size_bytes(max_size_bytes: usize) -> Self

Create a new WrDiskCache with a maximum size specified in bytes.

This provides finer-grained control than WrDiskCache::new which takes megabytes.

§Arguments
  • max_size_bytes - Maximum cache capacity in bytes
Source

pub fn max_size_bytes(&self) -> usize

Returns the maximum cache size in bytes.

Source

pub fn current_size_bytes(&self) -> usize

Returns the current approximate cache size in bytes (lock-free).

Note: This is an atomic snapshot and may be slightly stale if a write or eviction is concurrently in progress.

Source

pub async fn write(&self, offset: u64, data: Bytes) -> Result<()>

Write data at the given offset into the cache.

If writing this entry would exceed max_size_bytes, LRU eviction is triggered. Only clean (already-flushed) entries are eligible for eviction — dirty entries are never evicted to prevent data loss. If insufficient clean entries exist to make room, the cache may temporarily exceed its limit until a flush occurs.

§Zero-Copy

This method accepts bytes::Bytes which enables zero-copy slicing. The caller can pass a slice of a larger buffer without copying.

Source

pub async fn read(&self, offset: u64, length: u64) -> Result<Option<Bytes>>

Read cached data at the given offset and length.

Returns Some(data) if the requested range is fully contained in a cached entry, or None if the data is not in the cache.

§Complexity

O(log n) — a single BTreeMap::range lookup finds the unique candidate entry (the one with the largest start key <= offset). If that entry does not fully cover [offset, offset+length), no other entry can (entries with smaller keys end before offset; entries with larger keys start after offset).

§Zero-Copy

Returns bytes::Bytes slice instead of Vec<u8>, avoiding memory allocation.

Source

pub async fn flush(&self) -> Result<Vec<CacheEntry>>

Flush all dirty entries, returning them for persistence.

After flushing, entries remain in the cache but are marked as clean (eligible for future LRU eviction). The caller is responsible for writing the returned entries to durable storage.

The returned CacheEntry clones are O(1): bytes::Bytes is an Arc-backed buffer, so cloning only bumps a reference count — no data copy occurs.

Source

pub async fn clear(&self) -> Result<()>

Clear all entries from the cache and reset size tracking.

Source

pub async fn size(&self) -> usize

Returns the current total size of cached data in bytes.

Source

pub async fn is_empty(&self) -> bool

Returns true if the cache contains no entries.

Source

pub async fn count(&self) -> usize

Returns the number of entries in the cache.

Source

pub async fn dirty_count(&self) -> usize

Returns the number of dirty (unflushed) entries.

Trait Implementations§

Source§

impl Default for WrDiskCache

Source§

fn default() -> Self

Returns the “default value” for a type. 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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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