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;
21
22 import java.io.IOException;
23 import java.security.PrivilegedAction;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentHashMap;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.fs.FileSystem;
33 import org.apache.hadoop.hbase.client.HConnectionManager;
34 import org.apache.hadoop.hbase.master.HMaster;
35 import org.apache.hadoop.hbase.regionserver.HRegion;
36 import org.apache.hadoop.hbase.regionserver.HRegionServer;
37 import org.apache.hadoop.hbase.util.Bytes;
38 import org.apache.hadoop.hbase.util.JVMClusterUtil;
39 import org.apache.hadoop.hbase.util.Threads;
40 import org.apache.hadoop.hdfs.DistributedFileSystem;
41 import org.apache.hadoop.io.MapWritable;
42 import org.apache.hadoop.security.UserGroupInformation;
43
44
45
46
47
48
49
50 public class MiniHBaseCluster {
51 static final Log LOG = LogFactory.getLog(MiniHBaseCluster.class.getName());
52 private Configuration conf;
53 public LocalHBaseCluster hbaseCluster;
54
55
56
57
58
59
60
61 public MiniHBaseCluster(Configuration conf, int numRegionServers)
62 throws IOException {
63 this.conf = conf;
64 conf.set(HConstants.MASTER_PORT, "0");
65 init(numRegionServers);
66 }
67
68
69
70
71 public static class MiniHBaseClusterMaster extends HMaster {
72 private final Map<HServerInfo, List<HMsg>> messages =
73 new ConcurrentHashMap<HServerInfo, List<HMsg>>();
74
75 private final Map<HServerInfo, IOException> exceptions =
76 new ConcurrentHashMap<HServerInfo, IOException>();
77
78 public MiniHBaseClusterMaster(final Configuration conf)
79 throws IOException {
80 super(conf);
81 }
82
83
84
85
86
87
88 void addMessage(final HServerInfo hsi, HMsg msg) {
89 synchronized(this.messages) {
90 List<HMsg> hmsgs = this.messages.get(hsi);
91 if (hmsgs == null) {
92 hmsgs = new ArrayList<HMsg>();
93 this.messages.put(hsi, hmsgs);
94 }
95 hmsgs.add(msg);
96 }
97 }
98
99 void addException(final HServerInfo hsi, final IOException ex) {
100 this.exceptions.put(hsi, ex);
101 }
102
103
104
105
106
107
108
109
110
111
112 @Override
113 protected HMsg[] adornRegionServerAnswer(final HServerInfo hsi,
114 final HMsg[] msgs) throws IOException {
115 IOException ex = this.exceptions.remove(hsi);
116 if (ex != null) {
117 throw ex;
118 }
119 HMsg [] answerMsgs = msgs;
120 synchronized (this.messages) {
121 List<HMsg> hmsgs = this.messages.get(hsi);
122 if (hmsgs != null && !hmsgs.isEmpty()) {
123 int size = answerMsgs.length;
124 HMsg [] newAnswerMsgs = new HMsg[size + hmsgs.size()];
125 System.arraycopy(answerMsgs, 0, newAnswerMsgs, 0, answerMsgs.length);
126 for (int i = 0; i < hmsgs.size(); i++) {
127 newAnswerMsgs[answerMsgs.length + i] = hmsgs.get(i);
128 }
129 answerMsgs = newAnswerMsgs;
130 hmsgs.clear();
131 }
132 }
133 return super.adornRegionServerAnswer(hsi, answerMsgs);
134 }
135 }
136
137
138
139
140
141
142
143 public static class MiniHBaseClusterRegionServer extends HRegionServer {
144 private Thread shutdownThread = null;
145 private UserGroupInformation user = null;
146
147 public MiniHBaseClusterRegionServer(Configuration conf)
148 throws IOException {
149 super(conf);
150 this.user = UserGroupInformation.getCurrentUser();
151 }
152
153 public void setHServerInfo(final HServerInfo hsi) {
154 this.serverInfo = hsi;
155 }
156
157
158
159
160
161
162
163
164
165 @Override
166 protected void init(MapWritable c) throws IOException {
167 super.init(c);
168
169 this.shutdownThread = new SingleFileSystemShutdownThread(getFileSystem());
170 }
171
172 @Override
173 public void run() {
174 try {
175 this.user.doAs(new PrivilegedAction<Object>(){
176 public Object run() {
177 runRegionServer();
178 return null;
179 }
180 });
181 } finally {
182
183 if (this.shutdownThread != null) {
184 this.shutdownThread.start();
185 Threads.shutdown(this.shutdownThread, 30000);
186 }
187 }
188 }
189
190 private void runRegionServer() {
191 super.run();
192 }
193
194 public void kill() {
195 super.kill();
196 }
197 }
198
199
200
201
202
203 static class SingleFileSystemShutdownThread extends Thread {
204 private final FileSystem fs;
205 SingleFileSystemShutdownThread(final FileSystem fs) {
206 super("Shutdown of " + fs);
207 this.fs = fs;
208 }
209 @Override
210 public void run() {
211 try {
212 LOG.info("Hook closing fs=" + this.fs);
213 this.fs.close();
214 } catch (IOException e) {
215 LOG.warn("Running hook", e);
216 }
217 }
218 }
219
220 private void init(final int nRegionNodes) throws IOException {
221 try {
222
223 hbaseCluster = new LocalHBaseCluster(conf, nRegionNodes,
224 MiniHBaseCluster.MiniHBaseClusterMaster.class,
225 MiniHBaseCluster.MiniHBaseClusterRegionServer.class);
226 hbaseCluster.startup();
227 } catch(IOException e) {
228 shutdown();
229 throw e;
230 }
231 }
232
233
234
235
236
237
238
239 public JVMClusterUtil.RegionServerThread startRegionServer() throws IOException {
240 JVMClusterUtil.RegionServerThread t = this.hbaseCluster.addRegionServer();
241 t.start();
242 t.waitForServerOnline();
243 return t;
244 }
245
246
247
248
249
250 public HServerAddress getHMasterAddress() {
251 return this.hbaseCluster.getMaster().getMasterAddress();
252 }
253
254
255
256
257 public HMaster getMaster() {
258 return this.hbaseCluster.getMaster();
259 }
260
261
262
263
264
265 public String abortRegionServer(int serverNumber) {
266 HRegionServer server = getRegionServer(serverNumber);
267 LOG.info("Aborting " + server.toString());
268 server.abort("Aborting for tests", new Exception("Trace info"));
269 return server.toString();
270 }
271
272
273
274
275
276
277
278 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber) {
279 return stopRegionServer(serverNumber, true);
280 }
281
282
283
284
285
286
287
288
289
290
291
292 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber,
293 final boolean shutdownFS) {
294 JVMClusterUtil.RegionServerThread server =
295 hbaseCluster.getRegionServers().get(serverNumber);
296 LOG.info("Stopping " + server.toString());
297 server.getRegionServer().stop();
298 return server;
299 }
300
301
302
303
304
305
306
307 public String waitOnRegionServer(final int serverNumber) {
308 return this.hbaseCluster.waitOnRegionServer(serverNumber);
309 }
310
311
312
313
314 public void join() {
315 this.hbaseCluster.join();
316 }
317
318
319
320
321
322 public void shutdown() throws IOException {
323 if (this.hbaseCluster != null) {
324 this.hbaseCluster.shutdown();
325 }
326 HConnectionManager.deleteAllConnections(false);
327 }
328
329
330
331
332
333 public void flushcache() throws IOException {
334 for (JVMClusterUtil.RegionServerThread t:
335 this.hbaseCluster.getRegionServers()) {
336 for(HRegion r: t.getRegionServer().getOnlineRegions()) {
337 r.flushcache();
338 }
339 }
340 }
341
342
343
344
345
346 public void flushcache(byte [] tableName) throws IOException {
347 for (JVMClusterUtil.RegionServerThread t:
348 this.hbaseCluster.getRegionServers()) {
349 for(HRegion r: t.getRegionServer().getOnlineRegions()) {
350 if(Bytes.equals(r.getTableDesc().getName(), tableName)) {
351 r.flushcache();
352 }
353 }
354 }
355 }
356
357
358
359
360 public List<JVMClusterUtil.RegionServerThread> getRegionServerThreads() {
361 return this.hbaseCluster.getRegionServers();
362 }
363
364
365
366
367 public List<JVMClusterUtil.RegionServerThread> getLiveRegionServerThreads() {
368 return this.hbaseCluster.getLiveRegionServers();
369 }
370
371
372
373
374
375
376 public HRegionServer getRegionServer(int serverNumber) {
377 return hbaseCluster.getRegionServer(serverNumber);
378 }
379
380 public List<HRegion> getRegions(byte[] tableName) {
381 List<HRegion> ret = new ArrayList<HRegion>();
382 for (JVMClusterUtil.RegionServerThread rst : getRegionServerThreads()) {
383 HRegionServer hrs = rst.getRegionServer();
384 for (HRegion region : hrs.getOnlineRegions()) {
385 if (Bytes.equals(region.getTableDesc().getName(), tableName)) {
386 ret.add(region);
387 }
388 }
389 }
390 return ret;
391 }
392
393
394
395
396
397 public int getServerWithMeta() {
398 return getServerWith(HRegionInfo.FIRST_META_REGIONINFO.getRegionName());
399 }
400
401
402
403
404
405
406
407 public int getServerWith(byte[] regionName) {
408 int index = -1;
409 int count = 0;
410 for (JVMClusterUtil.RegionServerThread rst: getRegionServerThreads()) {
411 HRegionServer hrs = rst.getRegionServer();
412 HRegion metaRegion =
413 hrs.getOnlineRegion(regionName);
414 if (metaRegion != null) {
415 index = count;
416 break;
417 }
418 count++;
419 }
420 return index;
421 }
422
423
424
425
426
427
428
429 public void addExceptionToSendRegionServer(final int serverNumber,
430 IOException ex) throws IOException {
431 MiniHBaseClusterRegionServer hrs =
432 (MiniHBaseClusterRegionServer)getRegionServer(serverNumber);
433 addExceptionToSendRegionServer(hrs, ex);
434 }
435
436
437
438
439
440
441
442 public void addExceptionToSendRegionServer(
443 final MiniHBaseClusterRegionServer hrs, IOException ex)
444 throws IOException {
445 ((MiniHBaseClusterMaster)getMaster()).addException(hrs.getHServerInfo(),ex);
446 }
447
448
449
450
451
452
453
454
455 public void addMessageToSendRegionServer(final int serverNumber,
456 final HMsg msg)
457 throws IOException {
458 MiniHBaseClusterRegionServer hrs =
459 (MiniHBaseClusterRegionServer)getRegionServer(serverNumber);
460 addMessageToSendRegionServer(hrs, msg);
461 }
462
463
464
465
466
467
468
469
470 public void addMessageToSendRegionServer(final MiniHBaseClusterRegionServer hrs,
471 final HMsg msg)
472 throws IOException {
473 ((MiniHBaseClusterMaster)getMaster()).addMessage(hrs.getHServerInfo(), msg);
474 }
475 }