1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.util;
21
22 import com.google.common.base.Preconditions;
23 import java.util.HashSet;
24 import java.util.Random;
25 import java.util.Set;
26 import java.util.concurrent.atomic.AtomicLong;
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28
29
30
31
32
33
34
35
36
37 @InterfaceAudience.Private
38 public class Random64 {
39
40 private static final long multiplier = 6364136223846793005L;
41 private static final long addend = 1442695040888963407L;
42
43 private static final AtomicLong seedUniquifier
44 = new AtomicLong(8682522807148012L);
45
46 private long seed;
47
48
49
50
51 private static long seedUniquifier() {
52 for (; ; ) {
53 long current = seedUniquifier.get();
54 long next = current * 181783497276652981L;
55 if (seedUniquifier.compareAndSet(current, next)) {
56 return next;
57 }
58 }
59 }
60
61 public Random64() {
62 this(seedUniquifier() ^ System.nanoTime());
63 }
64
65 public Random64(long seed) {
66 this.seed = seed;
67 }
68
69 public long nextLong() {
70 return next64(64);
71 }
72
73 public void nextBytes(byte[] bytes) {
74 for (int i = 0, len = bytes.length; i < len;) {
75
76 for (long rnd = nextLong(), n = Math.min(len - i, Long.SIZE / Byte.SIZE);
77 n-- > 0; rnd >>>= Byte.SIZE) {
78 bytes[i++] = (byte) rnd;
79 }
80 }
81 }
82
83 private long next64(int bits) {
84 seed = seed * multiplier + addend;
85 return seed >>> (64 - bits);
86 }
87
88
89
90
91
92
93
94
95
96
97
98
99 public static void main(String[] args) {
100 long defaultTotalTestCnt = 1000000000000L;
101
102 if (args.length == 1) {
103 defaultTotalTestCnt = Long.parseLong(args[0]);
104 }
105
106 Preconditions.checkArgument(defaultTotalTestCnt > 0, "totalTestCnt <= 0");
107
108 final int precision = 100000;
109 final long totalTestCnt = defaultTotalTestCnt + precision;
110 final int reportPeriod = 100 * precision;
111 final long startTime = System.currentTimeMillis();
112
113 System.out.println("Do collision test, totalTestCnt=" + totalTestCnt);
114
115 Random64 rand = new Random64();
116 Set<Long> longSet = new HashSet<>();
117
118 for (long cnt = 1; cnt <= totalTestCnt; cnt++) {
119 final long randLong = rand.nextLong();
120
121 if (longSet.contains(randLong)) {
122 System.err.println("Conflict! count=" + cnt);
123 System.exit(1);
124 }
125
126 if (cnt % precision == 0) {
127 if (!longSet.add(randLong)) {
128 System.err.println("Conflict! count=" + cnt);
129 System.exit(1);
130 }
131
132 if (cnt % reportPeriod == 0) {
133 long cost = System.currentTimeMillis() - startTime;
134 long remainingMs = (long) (1.0 * (totalTestCnt - cnt) * cost / cnt);
135 System.out.println(
136 String.format(
137 "Progress: %.3f%%, remaining %d minutes",
138 100.0 * cnt / totalTestCnt, remainingMs / 60000
139 )
140 );
141 }
142 }
143
144 }
145
146 System.out.println("No collision!");
147 }
148
149 }