1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! In-memory live tail published by the I/O thread after fsync.
use std::collections::{BTreeMap, HashSet};
use std::sync::Arc;
use crate::infinitedb_core::{
address::RevisionId,
block::Record,
hilbert_key::HilbertKey,
record_identity::RecordIdentityKey,
snapshot::BlockIndexEntry,
space::SpaceRegistry,
};
use super::shard_view::{ShardView, ShardViewHandle, TailChunk};
/// Records visible to readers before hot segment seal.
///
/// Internally pairs sealed block index entries with the live tail in a single
/// [`ShardViewHandle`] so readers observe a consistent view.
pub struct LiveTailView {
view: ShardViewHandle,
}
impl LiveTailView {
pub fn new() -> Self {
Self {
view: ShardViewHandle::new(),
}
}
/// Load the atomic shard view for consistent reads.
pub fn load_view(&self) -> arc_swap::Guard<Arc<ShardView>> {
self.view.load()
}
/// Load shared tail chunks (zero-copy read path).
pub fn load(&self) -> Arc<Vec<TailChunk>> {
self.view.load_tail_chunks()
}
/// Replace the visible tail (called from the I/O thread on recovery).
pub fn publish(&self, records: Vec<Record>) {
self.view.publish_tail(records);
}
/// Append one durable record to the published tail.
pub fn append(&self, record: Record) {
self.view.append(record);
}
/// Publish a group of durable records in one chunk.
pub fn extend_chunk(&self, records: Vec<Record>) {
self.view.extend_chunk(records);
}
/// Publish a new sealed block and truncated tail atomically.
pub fn seal(
&self,
block_min_key: HilbertKey,
entry: BlockIndexEntry,
sealed: &HashSet<RecordIdentityKey>,
spaces: &SpaceRegistry,
) {
self.view.seal(block_min_key, entry, sealed, spaces);
}
/// Initialize sealed blocks from recovery.
pub fn init_blocks(&self, blocks: BTreeMap<HilbertKey, BlockIndexEntry>) {
self.view.init_blocks(blocks);
}
/// Explicit clone of all tail records (prefer [`load`] for zero-copy read paths).
pub fn snapshot(&self) -> Vec<Record> {
self.load_view().tail_vec()
}
pub fn captured_at(&self) -> RevisionId {
self.view.captured_at()
}
}
impl Default for LiveTailView {
fn default() -> Self {
Self::new()
}
}