|
|
|
@ -1,4 +1,6 @@
|
|
|
|
|
/** Copyright 2010-2012 Twitter, Inc.*/ |
|
|
|
|
/** |
|
|
|
|
* Copyright 2010-2012 Twitter, Inc. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
package org.apache.dolphinscheduler.common.utils; |
|
|
|
|
|
|
|
|
@ -6,66 +8,71 @@ import java.net.InetAddress;
|
|
|
|
|
import java.net.UnknownHostException; |
|
|
|
|
import java.util.Objects; |
|
|
|
|
|
|
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Rewriting based on Twitter snowflake algorithm |
|
|
|
|
* Rewriting based on Twitter snowflake algorithm |
|
|
|
|
*/ |
|
|
|
|
@Slf4j |
|
|
|
|
public class CodeGenerateUtils { |
|
|
|
|
|
|
|
|
|
// start timestamp
|
|
|
|
|
private static final long START_TIMESTAMP = 1609430400000L; // 2021-01-01 00:00:00
|
|
|
|
|
// Each machine generates 32 in the same millisecond
|
|
|
|
|
private static final long LOW_DIGIT_BIT = 5L; |
|
|
|
|
private static final long MIDDLE_BIT = 2L; |
|
|
|
|
private static final long MAX_LOW_DIGIT = ~(-1L << LOW_DIGIT_BIT); |
|
|
|
|
// The displacement to the left
|
|
|
|
|
private static final long MIDDLE_LEFT = LOW_DIGIT_BIT; |
|
|
|
|
private static final long HIGH_DIGIT_LEFT = LOW_DIGIT_BIT + MIDDLE_BIT; |
|
|
|
|
private final long machineHash; |
|
|
|
|
private long lowDigit = 0L; |
|
|
|
|
private long recordMillisecond = -1L; |
|
|
|
|
|
|
|
|
|
private static final long SYSTEM_TIMESTAMP = System.currentTimeMillis(); |
|
|
|
|
private static final long SYSTEM_NANOTIME = System.nanoTime(); |
|
|
|
|
private static final CodeGenerator codeGenerator; |
|
|
|
|
|
|
|
|
|
private CodeGenerateUtils() throws CodeGenerateException { |
|
|
|
|
static { |
|
|
|
|
try { |
|
|
|
|
this.machineHash = |
|
|
|
|
Math.abs(Objects.hash(InetAddress.getLocalHost().getHostName())) % (2 << (MIDDLE_BIT - 1)); |
|
|
|
|
codeGenerator = new CodeGenerator(InetAddress.getLocalHost().getHostName() + "-" + OSUtils.getProcessID()); |
|
|
|
|
} catch (UnknownHostException e) { |
|
|
|
|
throw new CodeGenerateException(e.getMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static CodeGenerateUtils instance = null; |
|
|
|
|
|
|
|
|
|
public static synchronized CodeGenerateUtils getInstance() throws CodeGenerateException { |
|
|
|
|
if (instance == null) { |
|
|
|
|
instance = new CodeGenerateUtils(); |
|
|
|
|
} |
|
|
|
|
return instance; |
|
|
|
|
public static long genCode() throws CodeGenerateException { |
|
|
|
|
return codeGenerator.genCode(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public synchronized long genCode() throws CodeGenerateException { |
|
|
|
|
long nowtMillisecond = systemMillisecond(); |
|
|
|
|
if (nowtMillisecond < recordMillisecond) { |
|
|
|
|
throw new CodeGenerateException("New code exception because time is set back."); |
|
|
|
|
public static class CodeGenerator { |
|
|
|
|
|
|
|
|
|
// start timestamp
|
|
|
|
|
private static final long START_TIMESTAMP = 1609430400000L; // 2021-01-01 00:00:00
|
|
|
|
|
// Each machine generates 32 in the same millisecond
|
|
|
|
|
private static final long LOW_DIGIT_BIT = 5L; |
|
|
|
|
private static final long MACHINE_BIT = 5L; |
|
|
|
|
private static final long MAX_LOW_DIGIT = ~(-1L << LOW_DIGIT_BIT); |
|
|
|
|
// The displacement to the left
|
|
|
|
|
private static final long HIGH_DIGIT_LEFT = LOW_DIGIT_BIT + MACHINE_BIT; |
|
|
|
|
public final long machineHash; |
|
|
|
|
private long lowDigit = 0L; |
|
|
|
|
private long recordMillisecond = -1L; |
|
|
|
|
|
|
|
|
|
private static final long SYSTEM_TIMESTAMP = System.currentTimeMillis(); |
|
|
|
|
private static final long SYSTEM_NANOTIME = System.nanoTime(); |
|
|
|
|
|
|
|
|
|
public CodeGenerator(String appName) { |
|
|
|
|
this.machineHash = Math.abs(Objects.hash(appName)) % (1 << MACHINE_BIT); |
|
|
|
|
} |
|
|
|
|
if (nowtMillisecond == recordMillisecond) { |
|
|
|
|
lowDigit = (lowDigit + 1) & MAX_LOW_DIGIT; |
|
|
|
|
if (lowDigit == 0L) { |
|
|
|
|
while (nowtMillisecond <= recordMillisecond) { |
|
|
|
|
nowtMillisecond = systemMillisecond(); |
|
|
|
|
|
|
|
|
|
public synchronized long genCode() throws CodeGenerateException { |
|
|
|
|
long nowtMillisecond = systemMillisecond(); |
|
|
|
|
if (nowtMillisecond < recordMillisecond) { |
|
|
|
|
throw new CodeGenerateException("New code exception because time is set back."); |
|
|
|
|
} |
|
|
|
|
if (nowtMillisecond == recordMillisecond) { |
|
|
|
|
lowDigit = (lowDigit + 1) & MAX_LOW_DIGIT; |
|
|
|
|
if (lowDigit == 0L) { |
|
|
|
|
while (nowtMillisecond <= recordMillisecond) { |
|
|
|
|
nowtMillisecond = systemMillisecond(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
lowDigit = 0L; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
lowDigit = 0L; |
|
|
|
|
recordMillisecond = nowtMillisecond; |
|
|
|
|
return (nowtMillisecond - START_TIMESTAMP) << HIGH_DIGIT_LEFT | machineHash << LOW_DIGIT_BIT | lowDigit; |
|
|
|
|
} |
|
|
|
|
recordMillisecond = nowtMillisecond; |
|
|
|
|
return (nowtMillisecond - START_TIMESTAMP) << HIGH_DIGIT_LEFT | machineHash << MIDDLE_LEFT | lowDigit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private long systemMillisecond() { |
|
|
|
|
return SYSTEM_TIMESTAMP + (System.nanoTime() - SYSTEM_NANOTIME) / 1000000; |
|
|
|
|
private long systemMillisecond() { |
|
|
|
|
return SYSTEM_TIMESTAMP + (System.nanoTime() - SYSTEM_NANOTIME) / 1000000; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static class CodeGenerateException extends RuntimeException { |
|
|
|
|