1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.util;
22
23 import java.util.Map;
24 import java.util.Random;
25 import java.util.concurrent.Callable;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ExecutorCompletionService;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Executors;
30 import java.util.concurrent.Future;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import static org.junit.Assert.*;
36
37 import org.apache.hadoop.hbase.MediumTests;
38 import org.junit.Test;
39 import org.junit.experimental.categories.Category;
40
41 @Category(MediumTests.class)
42
43 public class TestIdLock {
44
45 private static final Log LOG = LogFactory.getLog(TestIdLock.class);
46
47 private static final int NUM_IDS = 16;
48 private static final int NUM_THREADS = 128;
49 private static final int NUM_SECONDS = 15;
50
51 private IdLock idLock = new IdLock();
52
53 private Map<Long, String> idOwner = new ConcurrentHashMap<Long, String>();
54
55 private class IdLockTestThread implements Callable<Boolean> {
56
57 private String clientId;
58
59 public IdLockTestThread(String clientId) {
60 this.clientId = clientId;
61 }
62
63 @Override
64 public Boolean call() throws Exception {
65 Thread.currentThread().setName(clientId);
66 Random rand = new Random();
67 long endTime = System.currentTimeMillis() + NUM_SECONDS * 1000;
68 while (System.currentTimeMillis() < endTime) {
69 long id = rand.nextInt(NUM_IDS);
70
71 IdLock.Entry lockEntry = idLock.getLockEntry(id);
72 try {
73 int sleepMs = 1 + rand.nextInt(4);
74 String owner = idOwner.get(id);
75 if (owner != null) {
76 LOG.error("Id " + id + " already taken by " + owner + ", "
77 + clientId + " failed");
78 return false;
79 }
80
81 idOwner.put(id, clientId);
82 Thread.sleep(sleepMs);
83 idOwner.remove(id);
84
85 } finally {
86 idLock.releaseLockEntry(lockEntry);
87 }
88 }
89 return true;
90 }
91
92 }
93
94 @Test
95 public void testMultipleClients() throws Exception {
96 ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS);
97 try {
98 ExecutorCompletionService<Boolean> ecs =
99 new ExecutorCompletionService<Boolean>(exec);
100 for (int i = 0; i < NUM_THREADS; ++i)
101 ecs.submit(new IdLockTestThread("client_" + i));
102 for (int i = 0; i < NUM_THREADS; ++i) {
103 Future<Boolean> result = ecs.take();
104 assertTrue(result.get());
105 }
106 idLock.assertMapEmpty();
107 } finally {
108 exec.shutdown();
109 }
110 }
111
112
113 @org.junit.Rule
114 public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
115 new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
116 }
117