Skip to main content

FillRegistry

Struct FillRegistry 

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

Range-aware coalescing registry: the live in-flight fills, keyed by hash, plus a per-hash captured outboard. A serve-miss consults Self::claim to split its range into an attach (covered by a running pull) and a remainder (fetch it), and Self::range_still_live answers a parked reader’s “keep awaiting or fail?”. Purely synchronous range math under a std Mutex; the lock is never held across an await.

Implementations§

Source§

impl FillRegistry

Source

pub fn new() -> Self

An empty registry with no metrics handle (unit fixtures).

Source

pub fn with_metrics(metrics: Option<Arc<CacheMetrics>>) -> Self

An empty registry that reports its coalescing decisions to metrics.

Source

pub fn register_fill( self: &Arc<Self>, hash: Hash, session: &Arc<FillSession>, ) -> ObserverLease

Publish a new pull’s session (already scoped via FillSession::set_covered to the bytes it will fetch) and return the owner lease (observer count starts at 1). The entry stays in the map until the owning pull is joined node-side. A test-facing helper; production registers via Self::claim.

Source

pub fn in_flight_total(&self, hash: Hash) -> Option<u64>

The blob length of a LIVE in-flight fill for hash, if one runs — an ADVISORY peek the serve-miss path uses to skip its upstream header handshake when a pull it can coalesce onto already exists. Returns the total_bytes of the first non-dead session under hash (every session for one hash shares the blob’s geometry, so any live one’s length is THE length); None when no live fill exists (empty, or only dead sessions remain). Advisory only: a concurrent last-observer drop can retire the peeked session before the caller’s atomic Self::claim, which then owns a fresh pull and opens the leg late — so this NEVER replaces claim, it only removes the handshake in the common coalescing case.

Source

pub fn range_still_live(&self, hash: Hash, range: &ChunkRanges) -> bool

Whether any LIVE fill of hash still covers range. A parked reader calls this (via FillSession::range_still_live) to decide “keep awaiting a capture / present-range advance, or fail because no pull will ever fill this”. true iff some live session’s covered intersects range.

Source

pub fn claim( self: &Arc<Self>, hash: Hash, offset: u64, len: u64, total: u64, make_session: impl FnOnce() -> Arc<FillSession>, ) -> FillClaim

Atomically decide attach/own/mixed AND register any new owner session, all under ONE map-lock acquisition. This closes the coalescing TOCTOU race a separate plan-then-register pair would leave open: between two lock acquisitions another thread can register, so two concurrent fresh misses for the same blob would both see an empty registry and both open a pull. claim holds the lock across the whole decision, so exactly one of two racing identical claims registers an owner and the other attaches.

R = align_range_clamped(offset, len, total): an end past total clamps to it, so a request whose claimed size grows still coalesces with a live fill instead of always falling to Owner. On an align error (a start at or past total) or empty R, the caller takes the Owner path (its own fetch surfaces any out-of-bounds error). Otherwise, over LIVE sessions whose paid frontier reaches R’s aligned fetch start (a session behind that frontier is excluded — attaching to it would park this request on a pull that advances only as the OTHER client pays, #2062; the exclusion trades duplicate egress for the overlap, counted as fill_not_coalesced), covered_union = ⋃ covered, attach = R ∩ covered_union, remainder = R − covered_union:

  • attach empty → OWNER of the whole R.
  • remainder empty (a live pull covers all of R) → ATTACH to the largest-overlap session; make_session is NOT called.
  • both non-empty, and the largest-overlap sibling covers ALL of attach, and R − sibling.covered is ONE contiguous span → MIXED: own a pull for that remainder, attach the sibling for the overlap.
  • otherwise (a multi-sibling union, or an interior overlap splitting the remainder in two) → OWNER of the whole R, the conservative fallback. It never wedges; like the frontier exclusion above it can double-pull an overlap a live sibling also covers.

make_session runs under the lock only on an owning branch (never built-and-dropped on a pure attach); it does no await (a std lock) and only allocates, so holding the lock across it is safe.

Trait Implementations§

Source§

impl Debug for FillRegistry

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for FillRegistry

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> 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<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
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 = !

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<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