|
|
… |
88 unchanged lines |
| 89 |
89 |
|
} |
| 90 |
90 |
|
|
| 91 |
91 |
|
#[derive(Clone, Debug, Default)] |
| 92 |
|
- |
pub struct TreeGraph { |
|
92 |
+ |
struct TreeMaps { |
| 93 |
93 |
|
kinds: Map<NodeId, NodeKind>, |
| 94 |
94 |
|
introduced: Map<NodeId, ChangeHash>, |
| 95 |
95 |
|
placements: Map<OpKey, Placement>, |
|
|
… |
9 unchanged lines |
| 105 |
105 |
|
/// apply, so the view walks what is live rather than all history. |
| 106 |
106 |
|
live_placements_of: Map<NodeId, KeySet>, |
| 107 |
107 |
|
live_modes_of: Map<NodeId, KeySet>, |
|
108 |
+ |
} |
|
109 |
+ |
|
|
110 |
+ |
#[derive(Clone, Debug, Default)] |
|
111 |
+ |
pub struct TreeGraph { |
|
112 |
+ |
/// The graph itself; see [`TreeGraph::m`]. |
|
113 |
+ |
maps: std::sync::OnceLock<TreeMaps>, |
|
114 |
+ |
/// A state index's encoding of `maps`, decoded when first needed: a |
|
115 |
+ |
/// command that only reads the view (a status) never needs them. |
|
116 |
+ |
raw: Option<std::sync::Arc<Vec<u8>>>, |
| 108 |
117 |
|
/// The view, once computed, with the path of each directory in it; |
| 109 |
118 |
|
/// kept up to date as ops apply when that is simple (see |
| 110 |
119 |
|
/// `update_view`), cleared otherwise. |
|
|
… |
76 unchanged lines |
| 187 |
196 |
|
Self::default() |
| 188 |
197 |
|
} |
| 189 |
198 |
|
|
|
199 |
+ |
/// The graph's maps, decoded from a state index on first use. |
|
200 |
+ |
fn m(&self) -> &TreeMaps { |
|
201 |
+ |
self.maps.get_or_init(|| match &self.raw { |
|
202 |
+ |
Some(raw) => { |
|
203 |
+ |
TreeMaps::decode(raw).expect("a state index is checked against its hash when read") |
|
204 |
+ |
} |
|
205 |
+ |
None => TreeMaps::default(), |
|
206 |
+ |
}) |
|
207 |
+ |
} |
|
208 |
+ |
|
|
209 |
+ |
fn m_mut(&mut self) -> &mut TreeMaps { |
|
210 |
+ |
self.m(); |
|
211 |
+ |
self.maps.get_mut().expect("decoded just now") |
|
212 |
+ |
} |
|
213 |
+ |
|
| 190 |
214 |
|
/// Apply tree op `index` of `change`; `OpRef` self references must already be resolved. |
| 191 |
215 |
|
pub fn apply(&mut self, change: ChangeHash, index: u32, op: &TreeOp) { |
| 192 |
216 |
|
let cached = self.view_cache.take(); |
|
|
… |
28 unchanged lines |
| 221 |
245 |
|
parent, |
| 222 |
246 |
|
name, |
| 223 |
247 |
|
} => { |
| 224 |
|
- |
self.kinds.insert(*node, *kind); |
| 225 |
|
- |
self.introduced.insert(*node, change); |
| 226 |
|
- |
self.placements.insert( |
|
248 |
+ |
self.m_mut().kinds.insert(*node, *kind); |
|
249 |
+ |
self.m_mut().introduced.insert(*node, change); |
|
250 |
+ |
self.m_mut().placements.insert( |
| 227 |
251 |
|
key, |
| 228 |
252 |
|
Placement { |
| 229 |
253 |
|
node: *node, |
|
|
… |
1 unchanged lines |
| 231 |
255 |
|
name: name.clone(), |
| 232 |
256 |
|
}, |
| 233 |
257 |
|
); |
| 234 |
|
- |
self.placements_of.entry(*node).or_default().insert(key); |
|
258 |
+ |
self.m_mut() |
|
259 |
+ |
.placements_of |
|
260 |
+ |
.entry(*node) |
|
261 |
+ |
.or_default() |
|
262 |
+ |
.insert(key); |
| 235 |
263 |
|
self.index_placement(key); |
| 236 |
264 |
|
if *kind != NodeKind::Dir { |
| 237 |
|
- |
self.modes.insert(key, (*node, *mode)); |
| 238 |
|
- |
self.modes_of.entry(*node).or_default().insert(key); |
|
265 |
+ |
self.m_mut().modes.insert(key, (*node, *mode)); |
|
266 |
+ |
self.m_mut().modes_of.entry(*node).or_default().insert(key); |
| 239 |
267 |
|
self.index_mode(key); |
| 240 |
268 |
|
} |
| 241 |
269 |
|
} |
| 242 |
270 |
|
TreeOp::RemoveNode { placement, .. } => { |
| 243 |
|
- |
self.deleted_placements |
|
271 |
+ |
self.m_mut() |
|
272 |
+ |
.deleted_placements |
| 244 |
273 |
|
.entry(op_key(*placement)) |
| 245 |
274 |
|
.or_default() |
| 246 |
275 |
|
.insert(change); |
|
|
… |
5 unchanged lines |
| 252 |
281 |
|
parent, |
| 253 |
282 |
|
name, |
| 254 |
283 |
|
} => { |
| 255 |
|
- |
self.deleted_placements |
|
284 |
+ |
self.m_mut() |
|
285 |
+ |
.deleted_placements |
| 256 |
286 |
|
.entry(op_key(*old)) |
| 257 |
287 |
|
.or_default() |
| 258 |
288 |
|
.insert(change); |
| 259 |
289 |
|
self.index_placement(op_key(*old)); |
| 260 |
|
- |
self.placements.insert( |
|
290 |
+ |
self.m_mut().placements.insert( |
| 261 |
291 |
|
key, |
| 262 |
292 |
|
Placement { |
| 263 |
293 |
|
node: *node, |
|
|
… |
1 unchanged lines |
| 265 |
295 |
|
name: name.clone(), |
| 266 |
296 |
|
}, |
| 267 |
297 |
|
); |
| 268 |
|
- |
self.placements_of.entry(*node).or_default().insert(key); |
|
298 |
+ |
self.m_mut() |
|
299 |
+ |
.placements_of |
|
300 |
+ |
.entry(*node) |
|
301 |
+ |
.or_default() |
|
302 |
+ |
.insert(key); |
| 269 |
303 |
|
self.index_placement(key); |
| 270 |
304 |
|
} |
| 271 |
305 |
|
TreeOp::SetMode { node, old, mode } => { |
| 272 |
|
- |
self.deleted_modes |
|
306 |
+ |
self.m_mut() |
|
307 |
+ |
.deleted_modes |
| 273 |
308 |
|
.entry(op_key(*old)) |
| 274 |
309 |
|
.or_default() |
| 275 |
310 |
|
.insert(change); |
| 276 |
311 |
|
self.index_mode(op_key(*old)); |
| 277 |
|
- |
self.modes.insert(key, (*node, *mode)); |
| 278 |
|
- |
self.modes_of.entry(*node).or_default().insert(key); |
|
312 |
+ |
self.m_mut().modes.insert(key, (*node, *mode)); |
|
313 |
+ |
self.m_mut().modes_of.entry(*node).or_default().insert(key); |
| 279 |
314 |
|
self.index_mode(key); |
| 280 |
315 |
|
} |
| 281 |
316 |
|
} |
|
|
… |
48 unchanged lines |
| 330 |
365 |
|
return true; |
| 331 |
366 |
|
} |
| 332 |
367 |
|
if self |
|
368 |
+ |
.m() |
| 333 |
369 |
|
.live_placements_of |
| 334 |
370 |
|
.get(&node) |
| 335 |
371 |
|
.is_none_or(|s| s.len() != 1) |
| 336 |
372 |
|
{ |
| 337 |
373 |
|
return false; |
| 338 |
374 |
|
} |
| 339 |
|
- |
let Some(p) = self.placements.get(&key) else { |
|
375 |
+ |
let Some(p) = self.m().placements.get(&key) else { |
| 340 |
376 |
|
return false; |
| 341 |
377 |
|
}; |
| 342 |
378 |
|
let Some(path) = c.dirs.get(&p.parent).map(|d| join(d, &p.name)) else { |
|
|
… |
28 unchanged lines |
| 371 |
407 |
|
|
| 372 |
408 |
|
/// Drop the view entry of `node`'s placement `key`, just retired. |
| 373 |
409 |
|
fn view_remove(&self, c: &mut CachedView, node: NodeId, key: OpKey) -> bool { |
| 374 |
|
- |
if self.live_placements_of.contains_key(&node) { |
|
410 |
+ |
if self.m().live_placements_of.contains_key(&node) { |
| 375 |
411 |
|
return false; |
| 376 |
412 |
|
} |
| 377 |
|
- |
let Some(p) = self.placements.get(&key) else { |
|
413 |
+ |
let Some(p) = self.m().placements.get(&key) else { |
| 378 |
414 |
|
return false; |
| 379 |
415 |
|
}; |
| 380 |
416 |
|
let Some(path) = c.dirs.get(&p.parent).map(|d| join(d, &p.name)) else { |
|
|
… |
29 unchanged lines |
| 410 |
446 |
|
} |
| 411 |
447 |
|
let mode_atom = lm.iter().map(|(k, _)| *k).max(); |
| 412 |
448 |
|
let mode = mode_atom |
| 413 |
|
- |
.and_then(|k| self.modes.get(&k).map(|(_, m)| *m)) |
|
449 |
+ |
.and_then(|k| self.m().modes.get(&k).map(|(_, m)| *m)) |
| 414 |
450 |
|
.unwrap_or_default(); |
| 415 |
451 |
|
Some((mode_atom, mode)) |
| 416 |
452 |
|
} |
| 417 |
453 |
|
|
| 418 |
454 |
|
/// Bring placement `k` in the live index up to date. |
| 419 |
455 |
|
fn index_placement(&mut self, k: OpKey) { |
| 420 |
|
- |
let Some(node) = self.placements.get(&k).map(|p| p.node) else { |
|
456 |
+ |
let Some(node) = self.m_mut().placements.get(&k).map(|p| p.node) else { |
| 421 |
457 |
|
return; |
| 422 |
458 |
|
}; |
| 423 |
459 |
|
if self.placement_live(&k) { |
| 424 |
|
- |
self.live_placements_of.entry(node).or_default().insert(k); |
| 425 |
|
- |
} else if let Some(set) = self.live_placements_of.get_mut(&node) { |
|
460 |
+ |
self.m_mut() |
|
461 |
+ |
.live_placements_of |
|
462 |
+ |
.entry(node) |
|
463 |
+ |
.or_default() |
|
464 |
+ |
.insert(k); |
|
465 |
+ |
} else if let Some(set) = self.m_mut().live_placements_of.get_mut(&node) { |
| 426 |
466 |
|
set.remove(&k); |
| 427 |
467 |
|
if set.is_empty() { |
| 428 |
|
- |
self.live_placements_of.remove(&node); |
|
468 |
+ |
self.m_mut().live_placements_of.remove(&node); |
| 429 |
469 |
|
} |
| 430 |
470 |
|
} |
| 431 |
471 |
|
} |
| 432 |
472 |
|
|
| 433 |
473 |
|
/// Bring mode atom `k` in the live index up to date. |
| 434 |
474 |
|
fn index_mode(&mut self, k: OpKey) { |
| 435 |
|
- |
let Some(node) = self.modes.get(&k).map(|(n, _)| *n) else { |
|
475 |
+ |
let Some(node) = self.m_mut().modes.get(&k).map(|(n, _)| *n) else { |
| 436 |
476 |
|
return; |
| 437 |
477 |
|
}; |
| 438 |
478 |
|
if self.mode_live(&k) { |
| 439 |
|
- |
self.live_modes_of.entry(node).or_default().insert(k); |
| 440 |
|
- |
} else if let Some(set) = self.live_modes_of.get_mut(&node) { |
|
479 |
+ |
self.m_mut() |
|
480 |
+ |
.live_modes_of |
|
481 |
+ |
.entry(node) |
|
482 |
+ |
.or_default() |
|
483 |
+ |
.insert(k); |
|
484 |
+ |
} else if let Some(set) = self.m_mut().live_modes_of.get_mut(&node) { |
| 441 |
485 |
|
set.remove(&k); |
| 442 |
486 |
|
if set.is_empty() { |
| 443 |
|
- |
self.live_modes_of.remove(&node); |
|
487 |
+ |
self.m_mut().live_modes_of.remove(&node); |
| 444 |
488 |
|
} |
| 445 |
489 |
|
} |
| 446 |
490 |
|
} |
|
|
… |
3 unchanged lines |
| 450 |
494 |
|
/// back rather than make a second node for one Git path. |
| 451 |
495 |
|
pub fn dead_dirs(&self) -> HashMap<(NodeId, String), (NodeId, OpKey)> { |
| 452 |
496 |
|
let mut out: HashMap<(NodeId, String), (NodeId, OpKey)> = HashMap::new(); |
| 453 |
|
- |
for (k, p) in &self.placements { |
|
497 |
+ |
for (k, p) in &self.m().placements { |
| 454 |
498 |
|
if self.kind(&p.node) != Some(NodeKind::Dir) |
| 455 |
499 |
|
|| self.placement_live(k) |
| 456 |
500 |
|
|| !self.live_placements(&p.node).is_empty() |
|
|
… |
14 unchanged lines |
| 471 |
515 |
|
/// Every placement `node` ever had, live or not, with the changes that |
| 472 |
516 |
|
/// retired it (none while live). |
| 473 |
517 |
|
pub fn placement_history(&self, node: &NodeId) -> Vec<(OpKey, &Placement, Vec<ChangeHash>)> { |
| 474 |
|
- |
self.placements_of |
|
518 |
+ |
self.m() |
|
519 |
+ |
.placements_of |
| 475 |
520 |
|
.get(node) |
| 476 |
521 |
|
.into_iter() |
| 477 |
522 |
|
.flatten() |
| 478 |
523 |
|
.filter_map(|k| { |
| 479 |
|
- |
let p = self.placements.get(k)?; |
|
524 |
+ |
let p = self.m().placements.get(k)?; |
| 480 |
525 |
|
let by = self |
|
526 |
+ |
.m() |
| 481 |
527 |
|
.deleted_placements |
| 482 |
528 |
|
.get(k) |
| 483 |
529 |
|
.map(|d| d.iter().copied().collect()) |
|
|
… |
4 unchanged lines |
| 488 |
534 |
|
} |
| 489 |
535 |
|
|
| 490 |
536 |
|
fn placement_live(&self, k: &OpKey) -> bool { |
| 491 |
|
- |
self.deleted_placements.get(k).is_none_or(|d| d.is_empty()) |
|
537 |
+ |
self.m() |
|
538 |
+ |
.deleted_placements |
|
539 |
+ |
.get(k) |
|
540 |
+ |
.is_none_or(|d| d.is_empty()) |
| 492 |
541 |
|
} |
| 493 |
542 |
|
fn mode_live(&self, k: &OpKey) -> bool { |
| 494 |
|
- |
self.deleted_modes.get(k).is_none_or(|d| d.is_empty()) |
|
543 |
+ |
self.m().deleted_modes.get(k).is_none_or(|d| d.is_empty()) |
| 495 |
544 |
|
} |
| 496 |
545 |
|
|
| 497 |
546 |
|
pub fn kind(&self, node: &NodeId) -> Option<NodeKind> { |
| 498 |
547 |
|
if node.is_root() { |
| 499 |
548 |
|
Some(NodeKind::Dir) |
| 500 |
549 |
|
} else { |
| 501 |
|
- |
self.kinds.get(node).copied() |
|
550 |
+ |
self.m().kinds.get(node).copied() |
| 502 |
551 |
|
} |
| 503 |
552 |
|
} |
| 504 |
553 |
|
|
| 505 |
554 |
|
/// The change whose `AddNode` introduced `node`. |
| 506 |
555 |
|
pub fn introducer(&self, node: &NodeId) -> Option<ChangeHash> { |
| 507 |
|
- |
self.introduced.get(node).copied() |
|
556 |
+ |
self.m().introduced.get(node).copied() |
| 508 |
557 |
|
} |
| 509 |
558 |
|
|
| 510 |
559 |
|
pub fn placement(&self, k: &OpKey) -> Option<&Placement> { |
| 511 |
|
- |
self.placements.get(k) |
|
560 |
+ |
self.m().placements.get(k) |
| 512 |
561 |
|
} |
| 513 |
562 |
|
|
| 514 |
563 |
|
pub fn live_placements(&self, node: &NodeId) -> Vec<(OpKey, &Placement)> { |
| 515 |
|
- |
self.live_placements_of |
|
564 |
+ |
self.m() |
|
565 |
+ |
.live_placements_of |
| 516 |
566 |
|
.get(node) |
| 517 |
567 |
|
.into_iter() |
| 518 |
568 |
|
.flat_map(|ks| ks.iter()) |
| 519 |
|
- |
.filter_map(|k| self.placements.get(k).map(|p| (*k, p))) |
|
569 |
+ |
.filter_map(|k| self.m().placements.get(k).map(|p| (*k, p))) |
| 520 |
570 |
|
.collect() |
| 521 |
571 |
|
} |
| 522 |
572 |
|
|
| 523 |
573 |
|
pub fn live_modes(&self, node: &NodeId) -> Vec<(OpKey, Mode)> { |
| 524 |
|
- |
self.live_modes_of |
|
574 |
+ |
self.m() |
|
575 |
+ |
.live_modes_of |
| 525 |
576 |
|
.get(node) |
| 526 |
577 |
|
.into_iter() |
| 527 |
578 |
|
.flat_map(|ks| ks.iter()) |
| 528 |
|
- |
.filter_map(|k| self.modes.get(k).map(|(_, m)| (*k, *m))) |
|
579 |
+ |
.filter_map(|k| self.m().modes.get(k).map(|(_, m)| (*k, *m))) |
| 529 |
580 |
|
.collect() |
| 530 |
581 |
|
} |
| 531 |
582 |
|
|
| 532 |
583 |
|
/// Every node that has at least one live placement. |
| 533 |
584 |
|
pub fn placed_nodes(&self) -> impl Iterator<Item = NodeId> + '_ { |
| 534 |
|
- |
self.live_placements_of.keys().copied() |
|
585 |
+ |
self.m().live_placements_of.keys().copied() |
| 535 |
586 |
|
} |
| 536 |
587 |
|
|
| 537 |
588 |
|
/// Resolve the tree: assign paths, find conflicts. |
|
|
… |
12 unchanged lines |
| 550 |
601 |
|
|
| 551 |
602 |
|
// Live placements grouped by parent. |
| 552 |
603 |
|
let mut children: HashMap<NodeId, Vec<(OpKey, &Placement)>> = HashMap::new(); |
| 553 |
|
- |
for ks in self.live_placements_of.values() { |
|
604 |
+ |
for ks in self.m().live_placements_of.values() { |
| 554 |
605 |
|
for k in ks { |
| 555 |
|
- |
if let Some(p) = self.placements.get(k) { |
|
606 |
+ |
if let Some(p) = self.m().placements.get(k) { |
| 556 |
607 |
|
children.entry(p.parent).or_default().push((*k, p)); |
| 557 |
608 |
|
} |
| 558 |
609 |
|
} |
|
|
… |
4 unchanged lines |
| 563 |
614 |
|
|
| 564 |
615 |
|
// Multi-placement and mode conflicts. |
| 565 |
616 |
|
// Only placed nodes: one with no live placement is not in the tree. |
| 566 |
|
- |
let mut nodes: Vec<NodeId> = self.live_placements_of.keys().copied().collect(); |
|
617 |
+ |
let mut nodes: Vec<NodeId> = self.m().live_placements_of.keys().copied().collect(); |
| 567 |
618 |
|
nodes.sort(); |
| 568 |
619 |
|
let mut multi: HashSet<NodeId> = HashSet::new(); |
| 569 |
620 |
|
// Each node's mode and the atom it comes from, for the entries. |
|
|
… |
26 unchanged lines |
| 596 |
647 |
|
} |
| 597 |
648 |
|
let mode_atom = lm.iter().map(|(k, _)| *k).max(); |
| 598 |
649 |
|
let mode = mode_atom |
| 599 |
|
- |
.and_then(|k| self.modes.get(&k).map(|(_, m)| *m)) |
|
650 |
+ |
.and_then(|k| self.m().modes.get(&k).map(|(_, m)| *m)) |
| 600 |
651 |
|
.unwrap_or_default(); |
| 601 |
652 |
|
modes.insert(*n, (mode_atom, mode)); |
| 602 |
653 |
|
} |
|
|
… |
128 unchanged lines |
| 731 |
782 |
|
.collect(), |
| 732 |
783 |
|
) |
| 733 |
784 |
|
}; |
| 734 |
|
- |
let mut nodes: Vec<&NodeId> = self.kinds.keys().collect(); |
|
785 |
+ |
let mut nodes: Vec<&NodeId> = self.m().kinds.keys().collect(); |
| 735 |
786 |
|
nodes.sort(); |
| 736 |
|
- |
let mut pks: Vec<&OpKey> = self.placements.keys().collect(); |
|
787 |
+ |
let mut pks: Vec<&OpKey> = self.m().placements.keys().collect(); |
| 737 |
788 |
|
pks.sort(); |
| 738 |
|
- |
let mut mks: Vec<&OpKey> = self.modes.keys().collect(); |
|
789 |
+ |
let mut mks: Vec<&OpKey> = self.m().modes.keys().collect(); |
| 739 |
790 |
|
mks.sort(); |
| 740 |
791 |
|
Value::map([ |
| 741 |
792 |
|
( |
|
|
… |
4 unchanged lines |
| 746 |
797 |
|
.map(|n| { |
| 747 |
798 |
|
Value::Array(vec![ |
| 748 |
799 |
|
Value::Bytes(n.0.to_vec()), |
| 749 |
|
- |
Value::Uint(self.kinds[n].tag()), |
| 750 |
|
- |
self.introduced |
|
800 |
+ |
Value::Uint(self.m().kinds[n].tag()), |
|
801 |
+ |
self.m() |
|
802 |
+ |
.introduced |
| 751 |
803 |
|
.get(n) |
| 752 |
804 |
|
.map(|h| Value::Bytes(h.0.to_vec())) |
| 753 |
805 |
|
.unwrap_or(Value::Null), |
|
|
… |
7 unchanged lines |
| 761 |
813 |
|
Value::Array( |
| 762 |
814 |
|
pks.into_iter() |
| 763 |
815 |
|
.map(|k| { |
| 764 |
|
- |
let p = &self.placements[k]; |
|
816 |
+ |
let p = &self.m().placements[k]; |
| 765 |
817 |
|
let mut v = opkey(k); |
| 766 |
818 |
|
v.extend([ |
| 767 |
819 |
|
Value::Bytes(p.node.0.to_vec()), |
|
|
… |
5 unchanged lines |
| 773 |
825 |
|
.collect(), |
| 774 |
826 |
|
), |
| 775 |
827 |
|
), |
| 776 |
|
- |
(2, deleters(&self.deleted_placements)), |
|
828 |
+ |
(2, deleters(&self.m().deleted_placements)), |
| 777 |
829 |
|
( |
| 778 |
830 |
|
3, |
| 779 |
831 |
|
Value::Array( |
| 780 |
832 |
|
mks.into_iter() |
| 781 |
833 |
|
.map(|k| { |
| 782 |
|
- |
let (n, m) = &self.modes[k]; |
|
834 |
+ |
let (n, m) = &self.m().modes[k]; |
| 783 |
835 |
|
let mut v = opkey(k); |
| 784 |
836 |
|
v.extend([Value::Bytes(n.0.to_vec()), Value::Uint(m.bits())]); |
| 785 |
837 |
|
Value::Array(v) |
|
|
… |
1 unchanged lines |
| 787 |
839 |
|
.collect(), |
| 788 |
840 |
|
), |
| 789 |
841 |
|
), |
| 790 |
|
- |
(4, deleters(&self.deleted_modes)), |
|
842 |
+ |
(4, deleters(&self.m().deleted_modes)), |
| 791 |
843 |
|
]) |
| 792 |
844 |
|
} |
| 793 |
845 |
|
|
|
|
… |
14 unchanged lines |
| 808 |
860 |
|
return Err(ObjectError::Schema("node entry: expected 3 fields".into())); |
| 809 |
861 |
|
} |
| 810 |
862 |
|
let id = node(&e[0])?; |
| 811 |
|
- |
g.kinds |
|
863 |
+ |
g.m_mut() |
|
864 |
+ |
.kinds |
| 812 |
865 |
|
.insert(id, NodeKind::from_tag(uint(&e[1], "kind")?)?); |
| 813 |
866 |
|
if !e[2].is_null() { |
| 814 |
|
- |
g.introduced.insert(id, oref(&e[2], "introducer")?); |
|
867 |
+ |
g.m_mut().introduced.insert(id, oref(&e[2], "introducer")?); |
| 815 |
868 |
|
} |
| 816 |
869 |
|
} |
| 817 |
870 |
|
for p in array(field(m, 1, "placements")?, "placements")? { |
|
|
… |
7 unchanged lines |
| 825 |
878 |
|
parent: node(&e[3])?, |
| 826 |
879 |
|
name: text(&e[4], "name")?.to_owned(), |
| 827 |
880 |
|
}; |
| 828 |
|
- |
g.placements_of.entry(pl.node).or_default().insert(k); |
| 829 |
|
- |
g.placements.insert(k, pl); |
|
881 |
+ |
g.m_mut() |
|
882 |
+ |
.placements_of |
|
883 |
+ |
.entry(pl.node) |
|
884 |
+ |
.or_default() |
|
885 |
+ |
.insert(k); |
|
886 |
+ |
g.m_mut().placements.insert(k, pl); |
| 830 |
887 |
|
} |
| 831 |
888 |
|
let deleters = |v: &crate::cbor::Value, |
| 832 |
889 |
|
what: &str| |
|
|
… |
14 unchanged lines |
| 847 |
904 |
|
} |
| 848 |
905 |
|
Ok(out) |
| 849 |
906 |
|
}; |
| 850 |
|
- |
g.deleted_placements = deleters(field(m, 2, "deleted placements")?, "deleted placement")?; |
|
907 |
+ |
g.m_mut().deleted_placements = |
|
908 |
+ |
deleters(field(m, 2, "deleted placements")?, "deleted placement")?; |
| 851 |
909 |
|
for md in array(field(m, 3, "modes")?, "modes")? { |
| 852 |
910 |
|
let e = array(md, "mode")?; |
| 853 |
911 |
|
if e.len() != 4 { |
|
|
… |
1 unchanged lines |
| 855 |
913 |
|
} |
| 856 |
914 |
|
let k = opkey(e)?; |
| 857 |
915 |
|
let n = node(&e[2])?; |
| 858 |
|
- |
g.modes |
|
916 |
+ |
g.m_mut() |
|
917 |
+ |
.modes |
| 859 |
918 |
|
.insert(k, (n, Mode::from_bits(uint(&e[3], "mode bits")?)?)); |
| 860 |
|
- |
g.modes_of.entry(n).or_default().insert(k); |
|
919 |
+ |
g.m_mut().modes_of.entry(n).or_default().insert(k); |
| 861 |
920 |
|
} |
| 862 |
|
- |
g.deleted_modes = deleters(field(m, 4, "deleted modes")?, "deleted mode")?; |
| 863 |
|
- |
let keys: Vec<OpKey> = g.placements.keys().copied().collect(); |
|
921 |
+ |
g.m_mut().deleted_modes = deleters(field(m, 4, "deleted modes")?, "deleted mode")?; |
|
922 |
+ |
let keys: Vec<OpKey> = g.m_mut().placements.keys().copied().collect(); |
| 864 |
923 |
|
for k in keys { |
| 865 |
924 |
|
g.index_placement(k); |
| 866 |
925 |
|
} |
| 867 |
|
- |
let keys: Vec<OpKey> = g.modes.keys().copied().collect(); |
|
926 |
+ |
let keys: Vec<OpKey> = g.m_mut().modes.keys().copied().collect(); |
| 868 |
927 |
|
for k in keys { |
| 869 |
928 |
|
g.index_mode(k); |
| 870 |
929 |
|
} |
|
|
… |
9 unchanged lines |
| 880 |
939 |
|
w.object(&k.0); |
| 881 |
940 |
|
w.u32(k.1); |
| 882 |
941 |
|
}; |
| 883 |
|
- |
let mut kinds: Vec<(&NodeId, &NodeKind)> = self.kinds.iter().collect(); |
|
942 |
+ |
// The maps as a block of their own: a reader keeps it undecoded |
|
943 |
+ |
// until something needs them. |
|
944 |
+ |
let outer = std::mem::take(w); |
|
945 |
+ |
let mut kinds: Vec<(&NodeId, &NodeKind)> = self.m().kinds.iter().collect(); |
| 884 |
946 |
|
kinds.sort_by_key(|(n, _)| **n); |
| 885 |
947 |
|
w.count(kinds.len()); |
| 886 |
948 |
|
for (n, k) in kinds { |
| 887 |
949 |
|
w.fixed(&n.0); |
| 888 |
950 |
|
w.u8(k.tag() as u8); |
| 889 |
951 |
|
} |
| 890 |
|
- |
let mut intro: Vec<(&NodeId, &ChangeHash)> = self.introduced.iter().collect(); |
|
952 |
+ |
let mut intro: Vec<(&NodeId, &ChangeHash)> = self.m().introduced.iter().collect(); |
| 891 |
953 |
|
intro.sort(); |
| 892 |
954 |
|
w.count(intro.len()); |
| 893 |
955 |
|
for (n, c) in intro { |
| 894 |
956 |
|
w.fixed(&n.0); |
| 895 |
957 |
|
w.object(c); |
| 896 |
958 |
|
} |
| 897 |
|
- |
let mut pl: Vec<(&OpKey, &Placement)> = self.placements.iter().collect(); |
|
959 |
+ |
let mut pl: Vec<(&OpKey, &Placement)> = self.m().placements.iter().collect(); |
| 898 |
960 |
|
pl.sort_by_key(|(k, _)| **k); |
| 899 |
961 |
|
w.count(pl.len()); |
| 900 |
962 |
|
for (k, p) in pl { |
|
|
… |
2 unchanged lines |
| 903 |
965 |
|
w.fixed(&p.parent.0); |
| 904 |
966 |
|
w.bytes(p.name.as_bytes()); |
| 905 |
967 |
|
} |
| 906 |
|
- |
let mut modes: Vec<(&OpKey, &(NodeId, Mode))> = self.modes.iter().collect(); |
|
968 |
+ |
let mut modes: Vec<(&OpKey, &(NodeId, Mode))> = self.m().modes.iter().collect(); |
| 907 |
969 |
|
modes.sort_by_key(|(k, _)| **k); |
| 908 |
970 |
|
w.count(modes.len()); |
| 909 |
971 |
|
for (k, (n, m)) in modes { |
|
|
… |
1 unchanged lines |
| 911 |
973 |
|
w.fixed(&n.0); |
| 912 |
974 |
|
w.u8(m.bits() as u8); |
| 913 |
975 |
|
} |
| 914 |
|
- |
for m in [&self.deleted_placements, &self.deleted_modes] { |
|
976 |
+ |
for m in [&self.m().deleted_placements, &self.m().deleted_modes] { |
| 915 |
977 |
|
let mut ks: Vec<(&OpKey, &BTreeSet<ChangeHash>)> = m.iter().collect(); |
| 916 |
978 |
|
ks.sort_by_key(|(k, _)| **k); |
| 917 |
979 |
|
w.count(ks.len()); |
|
|
… |
5 unchanged lines |
| 923 |
985 |
|
} |
| 924 |
986 |
|
} |
| 925 |
987 |
|
} |
| 926 |
|
- |
// The view as a block of its own, decoded beside the maps. |
|
988 |
+ |
let maps = std::mem::replace(w, outer); |
|
989 |
+ |
w.bytes(&maps.0); |
|
990 |
+ |
// The view as a block of its own. |
| 927 |
991 |
|
let outer = std::mem::take(w); |
| 928 |
992 |
|
let view = self.view(); |
| 929 |
993 |
|
if view.conflicts.is_empty() { |
|
|
… |
23 unchanged lines |
| 953 |
1017 |
|
pub(crate) fn read_flat( |
| 954 |
1018 |
|
r: &mut crate::flat::Reader, |
| 955 |
1019 |
|
) -> Result<TreeGraph, crate::objects::ObjectError> { |
|
1020 |
+ |
let maps = r.bytes()?; |
|
1021 |
+ |
let view = Self::read_view(r.bytes()?)?; |
|
1022 |
+ |
let mut g = TreeGraph { |
|
1023 |
+ |
raw: Some(std::sync::Arc::new(maps.to_vec())), |
|
1024 |
+ |
..TreeGraph::default() |
|
1025 |
+ |
}; |
|
1026 |
+ |
if let Some(view) = view { |
|
1027 |
+ |
#[cfg(test)] |
|
1028 |
+ |
assert_eq!(view, g.compute_view(), "an index's view is the tree's"); |
|
1029 |
+ |
g.view_cache = std::sync::OnceLock::from(CachedView::new(view)); |
|
1030 |
+ |
} |
|
1031 |
+ |
Ok(g) |
|
1032 |
+ |
} |
|
1033 |
+ |
} |
|
1034 |
+ |
|
|
1035 |
+ |
impl TreeMaps { |
|
1036 |
+ |
/// The maps block of a tree's flat form. |
|
1037 |
+ |
fn decode(bytes: &[u8]) -> Result<TreeMaps, crate::objects::ObjectError> { |
| 956 |
1038 |
|
use crate::objects::ObjectError; |
|
1039 |
+ |
let _t = crate::timing::phase("index: tree maps"); |
| 957 |
1040 |
|
let node = |r: &mut crate::flat::Reader| -> Result<NodeId, ObjectError> { |
| 958 |
1041 |
|
Ok(NodeId(r.fixed::<16>()?)) |
| 959 |
1042 |
|
}; |
| 960 |
1043 |
|
let key = |r: &mut crate::flat::Reader| -> Result<OpKey, ObjectError> { |
| 961 |
1044 |
|
Ok((r.object()?, r.u32()?)) |
| 962 |
1045 |
|
}; |
|
1046 |
+ |
let r = &mut crate::flat::Reader::new(bytes); |
| 963 |
1047 |
|
let mut g = TreeGraph::new(); |
| 964 |
|
- |
let t = crate::timing::phase("index: tree maps"); |
| 965 |
1048 |
|
for _ in 0..r.count()? { |
| 966 |
1049 |
|
let n = node(r)?; |
| 967 |
|
- |
g.kinds.insert(n, NodeKind::from_tag(r.u8()? as u64)?); |
|
1050 |
+ |
g.m_mut() |
|
1051 |
+ |
.kinds |
|
1052 |
+ |
.insert(n, NodeKind::from_tag(r.u8()? as u64)?); |
| 968 |
1053 |
|
} |
| 969 |
1054 |
|
for _ in 0..r.count()? { |
| 970 |
1055 |
|
let n = node(r)?; |
| 971 |
|
- |
g.introduced.insert(n, r.object()?); |
|
1056 |
+ |
g.m_mut().introduced.insert(n, r.object()?); |
| 972 |
1057 |
|
} |
| 973 |
1058 |
|
for _ in 0..r.count()? { |
| 974 |
1059 |
|
let k = key(r)?; |
|
|
… |
2 unchanged lines |
| 977 |
1062 |
|
parent: node(r)?, |
| 978 |
1063 |
|
name: r.text()?, |
| 979 |
1064 |
|
}; |
| 980 |
|
- |
g.placements_of.entry(p.node).or_default().insert(k); |
| 981 |
|
- |
g.placements.insert(k, p); |
|
1065 |
+ |
g.m_mut().placements_of.entry(p.node).or_default().insert(k); |
|
1066 |
+ |
g.m_mut().placements.insert(k, p); |
| 982 |
1067 |
|
} |
| 983 |
1068 |
|
for _ in 0..r.count()? { |
| 984 |
1069 |
|
let k = key(r)?; |
| 985 |
1070 |
|
let n = node(r)?; |
| 986 |
|
- |
g.modes.insert(k, (n, Mode::from_bits(r.u8()? as u64)?)); |
| 987 |
|
- |
g.modes_of.entry(n).or_default().insert(k); |
|
1071 |
+ |
g.m_mut() |
|
1072 |
+ |
.modes |
|
1073 |
+ |
.insert(k, (n, Mode::from_bits(r.u8()? as u64)?)); |
|
1074 |
+ |
g.m_mut().modes_of.entry(n).or_default().insert(k); |
| 988 |
1075 |
|
} |
| 989 |
1076 |
|
for i in 0..2 { |
| 990 |
1077 |
|
let mut m: Map<OpKey, BTreeSet<ChangeHash>> = Map::default(); |
|
|
… |
6 unchanged lines |
| 997 |
1084 |
|
m.insert(k, by); |
| 998 |
1085 |
|
} |
| 999 |
1086 |
|
if i == 0 { |
| 1000 |
|
- |
g.deleted_placements = m; |
|
1087 |
+ |
g.m_mut().deleted_placements = m; |
| 1001 |
1088 |
|
} else { |
| 1002 |
|
- |
g.deleted_modes = m; |
|
1089 |
+ |
g.m_mut().deleted_modes = m; |
| 1003 |
1090 |
|
} |
| 1004 |
1091 |
|
} |
| 1005 |
|
- |
drop(t); |
| 1006 |
|
- |
let view_bytes = r.bytes()?; |
| 1007 |
|
- |
let (view, ()) = rayon::join( |
| 1008 |
|
- |
|| Self::read_view(view_bytes), |
| 1009 |
|
- |
|| { |
| 1010 |
|
- |
let _t = crate::timing::phase("index: tree live"); |
| 1011 |
|
- |
let keys: Vec<OpKey> = g.placements.keys().copied().collect(); |
| 1012 |
|
- |
for k in keys { |
| 1013 |
|
- |
g.index_placement(k); |
| 1014 |
|
- |
} |
| 1015 |
|
- |
let keys: Vec<OpKey> = g.modes.keys().copied().collect(); |
| 1016 |
|
- |
for k in keys { |
| 1017 |
|
- |
g.index_mode(k); |
| 1018 |
|
- |
} |
| 1019 |
|
- |
}, |
| 1020 |
|
- |
); |
| 1021 |
|
- |
if let Some(view) = view? { |
| 1022 |
|
- |
#[cfg(test)] |
| 1023 |
|
- |
assert_eq!(view, g.compute_view(), "an index's view is the tree's"); |
| 1024 |
|
- |
g.view_cache = std::sync::OnceLock::from(CachedView::new(view)); |
|
1092 |
+ |
if !r.at_end() { |
|
1093 |
+ |
return Err(ObjectError::Schema("state index: tree maps".into())); |
|
1094 |
+ |
} |
|
1095 |
+ |
let keys: Vec<OpKey> = g.m().placements.keys().copied().collect(); |
|
1096 |
+ |
for k in keys { |
|
1097 |
+ |
g.index_placement(k); |
|
1098 |
+ |
} |
|
1099 |
+ |
let keys: Vec<OpKey> = g.m().modes.keys().copied().collect(); |
|
1100 |
+ |
for k in keys { |
|
1101 |
+ |
g.index_mode(k); |
| 1025 |
1102 |
|
} |
| 1026 |
|
- |
Ok(g) |
|
1103 |
+ |
Ok(g.maps.into_inner().unwrap_or_default()) |
| 1027 |
1104 |
|
} |
| 1028 |
1105 |
|
} |
| 1029 |
1106 |
|
|
|
|
… |
436 unchanged lines |