1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.Future;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.conf.Configuration;
30
31 public abstract class MultithreadedTestUtil {
32
33 public static final Log LOG =
34 LogFactory.getLog(MultithreadedTestUtil.class);
35
36 public static class TestContext {
37 private final Configuration conf;
38 private Throwable err = null;
39 private boolean stopped = false;
40 private int threadDoneCount = 0;
41 private Set<TestThread> testThreads = new HashSet<TestThread>();
42
43 public TestContext(Configuration configuration) {
44 this.conf = configuration;
45 }
46
47 protected Configuration getConf() {
48 return conf;
49 }
50
51 public synchronized boolean shouldRun() {
52 return !stopped && err == null;
53 }
54
55 public void addThread(TestThread t) {
56 testThreads.add(t);
57 }
58
59 public void startThreads() {
60 for (TestThread t : testThreads) {
61 t.start();
62 }
63 }
64
65 public void waitFor(long millis) throws Exception {
66 long endTime = System.currentTimeMillis() + millis;
67 while (!stopped) {
68 long left = endTime - System.currentTimeMillis();
69 if (left <= 0) break;
70 synchronized (this) {
71 checkException();
72 wait(left);
73 }
74 }
75 }
76 private synchronized void checkException() throws Exception {
77 if (err != null) {
78 throw new RuntimeException("Deferred", err);
79 }
80 }
81
82 public synchronized void threadFailed(Throwable t) {
83 if (err == null) err = t;
84 LOG.error("Failed!", err);
85 notify();
86 }
87
88 public synchronized void threadDone() {
89 threadDoneCount++;
90 }
91
92 public void setStopFlag(boolean s) throws Exception {
93 synchronized (this) {
94 stopped = s;
95 }
96 }
97
98 public void stop() throws Exception {
99 synchronized (this) {
100 stopped = true;
101 }
102 for (TestThread t : testThreads) {
103 t.join();
104 }
105 checkException();
106 }
107 }
108
109
110
111
112
113 public static abstract class TestThread extends Thread {
114 protected final TestContext ctx;
115 protected boolean stopped;
116
117 public TestThread(TestContext ctx) {
118 this.ctx = ctx;
119 }
120
121 public void run() {
122 try {
123 doWork();
124 } catch (Throwable t) {
125 ctx.threadFailed(t);
126 }
127 ctx.threadDone();
128 }
129
130 public abstract void doWork() throws Exception;
131
132 protected void stopTestThread() {
133 this.stopped = true;
134 }
135 }
136
137
138
139
140 public static abstract class RepeatingTestThread extends TestThread {
141 public RepeatingTestThread(TestContext ctx) {
142 super(ctx);
143 }
144
145 public final void doWork() throws Exception {
146 while (ctx.shouldRun() && !stopped) {
147 doAnAction();
148 }
149 }
150
151 public abstract void doAnAction() throws Exception;
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 public static <T> void assertOnFutures(List<Future<T>> threadResults)
176 throws InterruptedException, ExecutionException {
177 for (Future<T> threadResult : threadResults) {
178 try {
179 threadResult.get();
180 } catch (ExecutionException e) {
181 if (e.getCause() instanceof AssertionError) {
182 throw (AssertionError) e.getCause();
183 }
184 throw e;
185 }
186 }
187 }
188 }