SHARE
TWEET

Untitled

a guest Oct 23rd, 2019 81 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System;
  2. using System.Linq;
  3.  
  4. namespace Snowflake
  5. {
  6.     public class IdWorker
  7.     {
  8.         // 2019-10-01T10:00:00+08
  9.         public const long DEFAULT_TWEPOCH = 1569895200000L;
  10.  
  11.         private readonly long clusterId;
  12.         private readonly long workerId;
  13.         private readonly int clusterIdBits;
  14.         private readonly int workerIdBits;
  15.         private readonly int sequenceBits;
  16.         private readonly long sequenceMask;
  17.         private readonly long twepoch;
  18.  
  19.         private long sequence = 0;
  20.         private long lastMillis = 0;
  21.  
  22.         public IdWorker(long clusterId, long workerId, int clusterIdBits = 5, int workerIdBits = 5, int sequenceBits = 12, long twepoch = DEFAULT_TWEPOCH)
  23.         {
  24.             this.clusterId = clusterId;
  25.             this.workerId = workerId;
  26.             this.clusterIdBits = clusterIdBits;
  27.             this.workerIdBits = workerIdBits;
  28.             this.sequenceBits = sequenceBits;
  29.             this.twepoch = twepoch;
  30.  
  31.             sequenceMask = -1 ^ (-1L << sequenceBits);
  32.             var maxClusterId = -1 ^ (-1L << clusterIdBits);
  33.             var maxWorkerId = -1 ^ (-1 << workerIdBits);
  34.  
  35.             if (clusterId < 0 || clusterId > maxClusterId)
  36.             {
  37.                 throw new ArgumentOutOfRangeException($"Value of \"{nameof(clusterId)}\" must be in the range 0 to {maxClusterId}.");
  38.             }
  39.             if (workerId < 0 || workerId > maxWorkerId)
  40.             {
  41.                 throw new ArgumentOutOfRangeException($"Value of \"{nameof(workerId)}\" must be in the range 0 to {maxWorkerId}.");
  42.             }
  43.             if (twepoch <= 0)
  44.             {
  45.                 throw new ArgumentOutOfRangeException($"Value of \"{nameof(twepoch)}\" must be greater than 0.");
  46.             }
  47.             if (clusterIdBits <= 0)
  48.             {
  49.                 throw new ArgumentOutOfRangeException($"Value of \"{nameof(clusterIdBits)}\" must be greater than 0.");
  50.             }
  51.             if (workerIdBits <= 0)
  52.             {
  53.                 throw new ArgumentOutOfRangeException($"Value of \"{nameof(workerIdBits)}\" must be greater than 0.");
  54.             }
  55.             if (sequenceBits <= 0)
  56.             {
  57.                 throw new ArgumentOutOfRangeException($"Value of \"{nameof(sequenceBits)}\" must be greater than 0.");
  58.             }
  59.             if (clusterIdBits + workerIdBits + sequenceBits >= 63)
  60.             {
  61.                 throw new ArgumentOutOfRangeException($"Sum of \"{nameof(clusterIdBits)}\" \"{nameof(workerIdBits)}\" and \"{nameof(sequenceBits)}\" must be less than 63");
  62.             }
  63.         }
  64.  
  65.         public long NextInt64()
  66.         {
  67.             lock (this)
  68.             {
  69.                 var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  70.                 if (timestamp == lastMillis)
  71.                 {
  72.                     sequence = (sequence + 1) & sequenceMask;
  73.                     if (sequence == 0L)
  74.                     {
  75.                         var nextMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  76.                         while (nextMillis <= lastMillis)
  77.                         {
  78.                             nextMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  79.                         }
  80.                         timestamp = nextMillis;
  81.                     }
  82.                 }
  83.                 else
  84.                 {
  85.                     sequence = 0L;
  86.                 }
  87.                 lastMillis = timestamp;
  88.                 return (timestamp - twepoch << clusterIdBits + workerIdBits + sequenceBits) |
  89.                     (clusterId << workerIdBits + sequenceBits) |
  90.                     (workerId << sequenceBits) |
  91.                     sequence;
  92.             }
  93.         }
  94.  
  95.         public byte[] NextBytes()
  96.         {
  97.             var nextId = NextInt64();
  98.             return new byte[]{
  99.                     (byte)(nextId >> 56),
  100.                     (byte)(nextId >> 48),
  101.                     (byte)(nextId >> 40),
  102.                     (byte)(nextId >> 32),
  103.                     (byte)(nextId >> 24),
  104.                     (byte)(nextId >> 16),
  105.                     (byte)(nextId >> 8),
  106.                     (byte)(nextId),
  107.                 };
  108.         }
  109.  
  110.         public string NextHex(bool lowerCase = false)
  111.         {
  112.             return string.Concat(NextBytes().Select(b => b.ToString(lowerCase ? "x2" : "X2")));
  113.         }
  114.  
  115.         public string NextBase64()
  116.         {
  117.             return Convert.ToBase64String(NextBytes());
  118.         }
  119.     }
  120. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top