Skip to content

Commit 99a917e

Browse files
sandreimAlexandra Iordache
authored and
Alexandra Iordache
committed
Refactor versionize::Error and array serializer.
- Implemented VersionizeResult. - Split versionize::Error into snapshot::Error and versionize:Error - Implement bincode compatible array serialization. - Add test for bincode compatibility. Signed-off-by: Andrei Sandu <[email protected]>
1 parent ee49525 commit 99a917e

File tree

11 files changed

+254
-127
lines changed

11 files changed

+254
-127
lines changed

src/snapshot/benches/basic.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ extern crate versionize_derive;
55

66
use criterion::{black_box, criterion_group, criterion_main, Criterion};
77
use snapshot::Snapshot;
8-
use versionize::{Error, Result, VersionMap, Versionize};
8+
use versionize::{Error, VersionMap, Versionize, VersionizeResult};
99
use versionize_derive::Versionize;
1010

1111
#[derive(Clone, Debug, Default, Versionize)]
@@ -49,7 +49,7 @@ impl Test {
4949
vec![1, 2, 3, 4]
5050
}
5151

52-
fn field4_serialize(&mut self, target_version: u16) -> Result<()> {
52+
fn field4_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
5353
// Fail if semantic serialization is called for the latest version.
5454
assert_ne!(target_version, Test::version());
5555
self.field0 = self.field4.iter().sum();
@@ -60,21 +60,21 @@ impl Test {
6060
Ok(())
6161
}
6262

63-
fn field4_deserialize(&mut self, source_version: u16) -> Result<()> {
63+
fn field4_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
6464
// Fail if semantic deserialization is called for the latest version.
6565
assert_ne!(source_version, Test::version());
6666
self.field4 = vec![self.field0; 4];
6767
Ok(())
6868
}
6969

70-
fn field3_serialize(&mut self, target_version: u16) -> Result<()> {
70+
fn field3_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
7171
// Fail if semantic serialization is called for the previous versions only.
7272
assert!(target_version < 3);
7373
self.field_x += 1;
7474
Ok(())
7575
}
7676

77-
fn field3_deserialize(&mut self, source_version: u16) -> Result<()> {
77+
fn field3_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
7878
// Fail if semantic deserialization is called for the latest version.
7979
assert!(source_version < 3);
8080
self.field_x += 1;

src/snapshot/src/lib.rs

+99-46
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ extern crate versionize_derive;
4242
use std::collections::hash_map::HashMap;
4343
use std::io::Read;
4444
use versionize::crc::{CRC64Reader, CRC64Writer};
45-
use versionize::{Error, Result, VersionMap, Versionize};
45+
use versionize::{VersionMap, Versionize, VersionizeResult};
4646
use versionize_derive::Versionize;
4747

48-
// 256k max section size.
49-
const SNAPSHOT_MAX_SECTION_SIZE: usize = 0x40000;
48+
// 128k max section size.
49+
const SNAPSHOT_MAX_SECTION_SIZE: usize = 0x20000;
5050
const SNAPSHOT_FORMAT_VERSION: u16 = 1;
5151
const BASE_MAGIC_ID_MASK: u64 = !0xFFFFu64;
5252

@@ -56,6 +56,21 @@ const BASE_MAGIC_ID: u64 = 0x0710_1984_8664_0000u64;
5656
#[cfg(target_arch = "aarch64")]
5757
const BASE_MAGIC_ID: u64 = 0x0710_1984_AAAA_0000u64;
5858

59+
/// Error definitions for the Snapshot API.
60+
#[derive(Debug, PartialEq)]
61+
pub enum Error {
62+
/// An IO error occured.
63+
Io(i32),
64+
/// A versioned serialization/deserialization error occured.
65+
Versionize(versionize::Error),
66+
/// CRC64 validation failed.
67+
Crc64(u64),
68+
/// Magic value does not match arch.
69+
InvalidMagic(u64),
70+
/// Section does not exist.
71+
SectionNotFound,
72+
}
73+
5974
#[derive(Default, Debug, Versionize)]
6075
struct SnapshotHdr {
6176
/// Snapshot data version (firecracker version).
@@ -83,7 +98,7 @@ struct Section {
8398
}
8499

85100
// Parse a magic_id and return the format version.
86-
fn get_format_version(magic_id: u64) -> Result<u16> {
101+
fn get_format_version(magic_id: u64) -> Result<u16, Error> {
87102
let magic_arch = magic_id & BASE_MAGIC_ID_MASK;
88103
if magic_arch == BASE_MAGIC_ID {
89104
return Ok((magic_id & !BASE_MAGIC_ID_MASK) as u16);
@@ -108,23 +123,24 @@ impl Snapshot {
108123
}
109124

110125
/// Attempts to load an existing snapshot.
111-
pub fn load<T>(mut reader: &mut T, version_map: VersionMap) -> Result<Snapshot>
126+
pub fn load<T>(mut reader: &mut T, version_map: VersionMap) -> Result<Snapshot, Error>
112127
where
113128
T: Read,
114129
{
115130
let format_version_map = Self::format_version_map();
116-
let magic_id = <u64 as Versionize>::deserialize(
117-
&mut reader,
118-
&format_version_map,
119-
0, /* unused */
120-
)?;
121-
let format_version = get_format_version(magic_id).unwrap();
131+
let magic_id =
132+
<u64 as Versionize>::deserialize(&mut reader, &format_version_map, 0 /* unused */)
133+
.map_err(Error::Versionize)?;
134+
135+
let format_version = get_format_version(magic_id)?;
122136
let hdr: SnapshotHdr =
123-
SnapshotHdr::deserialize(&mut reader, &format_version_map, format_version)?;
137+
SnapshotHdr::deserialize(&mut reader, &format_version_map, format_version)
138+
.map_err(Error::Versionize)?;
124139
let mut sections = HashMap::new();
125140

126141
for _ in 0..hdr.section_count {
127-
let section = Section::deserialize(&mut reader, &format_version_map, format_version)?;
142+
let section = Section::deserialize(&mut reader, &format_version_map, format_version)
143+
.map_err(Error::Versionize)?;
128144
sections.insert(section.name.clone(), section);
129145
}
130146

@@ -139,7 +155,7 @@ impl Snapshot {
139155
}
140156

141157
/// Attempts to load an existing snapshot and validate CRC.
142-
pub fn load_with_crc64<T>(reader: &mut T, version_map: VersionMap) -> Result<Snapshot>
158+
pub fn load_with_crc64<T>(reader: &mut T, version_map: VersionMap) -> Result<Snapshot, Error>
143159
where
144160
T: Read,
145161
{
@@ -151,7 +167,8 @@ impl Snapshot {
151167
// Since the reader updates the checksum as bytes ar being read from it, the order of these 2 statements is
152168
// important, we first get the checksum computed on the read bytes then read the stored checksum.
153169
let computed_checksum = crc_reader.checksum();
154-
let stored_checksum: u64 = Versionize::deserialize(&mut crc_reader, &format_vm, 0)?;
170+
let stored_checksum: u64 =
171+
Versionize::deserialize(&mut crc_reader, &format_vm, 0).map_err(Error::Versionize)?;
155172

156173
if computed_checksum != stored_checksum {
157174
return Err(Error::Crc64(computed_checksum));
@@ -161,20 +178,22 @@ impl Snapshot {
161178
}
162179

163180
/// Saves a snapshot and include a CRC64 checksum.
164-
pub fn save_with_crc64<T>(&mut self, writer: &mut T) -> Result<()>
181+
pub fn save_with_crc64<T>(&mut self, writer: &mut T) -> Result<(), Error>
165182
where
166183
T: std::io::Write,
167184
{
168185
let mut crc_writer = CRC64Writer::new(writer);
169186
self.save(&mut crc_writer)?;
170187

171188
let checksum = crc_writer.checksum();
172-
checksum.serialize(&mut crc_writer, &Self::format_version_map(), 0)?;
189+
checksum
190+
.serialize(&mut crc_writer, &Self::format_version_map(), 0)
191+
.map_err(Error::Versionize)?;
173192
Ok(())
174193
}
175194

176195
/// Save a snapshot.
177-
pub fn save<T>(&mut self, mut writer: &mut T) -> Result<()>
196+
pub fn save<T>(&mut self, mut writer: &mut T) -> Result<(), Error>
178197
where
179198
T: std::io::Write,
180199
{
@@ -187,23 +206,30 @@ impl Snapshot {
187206
let magic_id = build_magic_id(format_version_map.latest_version());
188207

189208
// Serialize magic id using the format version map.
190-
magic_id.serialize(&mut writer, &format_version_map, 0 /* unused */)?;
209+
magic_id
210+
.serialize(&mut writer, &format_version_map, 0 /* unused */)
211+
.map_err(Error::Versionize)?;
191212
// Serialize header using the format version map.
192-
self.hdr.serialize(
193-
&mut writer,
194-
&format_version_map,
195-
format_version_map.latest_version(),
196-
)?;
213+
self.hdr
214+
.serialize(
215+
&mut writer,
216+
&format_version_map,
217+
format_version_map.latest_version(),
218+
)
219+
.map_err(Error::Versionize)?;
197220

198221
// Serialize all the sections.
199222
for section in self.sections.values() {
200223
// The sections are already serialized.
201-
section.serialize(
202-
&mut writer,
203-
&format_version_map,
204-
format_version_map.latest_version(),
205-
)?;
224+
section
225+
.serialize(
226+
&mut writer,
227+
&format_version_map,
228+
format_version_map.latest_version(),
229+
)
230+
.map_err(Error::Versionize)?;
206231
}
232+
207233
writer
208234
.flush()
209235
.map_err(|ref err| Error::Io(err.raw_os_error().unwrap_or(0)))?;
@@ -212,7 +238,7 @@ impl Snapshot {
212238
}
213239

214240
/// Attempts to find and reads a section (deserialize/translate) from a snapshot.
215-
pub fn read_section<T>(&mut self, name: &str) -> Result<T>
241+
pub fn read_section<T>(&mut self, name: &str) -> Result<T, Error>
216242
where
217243
T: Versionize,
218244
{
@@ -221,14 +247,15 @@ impl Snapshot {
221247
&mut section.data.as_mut_slice().as_ref(),
222248
&self.version_map,
223249
self.hdr.data_version,
224-
)?)
250+
)
251+
.map_err(Error::Versionize)?)
225252
} else {
226253
Err(Error::SectionNotFound)
227254
}
228255
}
229256

230257
/// Write a section (serialize/translate) to a snapshot.
231-
pub fn write_section<T>(&mut self, name: &str, object: &T) -> Result<usize>
258+
pub fn write_section<T>(&mut self, name: &str, object: &T) -> Result<usize, Error>
232259
where
233260
T: Versionize,
234261
{
@@ -238,7 +265,9 @@ impl Snapshot {
238265
};
239266

240267
let slice = &mut new_section.data.as_mut_slice();
241-
object.serialize(slice, &self.version_map, self.target_version)?;
268+
object
269+
.serialize(slice, &self.version_map, self.target_version)
270+
.map_err(Error::Versionize)?;
242271
// Resize vec to serialized section len.
243272
let serialized_len =
244273
slice.as_ptr() as usize - new_section.data.as_slice().as_ptr() as usize;
@@ -305,36 +334,38 @@ mod tests {
305334
fn field4_default(_: u16) -> Vec<u64> {
306335
vec![1, 2, 3, 4]
307336
}
308-
fn field4_serialize(&mut self, target_version: u16) -> Result<()> {
337+
fn field4_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
309338
// Fail if semantic serialization is called for the latest version.
310339
assert_ne!(target_version, Test::version());
311340
self.field0 = self.field4.iter().sum();
312341

313342
if self.field0 == 6666 {
314-
return Err(Error::Semantic("field4 element sum is 6666".to_owned()));
343+
return Err(versionize::Error::Semantic(
344+
"field4 element sum is 6666".to_owned(),
345+
));
315346
}
316347
Ok(())
317348
}
318-
fn field4_deserialize(&mut self, source_version: u16) -> Result<()> {
349+
fn field4_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
319350
// Fail if semantic deserialization is called for the latest version.
320351
assert_ne!(source_version, Test::version());
321352
self.field4 = vec![self.field0; 4];
322353
Ok(())
323354
}
324355

325-
fn field3_serialize(&mut self, target_version: u16) -> Result<()> {
356+
fn field3_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
326357
// Fail if semantic serialization is called for the previous versions only.
327358
assert!(target_version < 3);
328359
self.field_x += 1;
329360
Ok(())
330361
}
331362

332-
fn field3_deserialize(&mut self, source_version: u16) -> Result<()> {
363+
fn field3_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
333364
// Fail if semantic deserialization is called for the latest version.
334365
assert!(source_version < 3);
335366
self.field_x += 1;
336367
if self.field0 == 7777 {
337-
return Err(Error::Semantic("field0 is 7777".to_owned()));
368+
return Err(versionize::Error::Semantic("field0 is 7777".to_owned()));
338369
}
339370
Ok(())
340371
}
@@ -426,7 +457,9 @@ mod tests {
426457
// The section will fail due to a custom semantic error.
427458
assert_eq!(
428459
snapshot.write_section("test", &state),
429-
Err(Error::Semantic("field4 element sum is 6666".to_owned()))
460+
Err(Error::Versionize(versionize::Error::Semantic(
461+
"field4 element sum is 6666".to_owned()
462+
)))
430463
);
431464
}
432465

@@ -461,7 +494,7 @@ mod tests {
461494
let section_read_error = snapshot.read_section::<Test>("test").unwrap_err();
462495
assert_eq!(
463496
section_read_error,
464-
Error::Semantic("field0 is 7777".to_owned())
497+
Error::Versionize(versionize::Error::Semantic("field0 is 7777".to_owned()))
465498
);
466499
}
467500

@@ -482,13 +515,33 @@ mod tests {
482515
assert!(snapshot.write_section("test", &state_1).is_ok());
483516
assert_eq!(
484517
snapshot.save(&mut snapshot_mem.as_mut_slice()).unwrap_err(),
485-
Error::Serialize(
518+
Error::Versionize(versionize::Error::Serialize(
486519
"Io(Custom { kind: WriteZero, error: \"failed to write whole buffer\" })"
487520
.to_owned()
488-
)
521+
))
489522
);
490523
}
491524

525+
#[test]
526+
fn test_read_invalid_section() {
527+
let vm = VersionMap::new();
528+
let state = Test1 {
529+
field_x: 0,
530+
field0: 0,
531+
field1: 1,
532+
};
533+
534+
let mut snapshot_mem = vec![0u8; 1024];
535+
536+
let mut snapshot = Snapshot::new(vm.clone(), 1);
537+
assert!(snapshot.write_section("test", &state).is_ok());
538+
assert_eq!(snapshot.save(&mut snapshot_mem.as_mut_slice()), Ok(()));
539+
540+
snapshot = Snapshot::load(&mut snapshot_mem.as_slice(), vm.clone()).unwrap();
541+
let section_read_error = snapshot.read_section::<Test>("404").unwrap_err();
542+
assert_eq!(section_read_error, Error::SectionNotFound);
543+
}
544+
492545
#[test]
493546
fn test_crc_ok() {
494547
let vm = VersionMap::new();
@@ -571,10 +624,10 @@ mod tests {
571624
Snapshot::load(&mut snapshot_mem.as_slice(), vm.clone()).unwrap_err();
572625
assert_eq!(
573626
snapshot_load_error,
574-
Error::Deserialize(
627+
Error::Versionize(versionize::Error::Deserialize(
575628
"Io(Custom { kind: UnexpectedEof, error: \"failed to fill whole buffer\" })"
576629
.to_owned()
577-
)
630+
))
578631
);
579632
}
580633

@@ -796,7 +849,7 @@ mod tests {
796849
"whatever".to_owned()
797850
}
798851

799-
fn semantic_x(&mut self, _target_version: u16) -> Result<()> {
852+
fn semantic_x(&mut self, _target_version: u16) -> VersionizeResult<()> {
800853
self.x = self.q as u32;
801854
Ok(())
802855
}

0 commit comments

Comments
 (0)