stacks_common/util/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation
// Copyright (C) 2020 Stacks Open Internet Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#[macro_use]
pub mod log;
#[macro_use]
pub mod macros;
pub mod chunked_encoding;
pub mod hash;
pub mod pair;
pub mod pipe;
pub mod retry;
pub mod secp256k1;
pub mod uint;
#[cfg(feature = "vrf")]
pub mod vrf;

use std::time::{SystemTime, UNIX_EPOCH};
use std::{error, fmt, thread, time};

pub fn get_epoch_time_secs() -> u64 {
    let start = SystemTime::now();
    let since_the_epoch = start
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");
    since_the_epoch.as_secs()
}

pub fn get_epoch_time_ms() -> u128 {
    let start = SystemTime::now();
    let since_the_epoch = start
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");
    since_the_epoch.as_millis()
}

pub fn sleep_ms(millis: u64) {
    let t = time::Duration::from_millis(millis);
    thread::sleep(t);
}

/// Hex deserialization error
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum HexError {
    /// Length was not 64 characters
    BadLength(usize),
    /// Non-hex character in string
    BadCharacter(char),
}

impl fmt::Display for HexError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            HexError::BadLength(n) => write!(f, "bad length {} for hex string", n),
            HexError::BadCharacter(c) => write!(f, "bad character {} for hex string", c),
        }
    }
}

impl error::Error for HexError {
    fn cause(&self) -> Option<&dyn error::Error> {
        None
    }
    fn description(&self) -> &str {
        match *self {
            HexError::BadLength(_) => "hex string non-64 length",
            HexError::BadCharacter(_) => "bad hex character",
        }
    }
}

/// PartialEq helper method for slices of arbitrary length.
pub fn slice_partialeq<T: PartialEq>(s1: &[T], s2: &[T]) -> bool {
    if s1.len() != s2.len() {
        return false;
    }
    for i in 0..s1.len() {
        if s1[i] != s2[i] {
            return false;
        }
    }
    true
}

pub mod db_common {
    use std::{thread, time};

    use rand::{thread_rng, Rng};

    pub fn tx_busy_handler(run_count: i32) -> bool {
        let mut sleep_count = 10;
        if run_count > 0 {
            sleep_count = 2u64.saturating_pow(run_count as u32);
        }
        sleep_count = sleep_count.saturating_add(thread_rng().gen::<u64>() % sleep_count);

        if sleep_count > 5000 {
            sleep_count = 5000;
        }

        crate::debug!(
            "Database is locked; sleeping {}ms and trying again",
            &sleep_count
        );

        thread::sleep(time::Duration::from_millis(sleep_count));
        true
    }
}