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 import org.junit.Test;
37
38 public class TestIdLock {
39
40 private static final Log LOG = LogFactory.getLog(TestIdLock.class);
41
42 private static final int NUM_IDS = 16;
43 private static final int NUM_THREADS = 128;
44 private static final int NUM_SECONDS = 15;
45
46 private IdLock idLock = new IdLock();
47
48 private Map<Long, String> idOwner = new ConcurrentHashMap<Long, String>();
49
50 private class IdLockTestThread implements Callable<Boolean> {
51
52 private String clientId;
53
54 public IdLockTestThread(String clientId) {
55 this.clientId = clientId;
56 }
57
58 @Override
59 public Boolean call() throws Exception {
60 Thread.currentThread().setName(clientId);
61 Random rand = new Random();
62 long endTime = System.currentTimeMillis() + NUM_SECONDS * 1000;
63 while (System.currentTimeMillis() < endTime) {
64 long id = rand.nextInt(NUM_IDS);
65
66 IdLock.Entry lockEntry = idLock.getLockEntry(id);
67 try {
68 int sleepMs = 1 + rand.nextInt(4);
69 String owner = idOwner.get(id);
70 if (owner != null) {
71 LOG.error("Id " + id + " already taken by " + owner + ", "
72 + clientId + " failed");
73 return false;
74 }
75
76 idOwner.put(id, clientId);
77 Thread.sleep(sleepMs);
78 idOwner.remove(id);
79
80 } finally {
81 idLock.releaseLockEntry(lockEntry);
82 }
83 }
84 return true;
85 }
86
87 }
88
89 @Test
90 public void testMultipleClients() throws Exception {
91 ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS);
92 try {
93 ExecutorCompletionService<Boolean> ecs =
94 new ExecutorCompletionService<Boolean>(exec);
95 for (int i = 0; i < NUM_THREADS; ++i)
96 ecs.submit(new IdLockTestThread("client_" + i));
97 for (int i = 0; i < NUM_THREADS; ++i) {
98 Future<Boolean> result = ecs.take();
99 assertTrue(result.get());
100 }
101 idLock.assertMapEmpty();
102 } finally {
103 exec.shutdown();
104 }
105 }
106
107 }