Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2019
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.35 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement