mmap_sync/
instance.rs

1use std::ffi::{OsStr, OsString};
2
3use crate::synchronizer::SynchronizerError;
4use crate::synchronizer::SynchronizerError::*;
5
6/// `InstanceVersion` represents data instance and consists of the following components:
7/// - data idx (0 or 1)   - 1 bit
8/// - data size (<549 GB) - 39 bits
9/// - data checksum       - 24 bits
10#[derive(Clone, Copy, Debug, PartialEq)]
11pub struct InstanceVersion(pub(crate) u64);
12
13const DATA_SIZE_BITS: usize = 39;
14const DATA_CHECKSUM_BITS: usize = 24;
15
16impl InstanceVersion {
17    /// Create new `InstanceVersion` from data instance `idx`, `size` and `checksum`
18    #[inline]
19    pub(crate) fn new(
20        idx: usize,
21        size: usize,
22        checksum: u64,
23    ) -> Result<InstanceVersion, SynchronizerError> {
24        let mut res: u64 = 0;
25
26        if idx > 1 || size >= 1 << DATA_SIZE_BITS {
27            return Err(InvalidInstanceVersionParams);
28        }
29
30        res |= (idx as u64) & 1;
31        res |= ((size as u64) & ((1 << DATA_SIZE_BITS) - 1)) << 1;
32        res |= (checksum & ((1 << DATA_CHECKSUM_BITS) - 1)) << (DATA_SIZE_BITS + 1);
33
34        Ok(InstanceVersion(res))
35    }
36
37    /// Get data instance `idx` (0 or 1)
38    #[inline]
39    pub(crate) fn idx(&self) -> usize {
40        self.0 as usize & 1
41    }
42
43    /// Get data instance `size`
44    #[inline]
45    pub(crate) fn size(&self) -> usize {
46        (self.0 as usize >> 1) & ((1 << DATA_SIZE_BITS) - 1)
47    }
48
49    /// Get data instance `checksum`
50    #[cfg(test)]
51    pub(crate) fn checksum(&self) -> u64 {
52        self.0 >> (DATA_SIZE_BITS + 1)
53    }
54
55    /// Get data instance `path`
56    #[inline]
57    pub(crate) fn path(&self, path_prefix: &OsStr) -> OsString {
58        let mut path = path_prefix.to_os_string();
59        path.push(format!("_data_{}", self.idx()));
60        path
61    }
62}
63
64impl TryFrom<u64> for InstanceVersion {
65    type Error = SynchronizerError;
66
67    /// Convert from `u64` to `InstanceVersion`
68    #[inline]
69    fn try_from(v: u64) -> Result<InstanceVersion, Self::Error> {
70        if v == 0 {
71            Err(UninitializedState)
72        } else {
73            Ok(InstanceVersion(v))
74        }
75    }
76}
77
78impl From<InstanceVersion> for u64 {
79    /// Convert from `InstanceVersion` to `u64`
80    #[inline]
81    fn from(v: InstanceVersion) -> Self {
82        v.0
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use crate::instance::*;
89    use proptest::prelude::*;
90
91    proptest! {
92        #[test]
93        fn test_new(idx in 0..2usize, size in 0..1usize << DATA_SIZE_BITS, checksum in 0..u64::MAX) {
94            let v = InstanceVersion::new(idx, size, checksum).unwrap();
95
96            assert_eq!(idx, v.idx());
97            assert_eq!(size, v.size());
98            assert_eq!(checksum & ((1 << DATA_CHECKSUM_BITS) - 1), v.checksum());
99        }
100    }
101}