Skip to main content

Engine

Trait Engine 

Source
pub trait Engine {
    type Work;

    // Required methods
    fn key_hash(&self, work: &Self::Work) -> Option<u64>;
    fn prefetch(&self, work: &Self::Work, hash: u64);
    fn run(&mut self, work: Self::Work, hash: Option<u64>) -> Flow;
    fn flush(&mut self);

    // Provided methods
    fn submit_io(&mut self) -> Result<()> { ... }
    fn drain_io(&mut self) -> Result<()> { ... }
    fn maintain(&mut self, budget: &mut Budget) { ... }
}
Expand description

The shard behind the loop.

One implementation per kind of shard, which for now means one: the string plane. The loop makes these calls in the order 04 section 2 lists and never in another order, so an implementation can rely on prefetch for a piece of work coming before run for it, on flush coming after every run in the batch, and on maintain coming last.

Required Associated Types§

Source

type Work

One command, however the layer above chose to represent it.

Required Methods§

Source

fn key_hash(&self, work: &Self::Work) -> Option<u64>

The hash of the key this work touches, or None when it touches none.

Called once per command, on the first walk. Whatever comes back is handed to Engine::run on the second walk, so a command’s key is hashed once per batch rather than once per walk.

Source

fn prefetch(&self, work: &Self::Work, hash: u64)

Ask the cache for whatever run is about to load for this work.

Usually one call to the index’s own prefetch. It has to be cheap and it has to read nothing, because it runs for all 64 commands before the first one executes.

The work comes with the hash because a hash on its own does not say which structure to warm. Two commands in one batch can carry the same key into different databases, and later into different types, so the engine needs the command to know which index the bucket is in.

Source

fn run(&mut self, work: Self::Work, hash: Option<u64>) -> Flow

Execute one command.

hash is what key_hash returned for this work, so a lookup takes the hashed form rather than hashing the key a second time.

Source

fn flush(&mut self)

Write out the replies the batch produced.

One writev per connection touched, never one per reply. aki’s HGETALL profile spent 69.7 percent of its time in write syscalls, and this is the call that exists so that does not happen again.

Provided Methods§

Source

fn submit_io(&mut self) -> Result<()>

Hand the submission queue to the kernel.

The first stage. One syscall when there is something queued, and none at all under SQPoll. Does nothing by default, which is right for a shard with no ring under it.

§Errors

Whatever the ring says. The turn stops there and reports it.

Source

fn drain_io(&mut self) -> Result<()>

Pick up completions that have arrived.

Where a parked command finds out its write landed. Does nothing by default.

§Errors

Whatever the ring says, including a failure an earlier submission left behind.

Source

fn maintain(&mut self, budget: &mut Budget)

Spend up to budget on background work.

Expiry sampling, eviction, the compaction handshake, partition rebalance and tier demotion, in that order of priority, per 04 section 6. Does nothing by default.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§