memoryd: memory writes decided into the Honcho ledger as they are journalled
Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
use bxcore::{LogRecord, SessionId, SessionStateReply, Timestamp};
|
||||
|
||||
@@ -32,9 +33,11 @@ enum Walk {
|
||||
Stop,
|
||||
}
|
||||
|
||||
/// The turns reported and not yet decided, and the ledger their decisions go to.
|
||||
/// The turns reported and not yet decided, and the ledger their decisions go to. The ledger has a
|
||||
/// lock of its own, held only to read or append: a walk holds `TurnSync`'s lock while it asks
|
||||
/// `brokerd`, and a memory write, decided under the index lock, takes only the ledger's.
|
||||
pub struct TurnSync {
|
||||
ledger: Ledger,
|
||||
ledger: Arc<Mutex<Ledger>>,
|
||||
agent: String,
|
||||
sessions: PathBuf,
|
||||
/// Each session with undecided turns, by its id, and the highest turn `loopd` reported for
|
||||
@@ -99,7 +102,7 @@ impl TurnSync {
|
||||
/// `loopd`'s session logs.
|
||||
pub fn new(ledger: Ledger, agent: &str, sessions: &Path) -> TurnSync {
|
||||
TurnSync {
|
||||
ledger,
|
||||
ledger: Arc::new(Mutex::new(ledger)),
|
||||
agent: agent.to_string(),
|
||||
sessions: sessions.to_path_buf(),
|
||||
reported: BTreeMap::new(),
|
||||
@@ -108,8 +111,14 @@ impl TurnSync {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ledger(&self) -> &Ledger {
|
||||
&self.ledger
|
||||
/// The ledger, locked. Never hold it while taking another lock.
|
||||
pub fn ledger(&self) -> MutexGuard<'_, Ledger> {
|
||||
self.ledger.lock().unwrap_or_else(|p| p.into_inner())
|
||||
}
|
||||
|
||||
/// The ledger's lock itself, for the worker and for memory writes.
|
||||
pub fn shared_ledger(&self) -> Arc<Mutex<Ledger>> {
|
||||
Arc::clone(&self.ledger)
|
||||
}
|
||||
|
||||
/// The directory of `loopd`'s session logs.
|
||||
@@ -128,7 +137,7 @@ impl TurnSync {
|
||||
/// to its next report: sessions from before Honcho was turned on are never walked.
|
||||
pub fn resume(&mut self) {
|
||||
let mut sessions: Vec<SessionId> = Vec::new();
|
||||
for (item, _) in self.ledger.decisions() {
|
||||
for (item, _) in self.ledger().decisions() {
|
||||
if let Item::Turn { session, .. } = item
|
||||
&& !sessions.contains(session)
|
||||
{
|
||||
@@ -147,7 +156,7 @@ impl TurnSync {
|
||||
|
||||
/// Append `record` to the ledger (the worker's `Sent` and `Failed`).
|
||||
pub fn append(&mut self, record: Record) -> Result<(), ledger::LedgerError> {
|
||||
self.ledger.append(record)
|
||||
self.ledger().append(record)
|
||||
}
|
||||
|
||||
/// `loopd` reported that turn `turn` of `session` ended. Remember it, then walk.
|
||||
@@ -200,7 +209,7 @@ impl TurnSync {
|
||||
turn,
|
||||
};
|
||||
let undecided: Vec<u64> = (1..=limit)
|
||||
.filter(|turn| !self.ledger.is_decided(&item(*turn)))
|
||||
.filter(|turn| !self.ledger().is_decided(&item(*turn)))
|
||||
.collect();
|
||||
if undecided.is_empty() {
|
||||
return if held { Walk::Waiting } else { Walk::Done };
|
||||
@@ -217,7 +226,8 @@ impl TurnSync {
|
||||
item: item(turn),
|
||||
action,
|
||||
};
|
||||
if let Err(e) = self.ledger.append(record) {
|
||||
let appended = self.ledger().append(record);
|
||||
if let Err(e) = appended {
|
||||
log(&format!("memoryd: {e}; {}", ledger::RUNBOOK));
|
||||
return Walk::Stop;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user