1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.regionserver;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertTrue;
23
24 import java.io.IOException;
25
26 import org.apache.hadoop.hbase.io.TimeRange;
27 import org.apache.hadoop.hbase.testclassification.SmallTests;
28 import org.apache.hadoop.hbase.util.Writables;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import java.util.concurrent.ThreadLocalRandom;
32
33 @Category({SmallTests.class})
34 public class TestTimeRangeTracker {
35 private static final int NUM_KEYS = 10000000;
36
37 @Test
38 public void testExtreme() {
39 TimeRange tr = new TimeRange();
40 assertTrue(tr.includesTimeRange(new TimeRange()));
41 TimeRangeTracker trt = new TimeRangeTracker();
42 assertFalse(trt.includesTimeRange(new TimeRange()));
43 trt.includeTimestamp(1);
44 trt.includeTimestamp(10);
45 assertTrue(trt.includesTimeRange(new TimeRange()));
46 }
47
48 @Test
49 public void testTimeRangeInitialized() {
50 TimeRangeTracker src = new TimeRangeTracker();
51 TimeRange tr = new TimeRange(System.currentTimeMillis());
52 assertFalse(src.includesTimeRange(tr));
53 }
54
55 @Test
56 public void testTimeRangeTrackerNullIsSameAsTimeRangeNull() throws IOException {
57 TimeRangeTracker src = new TimeRangeTracker(1, 2);
58 byte [] bytes = Writables.getBytes(src);
59 TimeRange tgt = TimeRangeTracker.getTimeRange(bytes);
60 assertEquals(src.getMin(), tgt.getMin());
61 assertEquals(src.getMax(), tgt.getMax());
62 }
63
64 @Test
65 public void testSerialization() throws IOException {
66 TimeRangeTracker src = new TimeRangeTracker(1, 2);
67 TimeRangeTracker tgt = new TimeRangeTracker();
68 Writables.copyWritable(src, tgt);
69 assertEquals(src.getMin(), tgt.getMin());
70 assertEquals(src.getMax(), tgt.getMax());
71 }
72
73 @Test
74 public void testAlwaysDecrementingSetsMaximum() {
75 TimeRangeTracker trr = new TimeRangeTracker();
76 trr.includeTimestamp(3);
77 trr.includeTimestamp(2);
78 trr.includeTimestamp(1);
79 assertTrue(trr.getMin() != TimeRangeTracker.INITIAL_MIN_TIMESTAMP);
80 assertTrue(trr.getMax() != -1
81 }
82
83 @Test
84 public void testSimpleInRange() {
85 TimeRangeTracker trr = new TimeRangeTracker();
86 trr.includeTimestamp(0);
87 trr.includeTimestamp(2);
88 assertTrue(trr.includesTimeRange(new TimeRange(1)));
89 }
90
91
92
93
94
95
96
97 @Test
98 public void testArriveAtRightAnswer() throws InterruptedException {
99 final TimeRangeTracker trr = new TimeRangeTracker();
100 final int threadCount = 10;
101 final int calls = 1000 * 1000;
102 Thread [] threads = new Thread[threadCount];
103 for (int i = 0; i < threads.length; i++) {
104 Thread t = new Thread("" + i) {
105 @Override
106 public void run() {
107 int offset = Integer.parseInt(getName());
108 boolean even = offset % 2 == 0;
109 if (even) {
110 for (int i = (offset * calls); i < calls; i++) trr.includeTimestamp(i);
111 } else {
112 int base = offset * calls;
113 for (int i = base + calls; i >= base; i--) trr.includeTimestamp(i);
114 }
115 }
116 };
117 t.start();
118 threads[i] = t;
119 }
120 for (int i = 0; i < threads.length; i++) {
121 threads[i].join();
122 }
123
124 assertTrue(trr.getMax() == calls * threadCount);
125 assertTrue(trr.getMin() == 0);
126 }
127
128 @Test
129 public void testRangeConstruction() throws IOException {
130 TimeRange defaultRange = new TimeRange();
131 assertEquals(0L, defaultRange.getMin());
132 assertEquals(Long.MAX_VALUE, defaultRange.getMax());
133 assertTrue(defaultRange.isAllTime());
134
135 TimeRange oneArgRange = new TimeRange(0L);
136 assertEquals(0L, oneArgRange.getMin());
137 assertEquals(Long.MAX_VALUE, oneArgRange.getMax());
138 assertTrue(oneArgRange.isAllTime());
139
140 TimeRange oneArgRange2 = new TimeRange(1);
141 assertEquals(1, oneArgRange2.getMin());
142 assertEquals(Long.MAX_VALUE, oneArgRange2.getMax());
143 assertFalse(oneArgRange2.isAllTime());
144
145 TimeRange twoArgRange = new TimeRange(0L, Long.MAX_VALUE);
146 assertEquals(0L, twoArgRange.getMin());
147 assertEquals(Long.MAX_VALUE, twoArgRange.getMax());
148 assertTrue(twoArgRange.isAllTime());
149
150 TimeRange twoArgRange2 = new TimeRange(0L, Long.MAX_VALUE - 1);
151 assertEquals(0L, twoArgRange2.getMin());
152 assertEquals(Long.MAX_VALUE - 1, twoArgRange2.getMax());
153 assertFalse(twoArgRange2.isAllTime());
154
155 TimeRange twoArgRange3 = new TimeRange(1, Long.MAX_VALUE);
156 assertEquals(1, twoArgRange3.getMin());
157 assertEquals(Long.MAX_VALUE, twoArgRange3.getMax());
158 assertFalse(twoArgRange3.isAllTime());
159 }
160
161 final static int NUM_OF_THREADS = 20;
162
163 class RandomTestData {
164 private long[] keys = new long[NUM_KEYS];
165 private long min = Long.MAX_VALUE;
166 private long max = 0;
167
168 public RandomTestData() {
169 if (ThreadLocalRandom.current().nextInt(NUM_OF_THREADS) % 2 == 0) {
170 for (int i = 0; i < NUM_KEYS; i++) {
171 keys[i] = i + ThreadLocalRandom.current().nextLong(NUM_OF_THREADS);
172 if (keys[i] < min) min = keys[i];
173 if (keys[i] > max) max = keys[i];
174 }
175 } else {
176 for (int i = NUM_KEYS - 1; i >= 0; i--) {
177 keys[i] = i + ThreadLocalRandom.current().nextLong(NUM_OF_THREADS);
178 if (keys[i] < min) min = keys[i];
179 if (keys[i] > max) max = keys[i];
180 }
181 }
182 }
183
184 public long getMax() {
185 return this.max;
186 }
187
188 public long getMin() {
189 return this.min;
190 }
191 }
192
193 class TrtUpdateRunnable implements Runnable {
194
195 private TimeRangeTracker trt;
196 private RandomTestData data;
197 public TrtUpdateRunnable(final TimeRangeTracker trt, final RandomTestData data) {
198 this.trt = trt;
199 this.data = data;
200 }
201
202 public void run() {
203 for (long key : data.keys) {
204 trt.includeTimestamp(key);
205 }
206 }
207 }
208
209
210
211
212
213
214 @Test
215 public void testConcurrentIncludeTimestampCorrectness() {
216 RandomTestData[] testData = new RandomTestData[NUM_OF_THREADS];
217 long min = Long.MAX_VALUE, max = 0;
218 for (int i = 0; i < NUM_OF_THREADS; i ++) {
219 testData[i] = new RandomTestData();
220 if (testData[i].getMin() < min) {
221 min = testData[i].getMin();
222 }
223 if (testData[i].getMax() > max) {
224 max = testData[i].getMax();
225 }
226 }
227
228 TimeRangeTracker trt = new TimeRangeTracker();
229
230 Thread[] t = new Thread[NUM_OF_THREADS];
231 for (int i = 0; i < NUM_OF_THREADS; i++) {
232 t[i] = new Thread(new TrtUpdateRunnable(trt, testData[i]));
233 t[i].start();
234 }
235
236 for (Thread thread : t) {
237 try {
238 thread.join();
239 } catch (InterruptedException e) {
240 e.printStackTrace();
241 }
242 }
243
244 assertTrue(min == trt.getMin());
245 assertTrue(max == trt.getMax());
246 }
247
248
249
250
251
252
253 public static void main(String[] args) throws InterruptedException {
254 long start = System.currentTimeMillis();
255 final TimeRangeTracker trr = new TimeRangeTracker();
256 final int threadCount = 5;
257 final int calls = 1024 * 1024 * 128;
258 Thread [] threads = new Thread[threadCount];
259 for (int i = 0; i < threads.length; i++) {
260 Thread t = new Thread("" + i) {
261 @Override
262 public void run() {
263 for (int i = 0; i < calls; i++) trr.includeTimestamp(i);
264 }
265 };
266 t.start();
267 threads[i] = t;
268 }
269 for (int i = 0; i < threads.length; i++) {
270 threads[i].join();
271 }
272 System.out.println(trr.getMin() + " " + trr.getMax() + " " +
273 (System.currentTimeMillis() - start));
274 }
275 }