dscale 0.5.2

A fast & deterministic simulation framework for benchmarking and testing distributed systems
Documentation
mod bandwidth;
mod latency;

use std::sync::Arc;

pub use bandwidth::BandwidthConfig;

use crate::GLOBAL_POOL;
use crate::Jiffies;
use crate::Pid;
use crate::events::Event;
use crate::events::NetworkFsm;
use crate::events::PidHandlerEvent;
use crate::events::TimedEvent;
use crate::network::bandwidth::Bandwidth;
use crate::network::latency::Latency;
use crate::random::Randomizer;
use crate::random::Seed;
use crate::topology::Topology;

pub(crate) enum NetworkDecision {
    Keep(TimedEvent),
    Ready(PidHandlerEvent),
}

pub(crate) struct Network {
    bandwidth: Bandwidth,
    latency: Latency,
}

impl Network {
    pub(crate) fn new(
        seed: Seed,
        bandwidth_type: BandwidthConfig,
        topology: Arc<Topology>,
    ) -> Self {
        Self {
            latency: Latency::new(Randomizer::new(seed), topology.clone()),
            bandwidth: Bandwidth::new(bandwidth_type, topology.list_pool(GLOBAL_POOL).len()),
        }
    }
}

impl Network {
    pub(crate) fn compute_latency(&mut self, source: Pid, target: Pid) -> Jiffies {
        self.latency.random_latency(source, target)
    }
}

impl Network {
    pub(crate) fn decide(
        &mut self,
        invocation_time: Jiffies,
        mut event: PidHandlerEvent,
    ) -> NetworkDecision {
        match &mut event {
            PidHandlerEvent::Network {
                target,
                message,
                fsm,
                ..
            } => match fsm {
                NetworkFsm::KeepLatency => {
                    match self.bandwidth.try_pass(message, *target, invocation_time) {
                        None => NetworkDecision::Ready(event),
                        Some(additional_latency) => {
                            *fsm = NetworkFsm::KeepBandwidth;
                            NetworkDecision::Keep(TimedEvent {
                                invocation_time: invocation_time + additional_latency,
                                event: Event::Handler(event),
                            })
                        }
                    }
                }
                NetworkFsm::KeepBandwidth => {
                    self.bandwidth.add_passed(message.virtual_size(), *target);
                    NetworkDecision::Ready(event)
                }
            },
            _ => unreachable!(),
        }
    }
}