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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use std::sync::atomic::{AtomicI64, AtomicU16, Ordering};

use crate::utils::string_utils;
use crate::utils::time_utils;

static CUR_MILLISECOND_NO: AtomicU16 = AtomicU16::new(0);
static CUR_DXC_SEQ_NO: AtomicU16 = AtomicU16::new(1);
static CUR_SERVICE_SEQ_NO: AtomicU16 = AtomicU16::new(1);
static LAST_TIMESTAMP: AtomicI64 = AtomicI64::new(0);

pub struct IdInfo {
    pub gen_time: String,
    pub timestamp: i64,
    pub mill_sec_no: u16,
}

pub struct IdentityInfo {
    pub ip: String,
    pub port: u16,
}

/**
 * 更新当前时间戳的事件
 */
#[allow(dead_code)]
pub fn update_timestamp(timestamp: i64) {
    LAST_TIMESTAMP.store(timestamp, Ordering::Release);
}

#[allow(dead_code)]
pub fn gen_dxc_id() -> i64 {
    let dxc_seq_no = CUR_DXC_SEQ_NO.fetch_add(1, Ordering::AcqRel);

    let cur_timestamp = time_utils::cur_timestamp() as u64;

    let val = ((cur_timestamp & 0xFFFFFFFF) << 30)
        | (((dxc_seq_no & 0x3FF) as u64) << 10) & 0xFFFFFFFFFFFFFC00;

    val as i64
}

#[allow(dead_code)]
pub fn get_dxc_id_by_service_id(service_id: i64) -> i64 {
    (service_id as u64 & 0xFFFFFFFFFFFFFC00) as i64
}

#[allow(dead_code)]
pub fn gen_service_id(service_id: i64) -> i64 {
    let service_seq_no = CUR_SERVICE_SEQ_NO.fetch_add(1, Ordering::AcqRel);
    service_id | (service_seq_no as i64 & 0x3FF)
}

#[allow(dead_code)]
pub fn get_dxc_gen_time(dxc_id: i64) -> i64 {
    dxc_id >> 30
}

#[allow(dead_code)]
pub fn get_id_gen_time(id: i64) -> String {
    let millis = get_id_timestamp(id);
    time_utils::timestamp_to_string("yyyy-MM-dd hh:mm:ss.SSS", millis)
}

#[allow(dead_code)]
pub fn get_id_timestamp(id: i64) -> i64 {
    id >> 16
}

#[allow(dead_code)]
pub fn get_millisecond_no(id: i64) -> u16 {
    (id & 0xFFFF) as u16
}

#[allow(dead_code)]
pub fn get_all_id_info(id: i64) -> IdInfo {
    IdInfo {
        timestamp: get_id_timestamp(id),
        gen_time: get_id_gen_time(id),
        mill_sec_no: get_millisecond_no(id),
    }
}

#[allow(dead_code)]
pub fn gen_id() -> i64 {
  gen_id_with_sgement_id(0)
}

#[allow(dead_code)]
pub fn gen_id_with_sgement_id(sgement_id: u16) -> i64 {
    let mut cur_timestamp = time_utils::cur_timestamp() & 0x7FFFFFFFFFFF;

    //  确保在 4096 以内
    let mill_no = CUR_MILLISECOND_NO.fetch_add(1, Ordering::AcqRel) % 4096;

    // 如果两次时间按戳一致,那么当前时间戳 + 1
    let last_timestamp = LAST_TIMESTAMP.fetch_max(cur_timestamp, Ordering::AcqRel);

    if last_timestamp > cur_timestamp && mill_no == 0 {
        cur_timestamp = LAST_TIMESTAMP.fetch_add(1, Ordering::AcqRel) + 1;
    }
    // 为  1672502400000  2023-01-01 00:00:00.000 时间戳
    (cur_timestamp - 1672502400000) << 22 | ((sgement_id as i64) << 12) | (mill_no as i64)
}

#[allow(dead_code)]
pub fn get_sgement_id_from_id(id: i64) -> u16 {
    //
    ((id & 0x00000000003FF000) >> 12) as u16
}

#[allow(dead_code)]
pub fn get_node_id_info(identity: i64) -> IdentityInfo {
    let ip = (identity >> 16) as u32;
    IdentityInfo {
        ip: string_utils::int_ip_to_str(ip),
        port: (identity & 0xFFFF) as u16,
    }
}

#[allow(dead_code)]
pub fn get_int_ip_from_conn_id(conn_id: i64) -> u32 {
    (conn_id >> 16) as u32
}

#[allow(dead_code)]
pub fn make_remote_node_id(ip: &str, port: u16) -> i64 {
    make_node_id(ip, port)
}

#[allow(dead_code)]
pub fn replace_identity_port(identity: i64, port: u16) -> i64 {
    let ip = (identity >> 16) as i64;
    ip << 16 | port as i64
}

#[allow(dead_code)]
pub fn make_node_id(ip: &str, port: u16) -> i64 {
    let ip = ip.trim();
    let node_identity_id = string_utils::str_ip_to_int(ip);
    ((node_identity_id as i64) << 16 | port as i64) as i64
}

#[allow(dead_code)]
pub fn make_node_id_with_uint_ip(ip: u32, port: u16) -> i64 {
    let conn_id = ip as i64;
    conn_id << 16 | port as i64
}

/**
 *
 */
#[allow(dead_code)]
pub fn addr_to_conn_id(addr: &str) -> i64 {
    let words: Vec<&str> = addr.split(':').collect();

    if words.len() != 2 {
        return 0;
    }

    let port: u16 = words[1].parse::<u16>().unwrap();

    make_node_id(words[0], port)
}

#[allow(dead_code)]
pub fn conn_id_to_addr(conn_id: i64) -> String {
    let identity_info = get_node_id_info(conn_id);

    format!("{}:{}", identity_info.ip, identity_info.port)
}