quotick/
epoch.rs

1use serde::de::DeserializeOwned;
2use serde::Serialize;
3
4use super::BackingFile;
5use super::frame::Frame;
6use super::path_builder::QuotickPathBuilder;
7use super::radix_trie::{Trie, TrieCommon};
8use super::Tick;
9
10#[derive(Debug)]
11pub enum EpochError {
12    BackingFileFailure(&'static str),
13    IndexFileFailure,
14    WriteFailure,
15    FrameConflict,
16    FrameTooBig,
17    FrameEmpty,
18}
19
20type FrameIndex<T> = Trie<u64, T>;
21
22pub struct Epoch<T: Tick + Serialize + DeserializeOwned> {
23    frame_index_backing: BackingFile<FrameIndex<T>>,
24
25    pub frame_index: FrameIndex<T>,
26
27    epoch: u64,
28
29    tainted: bool,
30
31    path_builder: QuotickPathBuilder,
32}
33
34impl<T: Tick + Serialize + DeserializeOwned> Epoch<T> {
35    #[inline(always)]
36    pub fn new(
37        epoch: u64,
38        path_builder: QuotickPathBuilder,
39    ) -> Result<Epoch<T>, EpochError> {
40        let mut frame_index_backing =
41            BackingFile::<FrameIndex<T>>::new(
42                path_builder.index_backing_file(epoch),
43            )
44                .or_else(|_|
45                    Err(
46                        EpochError::BackingFileFailure(
47                            "Failed to open frame index backing file.",
48                        ),
49                    )
50                )?;
51
52        let frame_index =
53            frame_index_backing.try_read()
54                .unwrap_or_else(|_| Trie::new());
55
56        Ok(
57            Epoch {
58                frame_index_backing,
59                frame_index,
60
61                epoch,
62                tainted: false,
63
64                path_builder,
65            },
66        )
67    }
68
69    #[inline(always)]
70    pub fn frames(&mut self) -> impl Iterator<Item=Frame<T>> + '_ {
71        self.frame_index
72            .iter()
73            .map(|(time, item)|
74                     Frame::new(
75                         *time,
76                         item.clone(),
77                     ),
78            )
79    }
80
81    #[inline(always)]
82    pub fn epoch(&self) -> u64 {
83        self.epoch
84    }
85
86    #[inline(always)]
87    pub fn insert(
88        &mut self,
89        frame: &Frame<T>,
90        force_overwrite: bool,
91    ) -> Result<(), EpochError> {
92        let time = frame.time();
93
94        if !force_overwrite && self.frame_index.get(&time).is_some() {
95            return Err(EpochError::FrameConflict);
96        }
97
98        self.frame_index
99            .insert(
100                time,
101                frame.tick().clone(),
102            );
103
104        self.tainted = true;
105
106        Ok(())
107    }
108
109    #[inline(always)]
110    pub fn persist(&mut self) {
111        if !self.tainted {
112            return;
113        }
114
115        self.frame_index_backing
116            .write_all(
117                &self.frame_index,
118            );
119
120        self.tainted = false;
121    }
122}
123
124impl<T: Tick + Serialize + DeserializeOwned> Drop for Epoch<T> {
125    #[inline(always)]
126    fn drop(&mut self) {
127        self.persist();
128    }
129}