Skip to main content

FlushController

Struct FlushController 

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

Manages the active and frozen memtable lifecycle.

The controller holds an active memtable that accepts writes, and optionally a frozen memtable that is being flushed. Writes go to the active memtable; when the flush threshold is reached, the active memtable is frozen and swapped for a fresh one.

Implementations§

Source§

impl FlushController

Source

pub fn new(config: FlushConfig) -> Self

Create a new flush controller with the given configuration.

Source

pub fn active_memtable(&self) -> Arc<Memtable> ⓘ

Get a reference to the active memtable.

Source

pub fn frozen_memtable(&self) -> Option<Arc<Memtable>>

Get a reference to the frozen memtable, if any.

Source

pub fn insert(&self, point: &Point) -> Result<()>

Insert a point into the active memtable.

§Errors

Returns MemtableError::CapacityExceeded if the total memory (active + frozen) exceeds the configured maximum.

Source

pub fn insert_with_wal_seq(&self, point: &Point, wal_seq: u64) -> Result<()>

Insert a point that is already durable in the WAL at wal_seq.

No capacity check. Admission control runs before the WAL append; what the WAL holds is inserted unconditionally, because a record that is durable but in no memtable is a record the next flush’s WAL floor may pass — and then it is lost. The same applies to replay at open: rejecting an acknowledged record for being over a memory cap is silent data loss, not backpressure.

§Errors

Returns MemtableError::Frozen if the active memtable was frozen concurrently — which the freeze/insert lock order makes impossible from this method.

Source

pub fn frozen_count(&self) -> usize

How many memtables are frozen and waiting to be flushed.

Source

pub fn is_idle(&self) -> bool

true when neither the active memtable nor any frozen one holds a point.

Source

pub fn should_flush(&self) -> bool

Check whether the flush threshold has been reached.

Source

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

Freeze the active memtable and swap in a fresh one.

The frozen memtable is stored for later flushing.

§Errors

Returns an error if there is already a frozen memtable that hasn’t been flushed yet.

Source

pub fn flush_frozen(&self) -> Result<Vec<FlushResult>>

Flush the oldest frozen memtable to segment files.

Equivalent to flush_frozen_with with a registration step that does nothing.

§Errors

See flush_frozen_with.

Source

pub fn flush_frozen_with<F>(&self, register: F) -> Result<Vec<FlushResult>>
where F: FnMut(&[FlushResult]) -> Result<()>,

Flush the oldest frozen memtable to segment files and hand the results to register before letting the memtable go.

Groups points by measurement and writes one .csx segment per measurement, so each segment holds exactly one measurement.

The frozen memtable is released only after every segment is written and register has returned Ok. If either fails, the files written so far are removed and the memtable stays at the head of the frozen queue for the next attempt — otherwise a failed write drops the only in-memory copy while the next flush raises the WAL floor past its records. Registration is inside the same window: a segment on disk but not in the catalog is an orphan the next open deletes.

One flush per controller at a time; a concurrent caller waits.

§Errors

Returns MemtableError::NoFrozenMemtable if nothing is frozen or the frozen memtable is empty (it is discarded), the segment writer’s error, or register’s error.

Source

pub fn scan( &self, series_key: &SeriesKey, min_ts: i64, max_ts: i64, ) -> Vec<Point>

Scan both active and frozen memtables for a specific series.

Deduplicated by timestamp, newest write wins — the active memtable first, then the frozen queue newest to oldest.

The result is a set, in no particular order. ShardRouter sorts by timestamp across shards, and every caller reaches this through it.

§Consistency

Both memtable references are obtained under a single scope following frozen→active lock order (matching freeze_and_swap). This prevents a race where freeze_and_swap() moves data between the two reads.

Source

pub fn scan_all(&self) -> Vec<Point>

Scan all points across both active and frozen memtables.

Deduplicated by (series, timestamp), newest write wins. Unordered — see scan_measurement.

Source

pub fn scan_measurement( &self, measurement: &str, min_ts: i64, max_ts: i64, ) -> Vec<Point>

Scan points for a specific measurement across active and frozen memtables.

Deduplicated by (series, timestamp), newest write wins — the active memtable first, then the frozen queue newest to oldest.

The result is a set, in no particular order. ShardRouter sorts by timestamp across shards, and every caller reaches this through it.

Source

pub fn all_series_canonical_forms(&self) -> Vec<Arc<str>>

Every series held by this shard’s active and frozen memtables.

Source

pub fn visit_tags(&self, f: &mut impl FnMut(&str, &str))

Hand every tag pair this shard holds in memory to f.

Source

pub fn total_memory(&self) -> usize

Returns the total estimated memory across active and all frozen memtables.

Source

pub fn total_interner_memory(&self) -> usize

Heap bytes held by the interners of the active and frozen memtables.

Source

pub fn min_unflushed_wal_seq(&self) -> Option<u64>

The smallest WAL sequence number held by a memtable that is not yet in a segment — active or frozen.

This is what the WAL floor is capped by. It used to consult the active memtable only, so a frozen memtable still being written — or left behind by a failed flush — was invisible, and a concurrent flush of another shard raised the floor past its records.

Source

pub fn write_stall_delay(&self) -> Duration

Compute graduated write stall delay based on memory pressure.

Returns Duration::ZERO when memory usage is below the soft limit. Between the soft limit and the hard limit, returns a linearly increasing delay up to max_stall_delay. At or above the hard limit, callers should use check_capacity which returns an error.

This implements RocksDB-style graduated backpressure: as the memtable fills up, writes slow down proportionally, giving the flush thread time to drain without triggering hard rejections.

Trait Implementations§

Source§

impl Debug for FlushController

Source§

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

Formats the value using the given formatter. 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<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> 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, 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