use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
use std::sync::Mutex;
use std::time::{Duration, Instant};
use crate::command::GitService;
use gunnar_lfs::Operation;
pub const TARGET: Duration = Duration::from_millis(5);
pub const INTERVAL: Duration = Duration::from_millis(100);
pub const MIN_LIMIT: usize = 10;
pub const MAX_LIMIT: usize = 100;
pub const BUDGET_FLOOR_DENOMINATOR: usize = 2;
pub const DEFAULT_MEMORY_BUDGET_BYTES: u64 = 8 * 1024 * 1024 * 1024;
const MIB: u64 = 1024 * 1024;
pub const DEFAULT_ADMISSION_WAIT: Duration = Duration::from_secs(2);
pub const DEFAULT_KEYED_ADMISSION_WAIT: Duration = Duration::from_secs(30);
pub const WIRE_MEMORY_NUMERATOR: u64 = 1;
pub const WIRE_MEMORY_DENOMINATOR: u64 = 4;
pub const WIRE_RESERVE_STEP: u64 = 16 * MIB;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Lane {
Cheap,
Read,
Write,
}
impl Lane {
pub const ALL: [Lane; 3] = [Lane::Cheap, Lane::Read, Lane::Write];
pub const COUNT: usize = Lane::ALL.len();
pub const fn index(self) -> usize {
match self {
Lane::Cheap => 0,
Lane::Read => 1,
Lane::Write => 2,
}
}
pub const fn name(self) -> &'static str {
match self {
Lane::Cheap => "cheap",
Lane::Read => "read",
Lane::Write => "write",
}
}
pub const fn floor_share(self) -> (usize, usize) {
match self {
Lane::Cheap => (1, 8),
Lane::Read => (1, 4),
Lane::Write => (0, 1),
}
}
pub const fn floor_min(self) -> usize {
match self {
Lane::Cheap | Lane::Read => 2,
Lane::Write => 0,
}
}
pub fn floor(self, limit: usize) -> usize {
let (n, d) = self.floor_share();
(limit * n / d).max(self.floor_min()).min(limit)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum OpClass {
LsRemote,
Fetch,
Clone,
Push,
Gc,
}
impl OpClass {
pub const ALL: [OpClass; 5] = [
OpClass::LsRemote,
OpClass::Fetch,
OpClass::Clone,
OpClass::Push,
OpClass::Gc,
];
pub const COUNT: usize = OpClass::ALL.len();
pub const fn index(self) -> usize {
match self {
OpClass::LsRemote => 0,
OpClass::Fetch => 1,
OpClass::Clone => 2,
OpClass::Push => 3,
OpClass::Gc => 4,
}
}
pub const fn name(self) -> &'static str {
match self {
OpClass::LsRemote => "ls-remote",
OpClass::Fetch => "fetch",
OpClass::Clone => "clone",
OpClass::Push => "push",
OpClass::Gc => "gc",
}
}
pub const fn target(self) -> Duration {
match self {
OpClass::LsRemote => TARGET,
OpClass::Fetch => Duration::from_millis(45),
OpClass::Clone => Duration::from_millis(186),
OpClass::Push => Duration::from_millis(170),
OpClass::Gc => Duration::from_millis(186),
}
}
pub const fn admission_bytes(self) -> u64 {
match self {
OpClass::LsRemote => 4 * MIB,
OpClass::Fetch => 16 * MIB,
OpClass::Clone => 16 * MIB,
OpClass::Push => 32 * MIB,
OpClass::Gc => 32 * MIB,
}
}
pub const fn lane(self) -> Lane {
match self {
OpClass::LsRemote => Lane::Cheap,
OpClass::Fetch | OpClass::Clone => Lane::Read,
OpClass::Push | OpClass::Gc => Lane::Write,
}
}
pub fn for_ssh_service(service: GitService) -> OpClass {
match service {
GitService::UploadPack => OpClass::Fetch,
GitService::ReceivePack => OpClass::Push,
GitService::LfsTransfer(Operation::Upload) => OpClass::Push,
GitService::LfsTransfer(Operation::Download) => OpClass::Fetch,
}
}
}
impl std::fmt::Display for Lane {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.name())
}
}
impl std::fmt::Display for OpClass {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LimitBand {
pub min: usize,
pub max: usize,
}
impl LimitBand {
pub const DEFAULT: LimitBand = LimitBand {
min: MIN_LIMIT,
max: MAX_LIMIT,
};
pub fn for_ceiling(ceiling: usize) -> LimitBand {
LimitBand {
min: MIN_LIMIT.min(ceiling),
max: ceiling,
}
}
pub fn for_budget(budget: usize) -> LimitBand {
LimitBand {
min: (budget / BUDGET_FLOOR_DENOMINATOR).clamp(MIN_LIMIT.min(budget), budget),
max: budget,
}
}
fn clamp(self, limit: usize) -> usize {
limit.clamp(self.min, self.max)
}
}
#[derive(Debug, Clone, Copy)]
struct ClassWindow {
opened: Option<Instant>,
min: Option<Duration>,
}
impl ClassWindow {
const EMPTY: ClassWindow = ClassWindow {
opened: None,
min: None,
};
}
#[derive(Debug)]
pub struct Codel {
band: LimitBand,
limit: AtomicUsize,
windows: Mutex<[ClassWindow; OpClass::COUNT]>,
shrinks: AtomicU64,
grows: AtomicU64,
}
impl Codel {
pub fn new(band: LimitBand) -> Codel {
Codel {
band,
limit: AtomicUsize::new(band.max),
windows: Mutex::new([ClassWindow::EMPTY; OpClass::COUNT]),
shrinks: AtomicU64::new(0),
grows: AtomicU64::new(0),
}
}
pub fn band(&self) -> LimitBand {
self.band
}
pub fn limit(&self) -> usize {
self.limit.load(Ordering::Relaxed)
}
pub fn shrinks(&self) -> u64 {
self.shrinks.load(Ordering::Relaxed)
}
pub fn grows(&self) -> u64 {
self.grows.load(Ordering::Relaxed)
}
pub fn record(&self, class: OpClass, sojourn: Duration) {
self.record_at(class, sojourn, Instant::now());
}
pub fn record_at(&self, class: OpClass, sojourn: Duration, now: Instant) {
let mut windows = self.windows.lock().unwrap_or_else(|e| e.into_inner());
let window = &mut windows[class.index()];
let opened = *window.opened.get_or_insert(now);
window.min = Some(match window.min {
Some(previous) => previous.min(sojourn),
None => sojourn,
});
if now.saturating_duration_since(opened) < INTERVAL {
return;
}
let standing = window.min.is_some_and(|min| min > class.target());
*window = ClassWindow {
opened: Some(now),
min: None,
};
drop(windows);
if standing {
self.shrink();
} else {
self.grow();
}
}
fn shrink(&self) {
let band = self.band;
let _ = self
.limit
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |limit| {
Some(band.clamp(limit.saturating_sub((limit / 8).max(1))))
});
self.shrinks.fetch_add(1, Ordering::Relaxed);
}
fn grow(&self) {
let band = self.band;
let _ = self
.limit
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |limit| {
Some(band.clamp(limit.saturating_add(1)))
});
self.grows.fetch_add(1, Ordering::Relaxed);
}
}
#[derive(Debug)]
pub struct MemoryLedger {
budget: u64,
reserved: AtomicU64,
}
impl MemoryLedger {
pub fn new(budget: u64) -> MemoryLedger {
MemoryLedger {
budget,
reserved: AtomicU64::new(0),
}
}
pub fn budget(&self) -> u64 {
self.budget
}
pub fn reserved(&self) -> u64 {
self.reserved.load(Ordering::Relaxed)
}
pub fn try_reserve(&self, bytes: u64) -> bool {
self.reserved
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |reserved| {
let wanted = reserved.saturating_add(bytes);
(wanted <= self.budget).then_some(wanted)
})
.is_ok()
}
pub fn charge(&self, bytes: u64) -> bool {
let before = self.reserved.fetch_add(bytes, Ordering::Relaxed);
before.saturating_add(bytes) <= self.budget
}
pub fn release(&self, bytes: u64) {
let _ = self
.reserved
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |reserved| {
Some(reserved.saturating_sub(bytes))
});
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Shed {
Concurrency {
limit: usize,
in_flight: usize,
},
LaneFull {
lane: Lane,
ceiling: usize,
limit: usize,
},
Reserved {
occupied: usize,
limit: usize,
reserve: usize,
},
Memory {
class: OpClass,
wanted: u64,
reserved: u64,
budget: u64,
},
}
#[derive(Debug, Clone, Copy)]
pub struct Claim {
pub class: OpClass,
pub bytes: u64,
pub enqueued: Instant,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Growth {
Fitted {
held: u64,
},
Overdrawn {
held: u64,
reserved: u64,
budget: u64,
},
}
#[derive(Debug)]
pub struct Governor {
codel: Codel,
memory: MemoryLedger,
occupied: AtomicUsize,
per_lane: [AtomicUsize; Lane::COUNT],
waiting: [AtomicUsize; Lane::COUNT],
shed_concurrency: AtomicU64,
shed_lane: AtomicU64,
shed_memory: AtomicU64,
overdrawn: AtomicU64,
}
impl Governor {
pub fn new(band: LimitBand, budget: u64) -> Governor {
Governor {
codel: Codel::new(band),
memory: MemoryLedger::new(budget),
occupied: AtomicUsize::new(0),
per_lane: [const { AtomicUsize::new(0) }; Lane::COUNT],
waiting: [const { AtomicUsize::new(0) }; Lane::COUNT],
shed_concurrency: AtomicU64::new(0),
shed_lane: AtomicU64::new(0),
shed_memory: AtomicU64::new(0),
overdrawn: AtomicU64::new(0),
}
}
pub fn codel(&self) -> &Codel {
&self.codel
}
pub fn memory(&self) -> &MemoryLedger {
&self.memory
}
pub fn limit(&self) -> usize {
self.codel.limit()
}
pub fn occupied(&self) -> usize {
self.occupied.load(Ordering::Relaxed)
}
pub fn occupied_in(&self, lane: Lane) -> usize {
self.per_lane[lane.index()].load(Ordering::Relaxed)
}
pub fn lane_ceiling(&self, lane: Lane, limit: usize) -> usize {
let reserved_elsewhere: usize = Lane::ALL
.iter()
.filter(|other| **other != lane)
.map(|other| other.floor(limit).min(self.waiting_in(*other)))
.sum();
limit.saturating_sub(reserved_elsewhere).max(1)
}
pub fn waiting_in(&self, lane: Lane) -> usize {
self.waiting[lane.index()].load(Ordering::Relaxed)
}
pub fn entered_wait(&self, lane: Lane) {
self.waiting[lane.index()].fetch_add(1, Ordering::Relaxed);
}
pub fn left_wait(&self, lane: Lane) {
let _ = self.waiting[lane.index()].fetch_update(
Ordering::Relaxed,
Ordering::Relaxed,
|waiting| Some(waiting.saturating_sub(1)),
);
}
pub fn shed_counts(&self) -> (u64, u64, u64) {
(
self.shed_concurrency.load(Ordering::Relaxed),
self.shed_lane.load(Ordering::Relaxed),
self.shed_memory.load(Ordering::Relaxed),
)
}
pub fn overdrawn(&self) -> u64 {
self.overdrawn.load(Ordering::Relaxed)
}
pub fn try_claim(&self, class: OpClass) -> Result<Claim, Shed> {
self.claim(class, 0, true)
}
pub fn claim_for(&self, class: OpClass, count: bool) -> Result<Claim, Shed> {
self.claim(class, 0, count)
}
pub fn claim_reserving(
&self,
class: OpClass,
reserve: usize,
count: bool,
) -> Result<Claim, Shed> {
self.claim(class, reserve, count)
}
pub fn attempt(&self, class: OpClass) -> Result<Claim, Shed> {
self.claim(class, 0, false)
}
fn claim(&self, class: OpClass, reserve: usize, count: bool) -> Result<Claim, Shed> {
let limit = self.codel.limit();
let available = limit.saturating_sub(reserve);
let taken = self
.occupied
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |occupied| {
(occupied < available).then_some(occupied + 1)
});
if let Err(occupied) = taken {
if reserve > 0 {
return Err(Shed::Reserved {
occupied,
limit,
reserve,
});
}
if count {
self.shed_concurrency.fetch_add(1, Ordering::Relaxed);
}
return Err(Shed::Concurrency {
limit,
in_flight: occupied,
});
}
let lane = class.lane();
let ceiling = self.lane_ceiling(lane, limit);
let lane_taken = self.per_lane[lane.index()].fetch_update(
Ordering::Relaxed,
Ordering::Relaxed,
|held| (held < ceiling).then_some(held + 1),
);
if lane_taken.is_err() {
self.occupied.fetch_sub(1, Ordering::Relaxed);
if count {
self.shed_lane.fetch_add(1, Ordering::Relaxed);
}
return Err(Shed::LaneFull {
lane,
ceiling,
limit,
});
}
let bytes = class.admission_bytes();
if !self.memory.try_reserve(bytes) {
self.per_lane[lane.index()].fetch_sub(1, Ordering::Relaxed);
self.occupied.fetch_sub(1, Ordering::Relaxed);
if count {
self.shed_memory.fetch_add(1, Ordering::Relaxed);
}
return Err(Shed::Memory {
class,
wanted: bytes,
reserved: self.memory.reserved(),
budget: self.memory.budget(),
});
}
Ok(Claim {
class,
bytes,
enqueued: Instant::now(),
})
}
pub fn charge(&self, held_after: u64, extra: u64) -> Growth {
if self.memory.charge(extra) {
Growth::Fitted { held: held_after }
} else {
self.overdrawn.fetch_add(1, Ordering::Relaxed);
Growth::Overdrawn {
held: held_after,
reserved: self.memory.reserved(),
budget: self.memory.budget(),
}
}
}
pub fn release(&self, claim: &Claim, grown: u64) {
self.memory.release(claim.bytes.saturating_add(grown));
let lane = claim.class.lane();
let _ = self.per_lane[lane.index()].fetch_update(
Ordering::Relaxed,
Ordering::Relaxed,
|held| Some(held.saturating_sub(1)),
);
let _ = self
.occupied
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |occupied| {
Some(occupied.saturating_sub(1))
});
}
pub fn record_sojourn(&self, class: OpClass, sojourn: Duration) {
self.codel.record(class, sojourn);
}
}
#[derive(Debug, Default)]
pub struct ServiceMark(AtomicBool);
impl ServiceMark {
pub fn claim(&self) -> bool {
!self.0.swap(true, Ordering::Relaxed)
}
pub fn claimed(&self) -> bool {
self.0.load(Ordering::Relaxed)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn one_window(codel: &Codel, class: OpClass, sojourn: Duration, from: Instant) -> Instant {
codel.record_at(class, sojourn, from);
let closed = from + INTERVAL;
codel.record_at(class, sojourn, closed);
closed
}
#[test]
fn a_standing_queue_shrinks_the_limit() {
let codel = Codel::new(LimitBand::DEFAULT);
assert_eq!(
codel.limit(),
MAX_LIMIT,
"a governor starts at the top of its band"
);
let mut at = Instant::now();
for _ in 0..8 {
at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(50), at);
}
assert!(
codel.limit() < MAX_LIMIT,
"a queue standing at 50ms against a {:?} target did not shrink the limit: it is \
still {} after 8 closed windows (shrinks={})",
OpClass::LsRemote.target(),
codel.limit(),
codel.shrinks()
);
assert_eq!(
codel.shrinks(),
8,
"every closed standing window must shrink"
);
assert_eq!(
codel.limit(),
37,
"the decrease must be MULTIPLICATIVE (limit -= limit/8); an additive one would \
leave a different number here and would not back off fast enough to matter"
);
assert_eq!(codel.grows(), 0);
}
#[test]
fn a_draining_queue_grows_the_limit() {
let codel = Codel::new(LimitBand::DEFAULT);
let mut at = Instant::now();
for _ in 0..40 {
at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(50), at);
}
assert_eq!(
codel.limit(),
MIN_LIMIT,
"the standing phase must reach the floor"
);
for _ in 0..20 {
at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(1), at);
}
assert!(
codel.limit() > MIN_LIMIT,
"a queue draining at 1ms did not grow the limit: {} after 20 closed windows, and a \
controller that only shrinks is a ratchet",
codel.limit()
);
assert_eq!(
codel.limit(),
MIN_LIMIT + 20,
"growth must be ADDITIVE, one per closed draining window"
);
}
#[test]
fn the_limit_never_leaves_the_band() {
let codel = Codel::new(LimitBand::DEFAULT);
let mut at = Instant::now();
for _ in 0..200 {
at = one_window(&codel, OpClass::LsRemote, Duration::from_secs(1), at);
let limit = codel.limit();
assert!(
(MIN_LIMIT..=MAX_LIMIT).contains(&limit),
"the limit left the band: {limit} is outside [{MIN_LIMIT}, {MAX_LIMIT}]"
);
}
assert_eq!(codel.limit(), MIN_LIMIT);
for _ in 0..500 {
at = one_window(&codel, OpClass::LsRemote, Duration::from_micros(1), at);
let limit = codel.limit();
assert!(
(MIN_LIMIT..=MAX_LIMIT).contains(&limit),
"the limit left the band: {limit} is outside [{MIN_LIMIT}, {MAX_LIMIT}]"
);
}
assert_eq!(codel.limit(), MAX_LIMIT);
}
#[test]
fn a_slow_class_does_not_shrink_the_limit_on_a_fast_class_behalf() {
let codel = Codel::new(LimitBand::DEFAULT);
let mut at = Instant::now();
assert!(Duration::from_millis(150) > OpClass::LsRemote.target());
assert!(Duration::from_millis(150) < OpClass::Clone.target());
for _ in 0..8 {
at = one_window(&codel, OpClass::Clone, Duration::from_millis(150), at);
}
assert_eq!(
codel.limit(),
MAX_LIMIT,
"a clone waiting 150ms — well inside its own {:?} target, and a wait its client \
cannot perceive — shrank the shared limit to {}. That is the slow class poisoning \
the fast class's delay signal, which is the exact trap per-class sojourn exists to \
close (shrinks={})",
OpClass::Clone.target(),
codel.limit(),
codel.shrinks()
);
assert_eq!(codel.shrinks(), 0);
for _ in 0..8 {
at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(150), at);
}
assert!(
codel.limit() < MAX_LIMIT,
"150ms of ls-remote sojourn is thirty times its {:?} target and MUST shed load; a \
controller that shrinks for nobody is not a controller",
OpClass::LsRemote.target()
);
assert_eq!(codel.shrinks(), 8);
let before = codel.limit();
let shrinks_before = codel.shrinks();
for _ in 0..4 {
at = one_window(&codel, OpClass::Clone, Duration::from_millis(150), at);
}
assert!(
codel.limit() > before,
"the clone class must still read as DRAINING and grow the shared limit back from \
{before}, even though its absolute sojourn is thirty times the ls-remote target; \
it is {} instead",
codel.limit()
);
assert_eq!(
codel.shrinks(),
shrinks_before,
"not one of those clone windows may be read as standing"
);
}
#[test]
fn a_sample_lands_in_its_own_class_window_only() {
let codel = Codel::new(LimitBand::DEFAULT);
let at = Instant::now();
codel.record_at(OpClass::LsRemote, Duration::from_millis(50), at);
for step in 0..10 {
codel.record_at(
OpClass::Push,
Duration::from_millis(1),
at + INTERVAL * (step + 1),
);
}
assert_eq!(codel.grows(), 9, "push's own windows must close and grow");
assert_eq!(
codel.shrinks(),
0,
"a push sample closed the ls-remote window: shrinks={} grows={} after one ls-remote \
sample that could not have closed anything",
codel.shrinks(),
codel.grows()
);
}
#[test]
fn the_budget_admits_up_to_itself_and_then_denies() {
let clone = OpClass::Clone.admission_bytes();
let ledger = MemoryLedger::new(clone * 4);
let mut admitted = 0;
while ledger.try_reserve(clone) {
admitted += 1;
assert!(
admitted <= 4,
"the ledger admitted {admitted} clones against a 4-clone budget: {} reserved of {}",
ledger.reserved(),
ledger.budget()
);
}
assert_eq!(admitted, 4, "a 4-clone budget must admit exactly 4 clones");
assert_eq!(ledger.reserved(), ledger.budget());
assert!(
!ledger.try_reserve(1),
"a full ledger handed out one more byte"
);
}
#[test]
fn a_completed_operation_releases_its_reservation() {
let clone = OpClass::Clone.admission_bytes();
let ledger = MemoryLedger::new(clone * 4);
for _ in 0..4 {
assert!(ledger.try_reserve(clone));
}
assert!(!ledger.try_reserve(clone), "the budget is full");
ledger.release(clone);
assert!(
ledger.try_reserve(clone),
"the 4th clone finished and gave its {clone} bytes back, but the next clone was \
still refused: {} reserved of {}. A budget that is never released is a server that \
wedges after N operations",
ledger.reserved(),
ledger.budget()
);
}
#[test]
fn the_budget_is_not_exceeded_by_racing_admissions() {
use std::sync::{Arc, Barrier};
let slab = 1024 * 1024u64;
let slabs = 4u64;
let racers = 32;
let rounds = 20_000;
let budget = slab * slabs;
let ledger = Arc::new(MemoryLedger::new(budget));
let peak = Arc::new(AtomicU64::new(0));
let gate = Arc::new(Barrier::new(racers));
let threads: Vec<_> = (0..racers)
.map(|_| {
let ledger = Arc::clone(&ledger);
let peak = Arc::clone(&peak);
let gate = Arc::clone(&gate);
std::thread::spawn(move || {
gate.wait();
for _ in 0..rounds {
if ledger.try_reserve(slab) {
peak.fetch_max(ledger.reserved(), Ordering::Relaxed);
ledger.release(slab);
}
}
})
})
.collect();
for thread in threads {
thread.join().expect("racer");
}
assert_eq!(
ledger.reserved(),
0,
"every reservation was released, so the ledger must be empty"
);
assert!(
peak.load(Ordering::Relaxed) <= budget,
"{} racers cycling {rounds} times each drove the ledger to {} bytes against a budget \
of {budget}: it was exceeded by {} bytes, which is a budget that the number of \
concurrent admissions can walk straight past",
racers,
peak.load(Ordering::Relaxed),
peak.load(Ordering::Relaxed) - budget
);
assert_eq!(
peak.load(Ordering::Relaxed),
budget,
"the ledger never actually filled ({} of {budget}), so the boundary this test is \
about was never crossed",
peak.load(Ordering::Relaxed)
);
}
#[test]
fn a_memory_refusal_does_not_leak_a_concurrency_slot() {
let clone = OpClass::Clone.admission_bytes();
let governor = Governor::new(LimitBand::DEFAULT, clone * 4);
let held: Vec<_> = (0..4)
.map(|i| {
governor
.try_claim(OpClass::Clone)
.unwrap_or_else(|shed| panic!("clone {i} of 4 was shed: {shed:?}"))
})
.collect();
for _ in 0..40 {
let shed = governor
.try_claim(OpClass::Clone)
.expect_err("the budget is full");
assert!(matches!(shed, Shed::Memory { .. }), "{shed:?}");
}
assert_eq!(
governor.occupied(),
4,
"40 memory refusals leaked {} concurrency slots: occupied is {} with 4 operations \
actually in flight, so the gate now refuses on TIME for a reason that has nothing \
to do with time",
governor.occupied() - 4,
governor.occupied()
);
for claim in &held {
governor.release(claim, 0);
}
assert_eq!(governor.occupied(), 0);
assert_eq!(governor.memory().reserved(), 0);
}
#[test]
fn a_configured_ceiling_below_the_floor_is_still_the_ceiling() {
let band = LimitBand::for_ceiling(4);
assert_eq!(
band,
LimitBand { min: 4, max: 4 },
"a server told to serve 4 has a band of [{}, {}] and a limit of {}: the governor \
admits more than the operator configured",
band.min,
band.max,
Codel::new(band).limit()
);
assert_eq!(Codel::new(band).limit(), 4);
assert_eq!(
LimitBand::for_ceiling(256),
LimitBand { min: 10, max: 256 },
"a configured ceiling of 256 was lowered to the design's default"
);
assert_eq!(LimitBand::for_ceiling(32), LimitBand { min: 10, max: 32 });
assert_eq!(LimitBand::DEFAULT, LimitBand { min: 10, max: 100 });
}
#[test]
fn every_class_has_its_own_window_slot() {
let mut seen = [false; OpClass::COUNT];
for class in OpClass::ALL {
assert!(
!std::mem::replace(&mut seen[class.index()], true),
"{class} shares window slot {} with another class",
class.index()
);
}
assert!(seen.iter().all(|&s| s));
}
#[test]
fn the_service_mark_is_one_shot() {
let mark = ServiceMark::default();
assert!(!mark.claimed());
assert!(mark.claim(), "the first claim wins");
assert!(!mark.claim(), "the second claim must not");
assert!(mark.claimed());
}
}