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;
let mill_no = CUR_MILLISECOND_NO.fetch_add(1, Ordering::AcqRel) % 4096;
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;
}
(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)
}