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