Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Linq;
- namespace Snowflake
- {
- public class IdWorker
- {
- // 2019-10-01T10:00:00+08
- public const long DEFAULT_TWEPOCH = 1569895200000L;
- private readonly long clusterId;
- private readonly long workerId;
- private readonly int clusterIdBits;
- private readonly int workerIdBits;
- private readonly int sequenceBits;
- private readonly long sequenceMask;
- private readonly long twepoch;
- private long sequence = 0;
- private long lastMillis = 0;
- public IdWorker(long clusterId, long workerId, int clusterIdBits = 5, int workerIdBits = 5, int sequenceBits = 12, long twepoch = DEFAULT_TWEPOCH)
- {
- this.clusterId = clusterId;
- this.workerId = workerId;
- this.clusterIdBits = clusterIdBits;
- this.workerIdBits = workerIdBits;
- this.sequenceBits = sequenceBits;
- this.twepoch = twepoch;
- sequenceMask = -1 ^ (-1L << sequenceBits);
- var maxClusterId = -1 ^ (-1L << clusterIdBits);
- var maxWorkerId = -1 ^ (-1 << workerIdBits);
- if (clusterId < 0 || clusterId > maxClusterId)
- {
- throw new ArgumentOutOfRangeException($"Value of \"{nameof(clusterId)}\" must be in the range 0 to {maxClusterId}.");
- }
- if (workerId < 0 || workerId > maxWorkerId)
- {
- throw new ArgumentOutOfRangeException($"Value of \"{nameof(workerId)}\" must be in the range 0 to {maxWorkerId}.");
- }
- if (twepoch <= 0)
- {
- throw new ArgumentOutOfRangeException($"Value of \"{nameof(twepoch)}\" must be greater than 0.");
- }
- if (clusterIdBits <= 0)
- {
- throw new ArgumentOutOfRangeException($"Value of \"{nameof(clusterIdBits)}\" must be greater than 0.");
- }
- if (workerIdBits <= 0)
- {
- throw new ArgumentOutOfRangeException($"Value of \"{nameof(workerIdBits)}\" must be greater than 0.");
- }
- if (sequenceBits <= 0)
- {
- throw new ArgumentOutOfRangeException($"Value of \"{nameof(sequenceBits)}\" must be greater than 0.");
- }
- if (clusterIdBits + workerIdBits + sequenceBits >= 63)
- {
- throw new ArgumentOutOfRangeException($"Sum of \"{nameof(clusterIdBits)}\" \"{nameof(workerIdBits)}\" and \"{nameof(sequenceBits)}\" must be less than 63");
- }
- }
- public long NextInt64()
- {
- lock (this)
- {
- var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- if (timestamp == lastMillis)
- {
- sequence = (sequence + 1) & sequenceMask;
- if (sequence == 0L)
- {
- var nextMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- while (nextMillis <= lastMillis)
- {
- nextMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- }
- timestamp = nextMillis;
- }
- }
- else
- {
- sequence = 0L;
- }
- lastMillis = timestamp;
- return (timestamp - twepoch << clusterIdBits + workerIdBits + sequenceBits) |
- (clusterId << workerIdBits + sequenceBits) |
- (workerId << sequenceBits) |
- sequence;
- }
- }
- public byte[] NextBytes()
- {
- var nextId = NextInt64();
- return new byte[]{
- (byte)(nextId >> 56),
- (byte)(nextId >> 48),
- (byte)(nextId >> 40),
- (byte)(nextId >> 32),
- (byte)(nextId >> 24),
- (byte)(nextId >> 16),
- (byte)(nextId >> 8),
- (byte)(nextId),
- };
- }
- public string NextHex(bool lowerCase = false)
- {
- return string.Concat(NextBytes().Select(b => b.ToString(lowerCase ? "x2" : "X2")));
- }
- public string NextBase64()
- {
- return Convert.ToBase64String(NextBytes());
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement