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
use super::*;
pub struct Reservation<'a> {
pub(super) iobufs: &'a IoBufs,
pub(super) idx: usize,
pub(super) data: Vec<u8>,
pub(super) destination: &'a mut [u8],
pub(super) flushed: bool,
pub(super) lsn: Lsn,
pub(super) lid: LogID,
}
impl<'a> Drop for Reservation<'a> {
fn drop(&mut self) {
let should_flush = !self.data.is_empty() && !self.flushed;
if should_flush {
self.flush(false).unwrap();
}
}
}
impl<'a> Reservation<'a> {
pub fn abort(mut self) -> CacheResult<(Lsn, LogID), ()> {
self.flush(false)
}
pub fn complete(mut self) -> CacheResult<(Lsn, LogID), ()> {
self.flush(true)
}
pub fn lid(&self) -> LogID {
self.lid
}
pub fn lsn(&self) -> Lsn {
self.lsn
}
fn flush(&mut self, valid: bool) -> CacheResult<(Lsn, LogID), ()> {
if self.flushed {
panic!("flushing already-flushed reservation!");
}
self.flushed = true;
if !valid {
self.data[0] = FAILED_FLUSH;
}
self.destination.copy_from_slice(&*self.data);
self.iobufs.exit_reservation(self.idx)?;
Ok((self.lsn(), self.lid()))
}
}