use super::dirty::DirtyStore;
use super::store::{AuthorityError, Store};
use crate::engine::VertexId;
use rustc_hash::FxHashMap;
pub type ObservedRect = (u16, u32, u32, u32, u32);
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum HostState {
#[default]
Unbuilt,
Ready,
Failed(AuthorityError),
}
#[derive(Clone, Debug, Default)]
pub struct DiffCounters {
pub propagations: u64,
pub checked_seeds: u64,
pub closure_mismatches: u64,
pub closure_conservative: u64,
pub direct_mismatches: u64,
pub skipped: u64,
}
#[derive(Debug, Default)]
pub struct AuthorityHost {
pub(crate) store: Store,
pub(crate) state: HostState,
pub(crate) symbol_rev: u64,
pub(crate) dirty: DirtyStore,
pub(crate) builds: u64,
pub(crate) revision: u64,
pub(crate) incremental_mutations: u64,
pub(crate) diff: DiffCounters,
pub(crate) symbols: SymbolSlots,
pub(crate) structural_pending: bool,
pub(crate) replaying: bool,
pub(crate) structural_rebuilds: u64,
pub(crate) texts_unrendered: std::sync::Mutex<rustc_hash::FxHashSet<VertexId>>,
pub(crate) observed: FxHashMap<VertexId, Vec<ObservedRect>>,
pub(crate) rev_dyn: u64,
pub(crate) symbol_changes: SymbolChanges,
pub(crate) symbol_incremental: u64,
pub(crate) symbol_sync_work: u64,
pub(crate) symbol_rev_target: Option<u64>,
pub(crate) unbound: FxHashMap<Box<str>, rustc_hash::FxHashSet<VertexId>>,
pub(crate) pending_dirty: Vec<VertexId>,
pub(crate) pending_dirty_rects: Vec<(u16, crate::engine::authority::geom::Rect)>,
pub(crate) pending_direct_dirty: Vec<VertexId>,
pub(crate) pending_direct_dirty_runs: Vec<(crate::SheetId, u32, u32, u32)>,
}
#[derive(Debug, Default)]
pub(crate) struct SymbolChanges {
pub(crate) names: Vec<VertexId>,
pub(crate) other: bool,
}
#[derive(Debug, Default)]
pub struct SymbolSlots {
slot_of: FxHashMap<VertexId, u32>,
vertex_of: Vec<Option<VertexId>>,
free: std::collections::BinaryHeap<std::cmp::Reverse<u32>>,
}
impl SymbolSlots {
pub fn slot(&self, vertex: VertexId) -> Option<u32> {
self.slot_of.get(&vertex).copied()
}
pub fn vertex(&self, slot: u32) -> Option<VertexId> {
self.vertex_of.get(slot as usize).copied().flatten()
}
pub fn len(&self) -> usize {
self.slot_of.len()
}
pub fn is_empty(&self) -> bool {
self.slot_of.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (u32, VertexId)> + '_ {
self.vertex_of
.iter()
.enumerate()
.filter_map(|(s, v)| v.map(|v| (s as u32, v)))
}
pub fn sync(&mut self, live: &[VertexId]) -> Vec<u32> {
let mut retired = Vec::new();
for (slot, entry) in self.vertex_of.iter_mut().enumerate() {
if let Some(v) = *entry
&& live.binary_search(&v).is_err()
{
*entry = None;
self.slot_of.remove(&v);
retired.push(slot as u32);
}
}
self.free
.extend(retired.iter().map(|&s| std::cmp::Reverse(s)));
for &v in live {
if !self.slot_of.contains_key(&v) {
self.insert(v);
}
}
retired
}
pub fn insert(&mut self, vertex: VertexId) -> u32 {
if let Some(&slot) = self.slot_of.get(&vertex) {
return slot;
}
let slot = match self.free.pop() {
Some(std::cmp::Reverse(slot)) => slot,
None => {
self.vertex_of.push(None);
(self.vertex_of.len() - 1) as u32
}
};
self.vertex_of[slot as usize] = Some(vertex);
self.slot_of.insert(vertex, slot);
slot
}
pub fn remove(&mut self, vertex: VertexId) -> Option<u32> {
let slot = self.slot_of.remove(&vertex)?;
self.vertex_of[slot as usize] = None;
self.free.push(std::cmp::Reverse(slot));
Some(slot)
}
pub fn heap_bytes(&self) -> usize {
super::dir::hash_table_bytes::<(VertexId, u32)>(self.slot_of.capacity())
+ self.vertex_of.capacity() * size_of::<Option<VertexId>>()
+ self.free.capacity() * size_of::<u32>()
}
}
impl AuthorityHost {
pub fn state(&self) -> &HostState {
&self.state
}
pub fn store(&self) -> &Store {
&self.store
}
pub fn dirty(&self) -> &DirtyStore {
&self.dirty
}
pub fn builds(&self) -> u64 {
self.builds
}
pub fn revision(&self) -> u64 {
self.revision
}
pub fn rev_dyn(&self) -> u64 {
self.rev_dyn
}
pub fn has_observed(&self) -> bool {
!self.observed.is_empty()
}
pub fn observed(&self, reader: VertexId) -> Option<&[ObservedRect]> {
self.observed.get(&reader).map(Vec::as_slice)
}
pub(crate) fn set_observed(&mut self, reader: VertexId, mut reads: Vec<ObservedRect>) {
reads.sort_unstable();
reads.dedup();
if self.observed.get(&reader) != Some(&reads) {
self.observed.insert(reader, reads);
self.rev_dyn += 1;
}
}
pub(crate) fn forget_observed(&mut self, reader: VertexId) {
if self.observed.remove(&reader).is_some() {
self.rev_dyn += 1;
}
}
pub(crate) fn clear_observed(&mut self) {
if !self.observed.is_empty() {
self.observed.clear();
self.rev_dyn += 1;
}
}
pub fn incremental_mutations(&self) -> u64 {
self.incremental_mutations
}
pub fn diff_counters(&self) -> &DiffCounters {
&self.diff
}
pub fn symbols(&self) -> &SymbolSlots {
&self.symbols
}
pub fn symbol_incremental(&self) -> u64 {
self.symbol_incremental
}
pub fn symbol_sync_work(&self) -> u64 {
self.symbol_sync_work
}
pub(crate) fn note_unbound(&mut self, vertex: VertexId, keys: Vec<Box<str>>) {
for key in keys {
self.unbound.entry(key).or_default().insert(vertex);
}
}
pub fn structural_rebuilds(&self) -> u64 {
self.structural_rebuilds
}
}