1
use std::{fmt::Debug, io};
2

            
3
use file_manager::{fs::StdFileManager, FileManager};
4

            
5
use crate::{
6
    entry::EntryId,
7
    log_file::{Entry, RecoveredSegment, SegmentReader},
8
    WriteAheadLog,
9
};
10

            
11
/// Customizes recovery and checkpointing behavior for a
12
/// [`WriteAheadLog`](crate::WriteAheadLog).
13
pub trait LogManager<M = StdFileManager>: Send + Sync + Debug + 'static
14
where
15
    M: FileManager,
16
{
17
    /// When recovering a [`WriteAheadLog`](crate::WriteAheadLog), this function
18
    /// is called for each segment as it is read. To allow the segment to have
19
    /// its data recovered, return [`Recovery::Recover`]. If you wish to abandon
20
    /// the data contained in the segment, return [`Recovery::Abandon`].
21
3
    fn should_recover_segment(&mut self, _segment: &RecoveredSegment) -> io::Result<Recovery> {
22
3
        Ok(Recovery::Recover)
23
3
    }
24

            
25
    /// Invoked once for each entry contained in all recovered segments within a
26
    /// [`WriteAheadLog`](crate::WriteAheadLog).
27
    ///
28
    /// [`Entry::read_chunk()`] can be used to read each chunk of data that was
29
    /// written via
30
    /// [`EntryWriter::write_chunk`](crate::EntryWriter::write_chunk). The order
31
    /// of chunks is guaranteed to be the same as the order they were written
32
    /// in.
33
    fn recover(&mut self, entry: &mut Entry<'_, M::File>) -> io::Result<()>;
34

            
35
    /// Invoked each time the [`WriteAheadLog`](crate::WriteAheadLog) is ready
36
    /// to recycle and reuse segment files.
37
    ///
38
    /// `last_checkpointed_id` is the id of the last entry that is being
39
    /// checkedpointed and removed from the log. If needed,
40
    /// `checkpointed_entries` can be used to iterate over all entries that are
41
    /// being checkpointed.
42
    ///
43
    /// Shortly after this function returns, the entries stored within the file
44
    /// being checkpointed will no longer be accessible. To ensure ACID
45
    /// compliance of the underlying storage layer, all necessary changes must
46
    /// be fully synchronized to the underlying storage medium before this
47
    /// function returns.
48
    fn checkpoint_to(
49
        &mut self,
50
        last_checkpointed_id: EntryId,
51
        checkpointed_entries: &mut SegmentReader<M::File>,
52
        wal: &WriteAheadLog<M>,
53
    ) -> io::Result<()>;
54
}
55

            
56
/// Determines whether to recover a segment or not.
57
pub enum Recovery {
58
    /// Recover the segment.
59
    Recover,
60
    /// Abandon the segment and any entries stored within it. **Warning: This
61
    /// means losing data that was previously written to the log. This should
62
    /// rarely, if ever, be done.**
63
    Abandon,
64
}
65

            
66
/// A [`LogManager`] that does not attempt to recover any existing data.
67
#[derive(Debug)]
68
pub struct LogVoid;
69

            
70
impl<M> LogManager<M> for LogVoid
71
where
72
    M: file_manager::FileManager,
73
{
74
    fn should_recover_segment(&mut self, _segment: &RecoveredSegment) -> io::Result<Recovery> {
75
        Ok(Recovery::Abandon)
76
    }
77

            
78
    fn recover(&mut self, _entry: &mut Entry<'_, M::File>) -> io::Result<()> {
79
        Ok(())
80
    }
81

            
82
2131
    fn checkpoint_to(
83
2131
        &mut self,
84
2131
        _last_checkpointed_id: EntryId,
85
2131
        _reader: &mut SegmentReader<M::File>,
86
2131
        _wal: &WriteAheadLog<M>,
87
2131
    ) -> io::Result<()> {
88
2131
        Ok(())
89
2131
    }
90
}