package org.dromara.monitoring.config;

public class SnowFlakeUtil {
    // 起始时间戳
    private static final long startTimeStamp = 1577808000000L;
    // 机器ID
    private static final long workID = 1L;
    // 数据中心ID
    private static final long dataCenterID = 1L;
    // 序列号
    private static long sequence = 0L;
    // 数据中心ID移动位数
    private static final long dataCenterIndex = 12L;
    // 机器ID移动位数
    private static final long workIDIndex = 17L;
    // 时间戳移动位数
    private static final long timeStampIndex = 22L;
    // 记录上一次时间戳
    private static long lastTimeStamp = -1L;
    // 序列号掩码
    private static final long sequenceMask = -1L ^ (-1L << 12);
    public synchronized static long getID() {
        long now = System.currentTimeMillis();
        if (now < lastTimeStamp) {
            throw new RuntimeException("时钟回拨异常");
        }
        if (now == lastTimeStamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0L) {
                try {
                    Thread.sleep(1L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                now = System.currentTimeMillis();
            }
        } else {
            sequence = 0L;
        }
        lastTimeStamp = now;
        return ((now - startTimeStamp) << timeStampIndex) | (dataCenterID << dataCenterIndex) | (workID << workIDIndex) | sequence;
    }
}
