Skip to main content

ExplodedCache

Struct ExplodedCache 

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

The two pools, one door. Everything that used to call an ExplodedArchive calls this instead; the eager pool is an ExplodedArchive and behaves exactly as it did.

Implementations§

Source§

impl ExplodedCache

Source

pub fn open(base: &Path, policy: ExplodePolicy, budget: u64) -> Result<Self>

Open both pools at base (…/objects.exploded), adopting whatever lazy segments a previous process left beside it.

Source

pub fn registered(self: Arc<Self>) -> Arc<Self> ⓘ

Register this cache so a dashboard tick can read every open store’s band without holding a store lock — the same Weak registry crate::progress keeps, for the same reason and with the same sweep.

Source

pub fn root(&self) -> &str

Source

pub fn set_budget(&self, bytes: u64)

The quota, changed live — what the control plane sets when an account’s plan changes. Takes effect at the next rotation; it never refuses a write and never deletes on the caller’s thread.

Source

pub fn set_global_line(&self, bytes: u64)

The process-wide line this cache holds itself to its fair share of. 0 turns the global check off. Tests set it small; production takes default_global_line at open.

Source

pub fn set_disk_line_percent(&self, percent: u64)

The disk line, changed live. 0 turns it off. Takes effect at the next rotation, like the budget.

Source

pub fn pressure_refused_write_backs(&self) -> u64

Write-backs refused while the disk line was latched.

Source

pub fn budget(&self) -> u64

Source

pub fn policy(&self) -> ExplodePolicy

Source

pub fn path(&self) -> &Path

Source

pub fn explode( &self, oid: &[u8], kind: GitObjectKind, payload: &[u8], ) -> Result<()>

The eager write — the indexer’s sink, at push time. Unchanged behaviour: the policy decides, and what it declines is counted as skipped rather than silently dropped.

Source

pub fn explode_at( &self, oid: &[u8], kind: GitObjectKind, mode: Option<u32>, path: Option<&str>, payload: &[u8], ) -> Result<()>

Source

pub fn write_back( &self, oid: &[u8], kind: GitObjectKind, payload: &[u8], cost: ReadCost, ) -> Result<bool>

The lazy write-back — one object a reader has just inflated from the pack, kept for the next reader.

Buffers only: it appends to the newest segment’s in-memory rows and returns. Nothing is written, nothing is fsynced, no eviction runs. The reader that called it has its bytes already and is not made to wait for anybody — Self::maintain does the I/O on the store’s own thread. Two readers racing on one oid is benign: the same bytes are buffered twice and the newest row wins, which is what ExplodedArchive::explode_at already promises.

Source

pub fn maintain(&self) -> Result<u64>

Write down what is buffered, rotate if the newest segment is full, and evict until the pools fit the budget. The whole of the tier’s I/O, on one thread that is nobody’s reader.

Returns the bytes reclaimed, so a caller can log applied output rather than an intention.

Source

pub fn content(&self, oid: &[u8]) -> Result<Option<(GitObjectKind, Vec<u8>)>>

The object’s kind and bytes from either pool, or None — fall back and re-derive, never wrong.

Eager first: it is the smaller table, its index is the one already warm, and under the shipped policy it holds exactly the objects a graph walk asks for. Then the lazy segments newest first, so a re-entered object is found before the stale copy an older segment may still hold.

Source

pub fn has(&self, oid: &[u8]) -> Result<bool>

Source

pub fn name(&self, oid: &[u8]) -> Result<Option<(Option<u32>, Option<String>)>>

Source

pub fn of_kind(&self, kind: GitObjectKind) -> Result<Vec<(Vec<u8>, Vec<u8>)>>

Every oid of one kind, across both pools, newest spelling winning.

The graph fold’s input. Under the shipped policy every commit is in the eager pool, so this is one table’s scan and the lazy segments add nothing — but it unions rather than assuming that, because a store opened under a different policy must still fold a whole graph.

Source

pub fn retain(&self, live: &dyn Fn(&[u8]) -> bool) -> Result<u64>

Retire every oid live rejects — in both pools.

Both, and that is not defensive: a tombstone written only into the eager pool would leave the lazy pool’s row live, content would fall through to it, and a gc’d object would come back by the second door. That is the same defect a_wholly_dead_pack_does_not_come_back_when_the_store_is_reopened found the first time, one pool along.

Source

pub fn drop_cache(&self) -> Result<u64>

repo gc reclaims the cache. Every lazy segment is unlinked; the eager pool keeps its rows, because they are the graph. Returns the bytes that left the filesystem.

Source

pub fn flush(&self) -> Result<()>

Source

pub fn drop_caches(&self)

What the memory watchdog reaches for: every derived, rebuildable structure in every pool.

Source

pub fn rows(&self) -> Result<u64>

Source

pub fn eager_rows(&self) -> Result<u64>

Rows in the EAGER pool only — what adopt_journal compares against the index, because the lazy pool’s size is a function of what has been read and says nothing about whether a pack was absorbed.

Source

pub fn disk_bytes(&self) -> u64

Source

pub fn use_now(&self) -> CacheUse

Source

pub fn note_rederived(&self)

Source

pub fn pread_served(&self) -> u64

Source

pub fn skipped(&self) -> u64

Source

pub fn engine_stats(&self) -> ExplodedStats

The engine-wide counters, summed over both pools, so no caller can tell the two apart by its instruments.

Source

pub fn kick(self: &Arc<Self>)

Start the write-back thread if one is not already running — and return to the reader immediately either way.

The owner’s law, from the design note: nobody waits. The reader already has its bytes; the append, the fsync, the rotation and the eviction all happen here, on a thread that is nobody’s request. A thread per 4 MiB of write-back rather than a parked thread per store, because a box holding 1 200 open repositories (lane V) cannot afford 1 200 idle threads and can easily afford one spawn per few thousand objects read.

The flag is the whole of the mutual exclusion: a second reader finding it set does nothing, and the running thread loops until the buffer is empty before clearing it, so no work is dropped between the two.

Trait Implementations§

Source§

impl PayloadSink for ExplodedCache

Source§

fn wants(&self, kind: GitObjectKind) -> bool

Will this sink read the payload of an object of this kind? Read more
Source§

fn explode(&self, oid: &[u8], kind: GitObjectKind, payload: &[u8]) -> Result<()>

One resolved object: its oid, the type its chain resolves to, and the inflated payload. Called once per pack entry, never for a delta’s intermediate state.
Source§

fn flush(&self) -> Result<()>

Write down whatever is buffered. Called by the resolver when the memory watchdog says the box is short (crate::memguard) and at the end of a pack; a sink that buffers nothing has nothing to do.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

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