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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::cmp::Ordering;
use crate::Result;
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum LogQueue {
Append = 0,
Rewrite = 1,
}
pub type FileSeq = u64;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct FileId {
pub queue: LogQueue,
pub seq: FileSeq,
}
impl FileId {
pub fn new(queue: LogQueue, seq: FileSeq) -> Self {
Self { queue, seq }
}
#[cfg(test)]
pub fn dummy(queue: LogQueue) -> Self {
Self { queue, seq: 0 }
}
}
impl std::cmp::Ord for FileId {
fn cmp(&self, other: &Self) -> Ordering {
match (self.queue, other.queue) {
(LogQueue::Append, LogQueue::Rewrite) => Ordering::Greater,
(LogQueue::Rewrite, LogQueue::Append) => Ordering::Less,
_ => self.seq.cmp(&other.seq),
}
}
}
impl std::cmp::PartialOrd for FileId {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct FileBlockHandle {
pub id: FileId,
pub offset: u64,
pub len: usize,
}
impl FileBlockHandle {
#[cfg(test)]
pub fn dummy(queue: LogQueue) -> Self {
Self {
id: FileId::dummy(queue),
offset: 0,
len: 0,
}
}
}
pub trait PipeLog: Sized {
fn read_bytes(&self, handle: FileBlockHandle) -> Result<Vec<u8>>;
fn append(&self, queue: LogQueue, bytes: &[u8]) -> Result<FileBlockHandle>;
fn maybe_sync(&self, queue: LogQueue, sync: bool) -> Result<()>;
fn file_span(&self, queue: LogQueue) -> (FileSeq, FileSeq);
fn file_at(&self, queue: LogQueue, mut position: f64) -> FileSeq {
if position > 1.0 {
position = 1.0;
} else if position < 0.0 {
position = 0.0;
}
let (first, active) = self.file_span(queue);
let count = active - first + 1;
first + (count as f64 * position) as u64
}
fn total_size(&self, queue: LogQueue) -> usize;
fn rotate(&self, queue: LogQueue) -> Result<()>;
fn purge_to(&self, file_id: FileId) -> Result<usize>;
}