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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};
use rbatis::rbatis::Rbatis;
use crate::worker::worker_assigner;
use crate::bits_allocator;
use crate::config::rid_config;
pub struct UidGenerator {
bits_allocator: bits_allocator::BitsAllocator,
config: rid_config::UidConfig,
worker_id: i64,
last_second: Arc<Mutex<i64>>,
sequence : i64,
}
impl UidGenerator {
pub async fn new(config: &rid_config::UidConfig, rb: Arc<Rbatis>) -> Self {
let new_config = config.clone();
let id_assigner = worker_assigner::Assigner::new(
new_config.port.clone(),
Arc::clone(&rb)
);
let allocator = bits_allocator::BitsAllocator::new(
config.time_bits,
config.worker_bits,
config.seq_bits
);
let mut worker_id = id_assigner.assign_worker_id().await;
if worker_id > allocator.max_worker_id {
worker_id = worker_id % allocator.max_worker_id
}
return UidGenerator {
bits_allocator: allocator,
config: new_config,
worker_id,
last_second: Arc::new(Mutex::new(0)),
sequence: 0,
}
}
pub fn get_uid(& mut self) -> i64 {
let c = &self.config;
return self.next_id(c.epoch_seconds, c.max_backward_seconds,c.enable_backward);
}
pub fn parse_uid(&self, uid: i64) -> String {
let total_bits = bits_allocator::TOTAL_BITS;
let sign_bits = self.bits_allocator.sign_bits;
let timestamp_bits = self.bits_allocator.timestamp_bits;
let worker_id_bits = self.bits_allocator.worker_id_bits;
let sequence_bits = self.bits_allocator.sequence_bits;
let allocate_total_bits = self.bits_allocator.allocate_total_bits;
let sequence = (uid << (total_bits - sequence_bits)) >> (total_bits - sequence_bits);
let worker_id = (uid << (timestamp_bits + sign_bits + total_bits - allocate_total_bits))
>> (total_bits - worker_id_bits);
let delta_seconds = uid >> (worker_id_bits + sequence_bits);
return format!(
r#"{{\"uid\":\"{}\",\"timestamp\":\"{}\",\"worker_id\":\"{}\",\"sequence\":\"{}\"}}"#,
uid, self.config.epoch_seconds + delta_seconds, worker_id, sequence
);
}
fn next_id(
& mut self,
epoch_seconds: i64,
max_backward_seconds: i64,
enable_backward: bool
) -> i64 {
let mut last_second = self.last_second.lock().unwrap();
let mut current_second = self.get_current_second(epoch_seconds);
if current_second < *last_second {
if !enable_backward {
panic!("Clock moved backwards. But backward not enabled");
}
let refused_seconds = *last_second - current_second;
if refused_seconds <= max_backward_seconds {
while current_second < *last_second {
current_second = self.get_current_second(epoch_seconds)
}
} else {
panic!("Clock moved backwards. Refused seconds bigger than max backward seconds")
}
} else if current_second == *last_second {
self.sequence = (self.sequence + 1) & self.bits_allocator.max_sequence;
if self.sequence == 0 {
current_second = self.get_next_second(*last_second, epoch_seconds);
}
} else {
self.sequence = 0i64;
}
*last_second = current_second;
self.bits_allocator.allocate(
current_second - epoch_seconds,
self.worker_id,
self.sequence
)
}
#[inline(always)]
fn get_current_second(&self, epoch_seconds: i64) -> i64 {
let current_seconds = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64;
if current_seconds - epoch_seconds > self.bits_allocator.max_delta_seconds {
panic!("Timestamp bits is exhausted. Refusing uid generation.")
}
return current_seconds
}
#[inline(always)]
fn get_next_second(&self, last_timestamp: i64, epoch_seconds: i64) ->i64 {
let mut timestamp = self.get_current_second(epoch_seconds);
while timestamp <= last_timestamp {
timestamp = self.get_current_second(epoch_seconds)
}
return timestamp
}
}