1use crate::checksum::{Checksums, ChecksumsV38};
8use bit_vec::BitVec;
9use fprint::TypeFingerprint;
10use serde::{Deserialize, Serialize};
11
12pub type ExtentMode = ExtentModeV38;
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, TypeFingerprint)]
16pub enum ExtentModeV38 {
17 Raw,
21 Cow(ChecksumsV38),
24 OverwritePartial(BitVec),
29 Overwrite,
33}
34
35#[cfg(fuzz)]
36impl<'a> arbitrary::Arbitrary<'a> for ExtentMode {
37 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
38 Ok(match u.int_in_range(0..=3)? {
39 0 => ExtentMode::Raw,
40 1 => ExtentMode::Cow(u.arbitrary()?),
41 2 => ExtentMode::OverwritePartial(BitVec::from_bytes(u.arbitrary()?)),
42 3 => ExtentMode::Overwrite,
43 _ => unreachable!(),
44 })
45 }
46}
47
48pub type ExtentValue = ExtentValueV38;
51
52#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, TypeFingerprint)]
53#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
54pub enum ExtentValueV38 {
55 None,
58 Some { device_offset: u64, mode: ExtentModeV38, key_id: u64 },
62}
63
64impl ExtentValue {
65 pub fn new(device_offset: u64, mode: ExtentMode, key_id: u64) -> ExtentValue {
66 ExtentValue::Some { device_offset, mode, key_id }
67 }
68
69 pub fn new_raw(device_offset: u64, key_id: u64) -> ExtentValue {
70 Self::new(device_offset, ExtentMode::Raw, key_id)
71 }
72
73 pub fn with_checksum(device_offset: u64, checksums: Checksums, key_id: u64) -> ExtentValue {
75 Self::new(device_offset, ExtentMode::Cow(checksums), key_id)
76 }
77
78 pub fn blank_overwrite_extent(
80 device_offset: u64,
81 num_blocks: usize,
82 key_id: u64,
83 ) -> ExtentValue {
84 Self::new(
85 device_offset,
86 ExtentMode::OverwritePartial(BitVec::from_elem(num_blocks, false)),
87 key_id,
88 )
89 }
90
91 pub fn initialized_overwrite_extent(device_offset: u64, key_id: u64) -> ExtentValue {
93 Self::new(device_offset, ExtentMode::Overwrite, key_id)
94 }
95
96 pub fn deleted_extent() -> ExtentValue {
98 ExtentValue::None
99 }
100
101 pub fn is_deleted(&self) -> bool {
102 if let ExtentValue::None = self { true } else { false }
103 }
104
105 pub fn offset_by(&self, amount: u64, extent_len: u64) -> Self {
108 match self {
109 ExtentValue::None => Self::deleted_extent(),
110 ExtentValue::Some { device_offset, mode, key_id } => {
111 let mode = match mode {
112 ExtentMode::Raw => ExtentMode::Raw,
113 ExtentMode::Cow(checksums) => {
114 if checksums.len() > 0 {
115 let index = (amount / (extent_len / checksums.len() as u64)) as usize;
116 ExtentMode::Cow(checksums.offset_by(index))
117 } else {
118 ExtentMode::Cow(Checksums::fletcher(Vec::new()))
119 }
120 }
121 ExtentMode::Overwrite => ExtentMode::Overwrite,
122 ExtentMode::OverwritePartial(bitmap) => {
123 debug_assert!(bitmap.len() > 0);
124 let index = (amount / (extent_len / bitmap.len() as u64)) as usize;
125 ExtentMode::OverwritePartial(bitmap.clone().split_off(index))
126 }
127 };
128 ExtentValue::Some { device_offset: device_offset + amount, mode, key_id: *key_id }
129 }
130 }
131 }
132
133 pub fn shrunk(&self, original_len: u64, new_len: u64) -> Self {
135 match self {
136 ExtentValue::None => Self::deleted_extent(),
137 ExtentValue::Some { device_offset, mode, key_id } => {
138 let mode = match mode {
139 ExtentMode::Raw => ExtentMode::Raw,
140 ExtentMode::Cow(checksums) => {
141 if checksums.len() > 0 {
142 let len = (new_len / (original_len / checksums.len() as u64)) as usize;
143 ExtentMode::Cow(checksums.shrunk(len))
144 } else {
145 ExtentMode::Cow(Checksums::fletcher(Vec::new()))
146 }
147 }
148 ExtentMode::Overwrite => ExtentMode::Overwrite,
149 ExtentMode::OverwritePartial(bitmap) => {
150 debug_assert!(bitmap.len() > 0);
151 let len = (new_len / (original_len / bitmap.len() as u64)) as usize;
152 let mut new_bitmap = bitmap.clone();
153 new_bitmap.truncate(len);
154 ExtentMode::OverwritePartial(new_bitmap)
155 }
156 };
157 ExtentValue::Some { device_offset: *device_offset, mode, key_id: *key_id }
158 }
159 }
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::{ExtentMode, ExtentValue};
166 use crate::checksum::Checksums;
167 use crate::object_store::VOLUME_DATA_KEY_ID;
168 use bit_vec::BitVec;
169
170 #[test]
171 fn extent_value_offset_by() {
172 assert_eq!(ExtentValue::None.offset_by(1024, 2048), ExtentValue::None);
173 assert_eq!(
174 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).offset_by(0, 2048),
175 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
176 );
177 assert_eq!(
178 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).offset_by(1024, 2048),
179 ExtentValue::new_raw(2048, VOLUME_DATA_KEY_ID)
180 );
181 assert_eq!(
182 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).offset_by(2048, 2048),
183 ExtentValue::new_raw(3072, VOLUME_DATA_KEY_ID)
184 );
185
186 let make_checksums = |range: std::ops::Range<u64>| Checksums::fletcher(range.collect());
187
188 assert_eq!(
190 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
191 .offset_by(0, 2048),
192 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
193 );
194 assert_eq!(
195 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
196 .offset_by(1024, 2048),
197 ExtentValue::with_checksum(2048, make_checksums(4..8), VOLUME_DATA_KEY_ID)
198 );
199 assert_eq!(
200 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
201 .offset_by(2048, 2048),
202 ExtentValue::with_checksum(3072, Checksums::fletcher(Vec::new()), VOLUME_DATA_KEY_ID)
203 );
204
205 let make_bitmap = |cut, length| {
208 let mut begin_bitmap = BitVec::from_elem(cut, false);
209 let mut end_bitmap = BitVec::from_elem(length - cut, true);
210 begin_bitmap.append(&mut end_bitmap);
211 ExtentMode::OverwritePartial(begin_bitmap)
212 };
213 let make_extent =
214 |device_offset, mode| ExtentValue::Some { device_offset, mode, key_id: 0 };
215
216 assert_eq!(
217 make_extent(1024, make_bitmap(1, 8)).offset_by(0, 2048),
218 make_extent(1024, make_bitmap(1, 8))
219 );
220 assert_eq!(
221 make_extent(1024, make_bitmap(5, 8)).offset_by(1024, 2048),
222 make_extent(2048, make_bitmap(1, 4))
223 );
224 assert_eq!(
225 make_extent(1024, make_bitmap(0, 8)).offset_by(2048, 2048),
226 make_extent(3072, ExtentMode::OverwritePartial(BitVec::new()))
227 );
228
229 assert_eq!(
230 make_extent(1024, ExtentMode::Overwrite).offset_by(0, 2048),
231 make_extent(1024, ExtentMode::Overwrite)
232 );
233 assert_eq!(
234 make_extent(1024, ExtentMode::Overwrite).offset_by(1024, 2048),
235 make_extent(2048, ExtentMode::Overwrite)
236 );
237 assert_eq!(
238 make_extent(1024, ExtentMode::Overwrite).offset_by(2048, 2048),
239 make_extent(3072, ExtentMode::Overwrite)
240 );
241 }
242
243 #[test]
244 fn extent_value_shrunk() {
245 assert_eq!(ExtentValue::None.shrunk(2048, 1024), ExtentValue::None);
246 assert_eq!(
247 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).shrunk(2048, 2048),
248 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
249 );
250 assert_eq!(
251 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).shrunk(2048, 1024),
252 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
253 );
254 assert_eq!(
255 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).shrunk(2048, 0),
256 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
257 );
258
259 let make_checksums = |range: std::ops::Range<u64>| Checksums::fletcher(range.collect());
260
261 assert_eq!(
263 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
264 .shrunk(2048, 2048),
265 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
266 );
267 assert_eq!(
268 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
269 .shrunk(2048, 1024),
270 ExtentValue::with_checksum(1024, make_checksums(0..4), VOLUME_DATA_KEY_ID)
271 );
272 assert_eq!(
273 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
274 .shrunk(2048, 0),
275 ExtentValue::with_checksum(1024, Checksums::fletcher(Vec::new()), VOLUME_DATA_KEY_ID)
276 );
277
278 let make_bitmap = |cut, length| {
281 let mut begin_bitmap = BitVec::from_elem(cut, false);
282 let mut end_bitmap = BitVec::from_elem(length - cut, true);
283 begin_bitmap.append(&mut end_bitmap);
284 ExtentMode::OverwritePartial(begin_bitmap)
285 };
286 let make_extent =
287 |device_offset, mode| ExtentValue::Some { device_offset, mode, key_id: 0 };
288
289 assert_eq!(
290 make_extent(1024, make_bitmap(1, 8)).shrunk(2048, 2048),
291 make_extent(1024, make_bitmap(1, 8))
292 );
293 assert_eq!(
294 make_extent(1024, make_bitmap(3, 8)).shrunk(2048, 1024),
295 make_extent(1024, make_bitmap(3, 4))
296 );
297 assert_eq!(
298 make_extent(1024, make_bitmap(0, 8)).shrunk(2048, 0),
299 make_extent(1024, ExtentMode::OverwritePartial(BitVec::new()))
300 );
301
302 assert_eq!(
303 make_extent(1024, ExtentMode::Overwrite).shrunk(2048, 2048),
304 make_extent(1024, ExtentMode::Overwrite)
305 );
306 assert_eq!(
307 make_extent(1024, ExtentMode::Overwrite).shrunk(2048, 1024),
308 make_extent(1024, ExtentMode::Overwrite)
309 );
310 assert_eq!(
311 make_extent(1024, ExtentMode::Overwrite).shrunk(2048, 0),
312 make_extent(1024, ExtentMode::Overwrite)
313 );
314 }
315}