xCommonLib/base/
id_generator.rs

1use std::sync::atomic::{AtomicI64, AtomicU16, Ordering};
2
3use crate::utils::string_utils;
4use crate::utils::time_utils;
5
6static CUR_MILLISECOND_NO: AtomicU16 = AtomicU16::new(0);
7static CUR_DXC_SEQ_NO: AtomicU16 = AtomicU16::new(1);
8static CUR_SERVICE_SEQ_NO: AtomicU16 = AtomicU16::new(1);
9static LAST_TIMESTAMP: AtomicI64 = AtomicI64::new(0);
10
11pub struct IdInfo {
12    pub gen_time: String,
13    pub timestamp: i64,
14    pub mill_sec_no: u16,
15}
16
17pub struct IdentityInfo {
18    pub ip: String,
19    pub port: u16,
20}
21
22/**
23 * 更新当前时间戳的事件
24 */
25#[allow(dead_code)]
26pub fn update_timestamp(timestamp: i64) {
27    LAST_TIMESTAMP.store(timestamp, Ordering::Release);
28}
29
30#[allow(dead_code)]
31pub fn gen_dxc_id() -> i64 {
32    let dxc_seq_no = CUR_DXC_SEQ_NO.fetch_add(1, Ordering::AcqRel);
33
34    let cur_timestamp = time_utils::cur_timestamp() as u64;
35
36    let val = ((cur_timestamp & 0xFFFFFFFF) << 30)
37        | (((dxc_seq_no & 0x3FF) as u64) << 10) & 0xFFFFFFFFFFFFFC00;
38
39    val as i64
40}
41
42#[allow(dead_code)]
43pub fn get_dxc_id_by_service_id(service_id: i64) -> i64 {
44    (service_id as u64 & 0xFFFFFFFFFFFFFC00) as i64
45}
46
47#[allow(dead_code)]
48pub fn gen_service_id(service_id: i64) -> i64 {
49    let service_seq_no = CUR_SERVICE_SEQ_NO.fetch_add(1, Ordering::AcqRel);
50    service_id | (service_seq_no as i64 & 0x3FF)
51}
52
53#[allow(dead_code)]
54pub fn get_dxc_gen_time(dxc_id: i64) -> i64 {
55    dxc_id >> 30
56}
57
58#[allow(dead_code)]
59pub fn get_id_gen_time(id: i64) -> String {
60    let millis = get_id_timestamp(id);
61    time_utils::timestamp_to_string("yyyy-MM-dd hh:mm:ss.SSS", millis)
62}
63
64#[allow(dead_code)]
65pub fn get_id_timestamp(id: i64) -> i64 {
66    id >> 16
67}
68
69#[allow(dead_code)]
70pub fn get_millisecond_no(id: i64) -> u16 {
71    (id & 0xFFFF) as u16
72}
73
74#[allow(dead_code)]
75pub fn get_all_id_info(id: i64) -> IdInfo {
76    IdInfo {
77        timestamp: get_id_timestamp(id),
78        gen_time: get_id_gen_time(id),
79        mill_sec_no: get_millisecond_no(id),
80    }
81}
82
83#[allow(dead_code)]
84pub fn gen_id() -> i64 {
85  gen_id_with_sgement_id(0)
86}
87
88#[allow(dead_code)]
89pub fn gen_id_with_sgement_id(sgement_id: u16) -> i64 {
90    let mut cur_timestamp = time_utils::cur_timestamp() & 0x7FFFFFFFFFFF;
91
92    //  确保在 4096 以内
93    let mill_no = CUR_MILLISECOND_NO.fetch_add(1, Ordering::AcqRel) % 4096;
94
95    // 如果两次时间按戳一致,那么当前时间戳 + 1
96    let last_timestamp = LAST_TIMESTAMP.fetch_max(cur_timestamp, Ordering::AcqRel);
97
98    if last_timestamp > cur_timestamp && mill_no == 0 {
99        cur_timestamp = LAST_TIMESTAMP.fetch_add(1, Ordering::AcqRel) + 1;
100    }
101    // 为  1672502400000  2023-01-01 00:00:00.000 时间戳
102    (cur_timestamp - 1672502400000) << 22 | ((sgement_id as i64) << 12) | (mill_no as i64)
103}
104
105#[allow(dead_code)]
106pub fn get_sgement_id_from_id(id: i64) -> u16 {
107    //
108    ((id & 0x00000000003FF000) >> 12) as u16
109}
110
111#[allow(dead_code)]
112pub fn get_node_id_info(identity: i64) -> IdentityInfo {
113    let ip = (identity >> 16) as u32;
114    IdentityInfo {
115        ip: string_utils::int_ip_to_str(ip),
116        port: (identity & 0xFFFF) as u16,
117    }
118}
119
120#[allow(dead_code)]
121pub fn get_int_ip_from_conn_id(conn_id: i64) -> u32 {
122    (conn_id >> 16) as u32
123}
124
125#[allow(dead_code)]
126pub fn make_remote_node_id(ip: &str, port: u16) -> i64 {
127    make_node_id(ip, port)
128}
129
130#[allow(dead_code)]
131pub fn replace_identity_port(identity: i64, port: u16) -> i64 {
132    let ip = (identity >> 16) as i64;
133    ip << 16 | port as i64
134}
135
136#[allow(dead_code)]
137pub fn make_node_id(ip: &str, port: u16) -> i64 {
138    let ip = ip.trim();
139    let node_identity_id = string_utils::str_ip_to_int(ip);
140    ((node_identity_id as i64) << 16 | port as i64) as i64
141}
142
143#[allow(dead_code)]
144pub fn make_node_id_with_uint_ip(ip: u32, port: u16) -> i64 {
145    let conn_id = ip as i64;
146    conn_id << 16 | port as i64
147}
148
149/**
150 *
151 */
152#[allow(dead_code)]
153pub fn addr_to_conn_id(addr: &str) -> i64 {
154    let words: Vec<&str> = addr.split(':').collect();
155
156    if words.len() != 2 {
157        return 0;
158    }
159
160    let port: u16 = words[1].parse::<u16>().unwrap();
161
162    make_node_id(words[0], port)
163}
164
165#[allow(dead_code)]
166pub fn conn_id_to_addr(conn_id: i64) -> String {
167    let identity_info = get_node_id_info(conn_id);
168
169    format!("{}:{}", identity_info.ip, identity_info.port)
170}