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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use crate::{
commit::{CommitHash, CommitProof, CommitTree},
events::{
patch::{CheckedPatch, Diff, Patch},
EventRecord,
},
Error,
};
use async_trait::async_trait;
use binary_stream::futures::{Decodable, Encodable};
use futures::stream::BoxStream;
/// Event log iterator, stream and diff support.
#[async_trait]
pub trait EventLog<E>: Send + Sync
where
E: Default + Encodable + Decodable + Send + Sync + 'static,
{
/// Error type.
type Error: std::error::Error + std::fmt::Debug + From<Error>;
/// Commit tree contains the in-memory merkle tree.
fn tree(&self) -> &CommitTree;
/// Delete all events from the log file on disc
/// and in-memory.
async fn clear(&mut self) -> Result<(), Self::Error>;
/// Rewind this event log discarding commits after
/// the specific commit.
///
/// Returns the collection of log records that can
/// be used to revert if a subsequent merge fails.
async fn rewind(
&mut self,
commit: &CommitHash,
) -> Result<Vec<EventRecord>, Self::Error>;
/// Load data from storage to build a commit tree in memory.
async fn load_tree(&mut self) -> Result<(), Self::Error>;
/// Stream of event records.
///
/// # Panics
///
/// If the iterator cannot be initialized.
async fn record_stream(
&self,
reverse: bool,
) -> BoxStream<'async_trait, Result<EventRecord, Self::Error>>;
/// Stream of event records and decoded events.
///
/// # Panics
///
/// If the iterator cannot be initialized.
async fn event_stream(
&self,
reverse: bool,
) -> BoxStream<'async_trait, Result<(EventRecord, E), Self::Error>>;
/// Create a checked diff from a commit.
///
/// Used when merging to verify that the HEAD of the
/// event log matches the checkpoint before applying
/// the patch.
async fn diff_checked(
&self,
commit: Option<CommitHash>,
checkpoint: CommitProof,
) -> Result<Diff<E>, Self::Error>;
/// Create an unchecked diff of all events.
///
/// Used during a force merge to overwrite an event log
/// with new events.
///
/// For example, when destructive changes are made (change
/// cipher or password) then other devices need to rewrite
/// the event logs.
async fn diff_unchecked(&self) -> Result<Diff<E>, Self::Error>;
/// Diff of events until a specific commit; does
/// not include the target commit.
///
/// If no commit hash is given then all events are included.
async fn diff_events(
&self,
commit: Option<&CommitHash>,
) -> Result<Patch<E>, Self::Error>;
/// Append a collection of events and commit the tree hashes
/// only if all the events were successfully written.
async fn apply(&mut self, events: &[E]) -> Result<(), Self::Error>;
/// Append raw event records to the event log.
///
/// Use this to preserve the time information in
/// existing event records.
async fn apply_records(
&mut self,
records: Vec<EventRecord>,
) -> Result<(), Self::Error>;
/// Append a patch to this event log only if the
/// head of the tree matches the given proof.
async fn patch_checked(
&mut self,
commit_proof: &CommitProof,
patch: &Patch<E>,
) -> Result<CheckedPatch, Self::Error>;
/// Replace all events in this event log with the events in the diff.
///
/// For disc based implementations a snapshot is created
/// of the event log file beforehand by copying the event
/// log to a new file with a `snapshot-{root_hash}` file extension.
///
/// The events on disc and the in-memory merkle tree are then
/// removed before applying the patch in the diff.
///
/// After applying the events if the HEAD of the event log
/// does not match the `checkpoint` in the diff verification
/// fails and an attempt is made to rollback to the snapshot.
///
/// When verification fails an [Error::CheckpointVerification]
/// error will always be returned.
async fn replace_all_events(
&mut self,
diff: &Diff<E>,
) -> Result<(), Self::Error>;
/// Append a patch to this event log.
async fn patch_unchecked(
&mut self,
patch: &Patch<E>,
) -> Result<(), Self::Error>;
/// Diff of event records until a specific commit.
///
/// Searches backwards until it finds the specified commit
/// if given; if no commit is given the diff will include
/// all event records.
///
/// Does not include the target commit.
async fn diff_records(
&self,
commit: Option<&CommitHash>,
) -> Result<Vec<EventRecord>, Self::Error>;
/// Encoding version.
fn version(&self) -> u16;
}