nydus_utils/
lib.rs

1// Copyright 2020 Ant Group. All rights reserved.
2//
3// SPDX-License-Identifier: Apache-2.0
4
5#[macro_use]
6extern crate log;
7#[macro_use]
8extern crate serde;
9#[macro_use]
10extern crate lazy_static;
11#[macro_use]
12extern crate nydus_api;
13
14use std::convert::{Into, TryFrom, TryInto};
15use std::time::Duration;
16
17pub use self::exec::*;
18pub use self::inode_bitmap::InodeBitmap;
19pub use self::reader::*;
20pub use self::types::*;
21
22pub mod async_helper;
23pub mod compact;
24pub mod compress;
25pub mod crc32;
26#[cfg(feature = "encryption")]
27pub mod crypt;
28pub mod digest;
29pub mod exec;
30pub mod filemap;
31pub mod inode_bitmap;
32pub mod logger;
33pub mod metrics;
34pub mod mpmc;
35pub mod reader;
36pub mod trace;
37pub mod types;
38pub mod verity;
39
40/// Round up and divide the value `n` by `d`.
41pub fn div_round_up(n: u64, d: u64) -> u64 {
42    debug_assert!(d != 0);
43    debug_assert!(d.is_power_of_two());
44    n.div_ceil(d)
45}
46
47/// Round up the value `n` to by `d`.
48pub fn round_up(n: u64, d: u64) -> u64 {
49    debug_assert!(d != 0);
50    debug_assert!(d.is_power_of_two());
51    n.div_ceil(d) * d
52}
53
54/// Round up the value `n` to by `d`.
55pub fn round_up_usize(n: usize, d: usize) -> usize {
56    debug_assert!(d != 0);
57    debug_assert!(d.is_power_of_two());
58    n.div_ceil(d) * d
59}
60
61/// Overflow can fail this rounder if the base value is large enough with 4095 added.
62pub fn try_round_up_4k<U: TryFrom<u64>, T: Into<u64>>(x: T) -> Option<U> {
63    let t = 4095u64;
64    if let Some(v) = x.into().checked_add(t) {
65        let z = v & (!t);
66        z.try_into().ok()
67    } else {
68        None
69    }
70}
71
72pub fn round_down_4k(x: u64) -> u64 {
73    x & (!4095u64)
74}
75
76/// Round down the value `n` to by `d`.
77pub fn round_down(n: u64, d: u64) -> u64 {
78    debug_assert!(d != 0);
79    debug_assert!(d.is_power_of_two());
80    n / d * d
81}
82
83pub enum DelayType {
84    Fixed,
85    // an exponential delay between each attempts
86    BackOff,
87}
88
89pub struct Delayer {
90    r#type: DelayType,
91    attempts: u32,
92    time: Duration,
93}
94
95impl Delayer {
96    pub fn new(t: DelayType, time: Duration) -> Self {
97        Delayer {
98            r#type: t,
99            attempts: 0,
100            time,
101        }
102    }
103
104    pub fn delay(&mut self) {
105        use std::thread::sleep;
106
107        match self.r#type {
108            DelayType::Fixed => sleep(self.time),
109            DelayType::BackOff => sleep((1 << self.attempts) * self.time),
110        }
111        self.attempts += 1;
112    }
113}
114
115struct LazyDrop<T> {
116    v: T,
117}
118
119unsafe impl<T> Send for LazyDrop<T> {}
120
121/// Lazy drop of object.
122pub fn lazy_drop<T: 'static>(v: T) {
123    let v = LazyDrop { v };
124    std::thread::spawn(move || {
125        std::thread::sleep(Duration::from_secs(600));
126        let _ = v.v;
127    });
128}
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    #[test]
135    fn test_rounders() {
136        assert_eq!(round_down_4k(0), 0);
137        assert_eq!(round_down_4k(100), 0);
138        assert_eq!(round_down_4k(4300), 4096);
139        assert_eq!(round_down_4k(4096), 4096);
140        assert_eq!(round_down_4k(4095), 0);
141        assert_eq!(round_down_4k(4097), 4096);
142        assert_eq!(round_down_4k(u64::MAX - 1), u64::MAX - 4095);
143        assert_eq!(round_down_4k(u64::MAX - 4095), u64::MAX - 4095);
144        // zero is rounded up to zero
145        assert_eq!(try_round_up_4k::<i32, _>(0u32), Some(0i32));
146        assert_eq!(try_round_up_4k::<u32, _>(0u32), Some(0u32));
147        assert_eq!(try_round_up_4k::<u32, _>(1u32), Some(4096u32));
148        assert_eq!(try_round_up_4k::<u32, _>(100u32), Some(4096u32));
149        assert_eq!(try_round_up_4k::<u32, _>(4100u32), Some(8192u32));
150        assert_eq!(try_round_up_4k::<u32, _>(4096u32), Some(4096u32));
151        assert_eq!(try_round_up_4k::<u32, _>(4095u32), Some(4096u32));
152        assert_eq!(try_round_up_4k::<u32, _>(4097u32), Some(8192u32));
153        assert_eq!(try_round_up_4k::<u32, _>(u32::MAX), None);
154        assert_eq!(try_round_up_4k::<u64, _>(u32::MAX), Some(0x1_0000_0000u64));
155        assert_eq!(try_round_up_4k::<u32, _>(u64::MAX - 1), None);
156        assert_eq!(try_round_up_4k::<u32, _>(u64::MAX), None);
157        assert_eq!(try_round_up_4k::<u32, _>(u64::MAX - 4097), None);
158        // success
159        assert_eq!(
160            try_round_up_4k::<u64, _>(u64::MAX - 4096),
161            Some(u64::MAX - 4095)
162        );
163        // overflow
164        assert_eq!(try_round_up_4k::<u64, _>(u64::MAX - 1), None);
165        // fail to convert u64 to u32
166        assert_eq!(try_round_up_4k::<u32, _>(u64::MAX - 4096), None);
167    }
168
169    #[test]
170    fn test_round_up_usize() {
171        assert_eq!(round_up_usize(10, 8), 16);
172        assert_eq!(round_up_usize(100, 8), 104);
173        assert_eq!(round_up_usize(1000, 8), 1000);
174    }
175}