1use crate::ln::Ln;
9
10#[derive(Debug, Clone)]
18pub struct MapLn {
19 ln: Ln,
21 db_id: u64,
23 deleted: bool,
25 is_transient: bool,
27}
28
29impl MapLn {
30 pub fn new(db_id: u64, config_data: Vec<u8>) -> Self {
37 MapLn {
38 ln: Ln::new(Some(config_data)),
39 db_id,
40 deleted: false,
41 is_transient: false,
42 }
43 }
44
45 pub fn get_db_id(&self) -> u64 {
47 self.db_id
48 }
49
50 pub fn is_deleted(&self) -> bool {
52 self.deleted
53 }
54
55 pub fn set_deleted(&mut self, deleted: bool) {
57 self.deleted = deleted;
58 self.ln.set_dirty();
59 }
60
61 pub fn is_transient(&self) -> bool {
63 self.is_transient
64 }
65
66 pub fn set_transient(&mut self, transient: bool) {
68 self.is_transient = transient;
69 self.ln.set_dirty();
70 }
71
72 pub fn get_ln(&self) -> &Ln {
74 &self.ln
75 }
76
77 pub fn get_ln_mut(&mut self) -> &mut Ln {
79 &mut self.ln
80 }
81
82 pub fn log_size(&self) -> usize {
84 self.ln.log_size() + 8 + 1 + 1 }
86
87 pub fn write_to_log(&self, buf: &mut Vec<u8>) {
89 self.ln.write_to_log(buf);
90 buf.extend_from_slice(&self.db_id.to_be_bytes());
91 buf.push(if self.deleted { 1 } else { 0 });
92 buf.push(if self.is_transient { 1 } else { 0 });
93 }
94
95 pub fn read_from_log(buf: &[u8]) -> std::io::Result<Self> {
97 let ln = Ln::read_from_log(buf)?;
98 let ln_size = ln.log_size();
99 let remaining = &buf[ln_size..];
100
101 use byteorder::{BigEndian, ReadBytesExt};
102 use std::io::Cursor;
103 let mut cursor = Cursor::new(remaining);
104 let db_id = cursor.read_u64::<BigEndian>()?;
105 let deleted = cursor.read_u8()? != 0;
106 let is_transient = cursor.read_u8()? != 0;
107
108 Ok(MapLn { ln, db_id, deleted, is_transient })
109 }
110}
111
112impl std::fmt::Display for MapLn {
113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114 write!(
115 f,
116 "<mapln db_id={} deleted={} transient={}>",
117 self.db_id, self.deleted, self.is_transient
118 )
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use noxu_util::Vlsn;
126
127 #[test]
128 fn test_map_ln_new() {
129 let config = b"database config data".to_vec();
130 let map_ln = MapLn::new(42, config.clone());
131
132 assert_eq!(map_ln.get_db_id(), 42);
133 assert!(!map_ln.is_deleted());
134 assert!(!map_ln.is_transient());
135 assert_eq!(map_ln.get_ln().get_data(), Some(config.as_slice()));
136 }
137
138 #[test]
139 fn test_map_ln_roundtrip() {
140 let config = b"test config".to_vec();
141 let mut map_ln = MapLn::new(100, config.clone());
142 map_ln.get_ln_mut().set_vlsn(Vlsn::new(50));
143
144 let mut buf = Vec::new();
145 map_ln.write_to_log(&mut buf);
146
147 let map_ln2 = MapLn::read_from_log(&buf).unwrap();
148
149 assert_eq!(map_ln2.get_db_id(), 100);
150 assert!(!map_ln2.is_deleted());
151 assert!(!map_ln2.is_transient());
152 assert_eq!(map_ln2.get_ln().get_data(), Some(config.as_slice()));
153 assert_eq!(map_ln2.get_ln().get_vlsn().sequence(), 50);
154 }
155
156 #[test]
157 fn test_map_ln_deleted() {
158 let config = b"config".to_vec();
159 let mut map_ln = MapLn::new(200, config);
160
161 assert!(!map_ln.is_deleted());
162
163 map_ln.set_deleted(true);
164 assert!(map_ln.is_deleted());
165 assert!(map_ln.get_ln().is_dirty());
166
167 let mut buf = Vec::new();
169 map_ln.write_to_log(&mut buf);
170
171 let map_ln2 = MapLn::read_from_log(&buf).unwrap();
172
173 assert_eq!(map_ln2.get_db_id(), 200);
174 assert!(map_ln2.is_deleted());
175 assert!(!map_ln2.is_transient());
176 }
177
178 #[test]
179 fn test_map_ln_transient() {
180 let config = b"transient config".to_vec();
181 let mut map_ln = MapLn::new(300, config);
182
183 assert!(!map_ln.is_transient());
184
185 map_ln.set_transient(true);
186 assert!(map_ln.is_transient());
187 assert!(map_ln.get_ln().is_dirty());
188
189 let mut buf = Vec::new();
191 map_ln.write_to_log(&mut buf);
192
193 let map_ln2 = MapLn::read_from_log(&buf).unwrap();
194
195 assert_eq!(map_ln2.get_db_id(), 300);
196 assert!(!map_ln2.is_deleted());
197 assert!(map_ln2.is_transient());
198 }
199
200 #[test]
201 fn test_map_ln_both_flags() {
202 let config = b"config".to_vec();
203 let mut map_ln = MapLn::new(400, config);
204
205 map_ln.set_deleted(true);
206 map_ln.set_transient(true);
207
208 let mut buf = Vec::new();
209 map_ln.write_to_log(&mut buf);
210
211 let map_ln2 = MapLn::read_from_log(&buf).unwrap();
212
213 assert_eq!(map_ln2.get_db_id(), 400);
214 assert!(map_ln2.is_deleted());
215 assert!(map_ln2.is_transient());
216 }
217
218 #[test]
219 fn test_map_ln_log_size() {
220 let config = b"test".to_vec();
221 let map_ln = MapLn::new(500, config);
222
223 let size = map_ln.log_size();
224
225 let mut buf = Vec::new();
226 map_ln.write_to_log(&mut buf);
227
228 assert_eq!(size, buf.len());
229 }
230
231 #[test]
232 fn test_map_ln_display() {
233 let config = b"config".to_vec();
234 let map_ln = MapLn::new(600, config);
235
236 let s = format!("{}", map_ln);
237 assert!(s.contains("db_id=600"));
238 assert!(s.contains("deleted=false"));
239 assert!(s.contains("transient=false"));
240 }
241}