mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-06 00:34:23 +01:00
modify clock to use simulated time instead
This commit is contained in:
@@ -4,6 +4,17 @@ pub struct Instant {
|
||||
pub micros: u32,
|
||||
}
|
||||
|
||||
impl<T: chrono::TimeZone> From<chrono::DateTime<T>> for Instant {
|
||||
fn from(value: chrono::DateTime<T>) -> Self {
|
||||
Instant {
|
||||
secs: value.timestamp(),
|
||||
micros: value.timestamp_subsec_micros(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub trait Clock {
|
||||
fn now(&self) -> Instant;
|
||||
}
|
||||
|
||||
34
simulator/runner/clock.rs
Normal file
34
simulator/runner/clock.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use rand::Rng;
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SimulatorClock {
|
||||
curr_time: RefCell<DateTime<Utc>>,
|
||||
rng: RefCell<ChaCha8Rng>,
|
||||
}
|
||||
|
||||
impl SimulatorClock {
|
||||
const MIN_TICK: u64 = 1;
|
||||
const MAX_TICK: u64 = 50;
|
||||
|
||||
pub fn new(rng: ChaCha8Rng) -> Self {
|
||||
Self {
|
||||
curr_time: RefCell::new(Utc::now()),
|
||||
rng: RefCell::new(rng),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn now(&self) -> DateTime<Utc> {
|
||||
let mut time = self.curr_time.borrow_mut();
|
||||
let nanos = self
|
||||
.rng
|
||||
.borrow_mut()
|
||||
.gen_range(Self::MIN_TICK..Self::MAX_TICK);
|
||||
let nanos = std::time::Duration::from_micros(nanos);
|
||||
*time = *time + nanos;
|
||||
*time
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,13 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use rand::Rng as _;
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
use tracing::{instrument, Level};
|
||||
use turso_core::{File, Result};
|
||||
|
||||
use crate::model::FAULT_ERROR_MSG;
|
||||
use crate::{model::FAULT_ERROR_MSG, runner::clock::SimulatorClock};
|
||||
pub(crate) struct SimulatorFile {
|
||||
pub(crate) inner: Arc<dyn File>,
|
||||
pub(crate) fault: Cell<bool>,
|
||||
@@ -40,12 +41,13 @@ pub(crate) struct SimulatorFile {
|
||||
|
||||
pub sync_completion: RefCell<Option<Arc<turso_core::Completion>>>,
|
||||
pub queued_io: RefCell<Vec<DelayedIo>>,
|
||||
pub clock: Arc<SimulatorClock>,
|
||||
}
|
||||
|
||||
type IoOperation = Box<dyn FnOnce(&SimulatorFile) -> Result<Arc<turso_core::Completion>>>;
|
||||
|
||||
pub struct DelayedIo {
|
||||
pub time: std::time::Instant,
|
||||
pub time: turso_core::Instant,
|
||||
pub op: IoOperation,
|
||||
}
|
||||
|
||||
@@ -95,17 +97,19 @@ impl SimulatorFile {
|
||||
}
|
||||
|
||||
#[instrument(skip_all, level = Level::TRACE)]
|
||||
fn generate_latency_duration(&self) -> Option<std::time::Instant> {
|
||||
fn generate_latency_duration(&self) -> Option<turso_core::Instant> {
|
||||
let mut rng = self.rng.borrow_mut();
|
||||
// Chance to introduce some latency
|
||||
rng.gen_bool(self.latency_probability as f64 / 100.0)
|
||||
.then(|| {
|
||||
std::time::Instant::now() + std::time::Duration::from_millis(rng.gen_range(5..15))
|
||||
let now: DateTime<Utc> = self.clock.now().into();
|
||||
let sum = now + std::time::Duration::from_millis(rng.gen_range(5..20));
|
||||
sum.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip_all, level = Level::DEBUG)]
|
||||
pub fn run_queued_io(&self, now: std::time::Instant) -> Result<()> {
|
||||
pub fn run_queued_io(&self, now: turso_core::Instant) -> Result<()> {
|
||||
let mut queued_io = self.queued_io.borrow_mut();
|
||||
// TODO: as we are not in version 1.87 we cannot use `extract_if`
|
||||
// so we have to do something different to achieve the same thing
|
||||
|
||||
@@ -7,7 +7,10 @@ use rand::{RngCore, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
use turso_core::{Clock, Instant, MemoryIO, OpenFlags, PlatformIO, Result, IO};
|
||||
|
||||
use crate::{model::FAULT_ERROR_MSG, runner::file::SimulatorFile};
|
||||
use crate::{
|
||||
model::FAULT_ERROR_MSG,
|
||||
runner::{clock::SimulatorClock, file::SimulatorFile},
|
||||
};
|
||||
|
||||
pub(crate) struct SimulatorIO {
|
||||
pub(crate) inner: Box<dyn IO>,
|
||||
@@ -18,6 +21,7 @@ pub(crate) struct SimulatorIO {
|
||||
pub(crate) page_size: usize,
|
||||
seed: u64,
|
||||
latency_probability: usize,
|
||||
clock: Arc<SimulatorClock>,
|
||||
}
|
||||
|
||||
unsafe impl Send for SimulatorIO {}
|
||||
@@ -30,6 +34,8 @@ impl SimulatorIO {
|
||||
let files = RefCell::new(Vec::new());
|
||||
let rng = RefCell::new(ChaCha8Rng::seed_from_u64(seed));
|
||||
let nr_run_once_faults = Cell::new(0);
|
||||
let clock = SimulatorClock::new(ChaCha8Rng::seed_from_u64(seed));
|
||||
|
||||
Ok(Self {
|
||||
inner,
|
||||
fault,
|
||||
@@ -39,6 +45,7 @@ impl SimulatorIO {
|
||||
page_size,
|
||||
seed,
|
||||
latency_probability,
|
||||
clock: Arc::new(clock),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -59,11 +66,7 @@ impl SimulatorIO {
|
||||
|
||||
impl Clock for SimulatorIO {
|
||||
fn now(&self) -> Instant {
|
||||
let now = chrono::Local::now();
|
||||
Instant {
|
||||
secs: now.timestamp(),
|
||||
micros: now.timestamp_subsec_micros(),
|
||||
}
|
||||
self.clock.now().into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +92,7 @@ impl IO for SimulatorIO {
|
||||
latency_probability: self.latency_probability,
|
||||
sync_completion: RefCell::new(None),
|
||||
queued_io: RefCell::new(Vec::new()),
|
||||
clock: self.clock.clone(),
|
||||
});
|
||||
self.files.borrow_mut().push(file.clone());
|
||||
Ok(file)
|
||||
@@ -109,7 +113,7 @@ impl IO for SimulatorIO {
|
||||
FAULT_ERROR_MSG.into(),
|
||||
));
|
||||
}
|
||||
let now = std::time::Instant::now();
|
||||
let now = self.now();
|
||||
for file in self.files.borrow().iter() {
|
||||
file.run_queued_io(now)?;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod bugbase;
|
||||
pub mod cli;
|
||||
pub mod clock;
|
||||
pub mod differential;
|
||||
pub mod doublecheck;
|
||||
pub mod env;
|
||||
|
||||
Reference in New Issue
Block a user