Skip to main content

Wire

Struct Wire 

Source
pub struct Wire<S> { /* private fields */ }
Expand description

The engine: connections on one side, the command layer on the other.

One per thread, and it is two halves rather than one thing. The front is the connections and everything they own, which never leaves the thread that accepted them. Server is the databases, and every thread has a handle on the same one. This type is where the two meet, and every method on it that is not a one line delegation is a method that genuinely needs both: running a command, answering a client that blocked, and forgetting a client that has gone.

Implementations§

Source§

impl<S: Sink> Wire<S>

Source

pub fn new(sink: S) -> Wire<S>

An engine with an empty server.

Source

pub fn with_server(server: Server, sink: S) -> Wire<S>

An engine over a server the caller built, which is how a test gives it a clock it can move by hand.

Source

pub fn over(server: Arc<Server>, sink: S) -> Wire<S>

An engine over a server that already exists, which is how the second thread and every thread after it gets one.

Each thread builds its own front and they never see each other’s. What they share is behind the handle, and the reason the handle is counted rather than borrowed is that the threads outlive whichever call started them by design: a scope that borrows would tie the server’s lifetime to a frame that is meant to return.

Source

pub fn server(&self) -> &Server

The databases and the numbers INFO reports.

Source

pub fn shared(&self) -> Arc<Server>

Another handle on the same server, for building the next thread’s engine.

Source

pub fn server_mut(&mut self) -> &mut Server

The server, for the few settings that have to be made before it is serving.

That is the directory and the thread count, both of which are read everywhere and written once at startup, so they are settings and not state. This works while this engine holds the only handle, which is the case from the moment the server is built until the threads are started, and it is the caller’s job to do its setting up in that window.

§Panics

If a second handle already exists, because there is no honest answer to give: changing the directory under a thread that is already serving out of it is the bug this would otherwise hide.

Source

pub const fn sink(&self) -> &S

Where the replies went.

Source

pub const fn sink_mut(&mut self) -> &mut S

The same, mutably.

Source

pub fn set_limits(&mut self, limits: Limits)

Change the protocol limits, which is proto-max-bulk-len and friends.

Source

pub fn accept(&mut self) -> ConnId

Open a connection and give back its id.

Source

pub fn hangup(&mut self, conn: ConnId)

The peer went away.

Whatever is buffered for it is dropped rather than written, and the slot comes back as soon as the commands already framed out of its buffer have run, because those commands’ arguments still point into it.

Source

pub fn clients(&self) -> usize

How many connections are open.

Source

pub fn ready(&self) -> usize

Commands framed and waiting for the reactor.

Source

pub fn owed(&self) -> usize

Connections with a reply that has not gone out yet.

Non zero means a socket was full and what is left is being held for a later flush, which a driver waiting on readability needs to know: there is work here that no incoming byte will ever wake it up for.

Source

pub fn waiting(&self) -> usize

Clients of this thread’s that are blocked on a key.

The other thing a driver waiting on readability needs to know, and for the same reason owed is: there is work here that no incoming byte will wake it for. A blocked client is answered by a write another thread made or by its own deadline passing, and neither of those is a byte arriving on this thread’s poller, so a driver that reads this keeps its wait short while anybody is waiting on it.

Source

pub fn posted(&self) -> usize

Mail waiting for this thread, plus subscribers of its own that mail could arrive for.

The third thing a driver waiting on readability needs to know, and for the reason the other two are: a published message is a write another thread made and no byte arriving here will wake this thread for it. So a thread that has a subscriber keeps its wait short, and one that has none is not affected.

Source

pub fn stopping(&self) -> bool

Whether a client has asked the server to stop.

The driver reads this once a turn, next to the flag a signal sets, and leaves its loop when either is set. Asked after the batch rather than during it, so the SHUTDOWN and everything that shared its batch is finished and written out before anything closes.

Source

pub fn decoders(&self) -> usize

Decoders in the pool, which is the high water mark of one batch.

Source

pub fn buffer_bytes(&self) -> usize

What every connection’s read and reply buffers are holding.

Source

pub fn feed(&mut self, conn: ConnId, bytes: &[u8])

Take bytes off a connection and frame whatever commands they complete.

Anything left over stays in the connection’s buffer, half a command included, so the caller hands over whatever the socket gave it without looking at it.

Source

pub fn take_ready(&mut self, into: &mut Vec<Cmd>, max: usize) -> usize

Move up to max framed commands into into.

The reactor wants a batch it owns, and the front keeps the buffers, so what crosses between them is this: numbers, no borrows.

Source

pub fn tick(&mut self)

Take a clock reading for the whole batch.

04 section 5: once per turn, never per command, so every command in a batch compares against the same millisecond and two keys written together expire together.

Source

pub fn maintain(&mut self) -> Option<usize>

Do one batch’s worth of housekeeping.

That is the dead keys and then one segment of arena compaction at most, which between them are what stop a server that rewrites the same keys, or writes them under a deadline and never reads them back, from holding every version of everything it has ever been sent. It is separate from Wire::tick because the clock has to move before a batch runs and this does not: it can wait until the replies are out, and the driver decides when that is.

Per batch and not per turn of the loop. A turn can carry one command or a thousand, so a per turn call means the rate at which garbage is collected has nothing to do with the rate at which it is made, and on a saturated server the second one wins. That was measured: with this on the loop’s turn the server settled at seven segments for six segments’ worth of keys, which is where an unloaded process running the same writes settled at six.

Trait Implementations§

Source§

impl<S: Sink> Engine for Wire<S>

Source§

type Work = Cmd

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

fn key_hash(&self, cmd: &Cmd) -> Option<u64>

The hash of the key this work touches, or None when it touches none. Read more
Source§

fn prefetch(&self, cmd: &Cmd, hash: u64)

Ask the cache for whatever run is about to load for this work. Read more
Source§

fn run(&mut self, cmd: Cmd, _hash: Option<u64>) -> Flow

Execute one command. Read more
Source§

fn flush(&mut self)

Write out the replies the batch produced. Read more
Source§

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

Spend up to budget on background work. Read more
Source§

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

Hand the submission queue to the kernel. Read more
Source§

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

Pick up completions that have arrived. Read more

Auto Trait Implementations§

§

impl<S> !RefUnwindSafe for Wire<S>

§

impl<S> !UnwindSafe for Wire<S>

§

impl<S> Freeze for Wire<S>
where Front<S>: Freeze,

§

impl<S> Send for Wire<S>
where Front<S>: Send,

§

impl<S> Sync for Wire<S>
where Front<S>: Sync,

§

impl<S> Unpin for Wire<S>
where Front<S>: Unpin,

§

impl<S> UnsafeUnpin for Wire<S>
where Front<S>: UnsafeUnpin,

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, 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> MaybeSend for T

Source§

impl<T> MaybeSync for T

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.