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
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.hbase.ipc.HRegionInterface;
32 import org.apache.hadoop.hbase.ipc.HMasterInterface;
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.security.User;
38 import org.apache.hadoop.hbase.util.Bytes;
39 import org.apache.hadoop.hbase.util.JVMClusterUtil;
40 import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread;
41 import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
42 import org.apache.hadoop.hbase.util.Threads;
43 import org.apache.hadoop.io.MapWritable;
44
45
46
47
48
49
50
51 public class MiniHBaseCluster extends HBaseCluster {
52 static final Log LOG = LogFactory.getLog(MiniHBaseCluster.class.getName());
53 public LocalHBaseCluster hbaseCluster;
54 private static int index;
55
56
57
58
59
60
61
62 public MiniHBaseCluster(Configuration conf, int numRegionServers)
63 throws IOException, InterruptedException {
64 this(conf, 1, numRegionServers);
65 }
66
67
68
69
70
71
72
73
74 public MiniHBaseCluster(Configuration conf, int numMasters,
75 int numRegionServers)
76 throws IOException, InterruptedException {
77 this(conf, numMasters, numRegionServers, null, null);
78 }
79
80 public MiniHBaseCluster(Configuration conf, int numMasters, int numRegionServers,
81 Class<? extends HMaster> masterClass,
82 Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> regionserverClass)
83 throws IOException, InterruptedException {
84 super(conf);
85 conf.set(HConstants.MASTER_PORT, "0");
86 init(numMasters, numRegionServers, masterClass, regionserverClass);
87 this.initialClusterStatus = getClusterStatus();
88 }
89
90 public Configuration getConfiguration() {
91 return this.conf;
92 }
93
94
95
96
97
98
99
100 public static class MiniHBaseClusterRegionServer extends HRegionServer {
101 private Thread shutdownThread = null;
102 private User user = null;
103 public static boolean TEST_SKIP_CLOSE = false;
104
105 public MiniHBaseClusterRegionServer(Configuration conf)
106 throws IOException, InterruptedException {
107 super(conf);
108 this.user = User.getCurrent();
109 }
110
111
112
113
114
115
116
117
118
119 @Override
120 protected void handleReportForDutyResponse(MapWritable c) throws IOException {
121 super.handleReportForDutyResponse(c);
122
123 this.shutdownThread = new SingleFileSystemShutdownThread(getFileSystem());
124 }
125
126 @Override
127 public void run() {
128 try {
129 this.user.runAs(new PrivilegedAction<Object>(){
130 public Object run() {
131 runRegionServer();
132 return null;
133 }
134 });
135 } catch (Throwable t) {
136 LOG.error("Exception in run", t);
137 } finally {
138
139 if (this.shutdownThread != null) {
140 this.shutdownThread.start();
141 Threads.shutdown(this.shutdownThread, 30000);
142 }
143 }
144 }
145
146 private void runRegionServer() {
147 super.run();
148 }
149
150 @Override
151 public void kill() {
152 super.kill();
153 }
154
155 public void abort(final String reason, final Throwable cause) {
156 this.user.runAs(new PrivilegedAction<Object>() {
157 public Object run() {
158 abortRegionServer(reason, cause);
159 return null;
160 }
161 });
162 }
163
164 private void abortRegionServer(String reason, Throwable cause) {
165 super.abort(reason, cause);
166 }
167 }
168
169
170
171
172
173 static class SingleFileSystemShutdownThread extends Thread {
174 private final FileSystem fs;
175 SingleFileSystemShutdownThread(final FileSystem fs) {
176 super("Shutdown of " + fs);
177 this.fs = fs;
178 }
179 @Override
180 public void run() {
181 try {
182 LOG.info("Hook closing fs=" + this.fs);
183 this.fs.close();
184 } catch (NullPointerException npe) {
185 LOG.debug("Need to fix these: " + npe.toString());
186 } catch (IOException e) {
187 LOG.warn("Running hook", e);
188 }
189 }
190 }
191
192 private void init(final int nMasterNodes, final int nRegionNodes,
193 Class<? extends HMaster> masterClass,
194 Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> regionserverClass)
195 throws IOException, InterruptedException {
196 try {
197 if (masterClass == null){
198 masterClass = HMaster.class;
199 }
200 if (regionserverClass == null){
201 regionserverClass = MiniHBaseCluster.MiniHBaseClusterRegionServer.class;
202 }
203
204
205 hbaseCluster = new LocalHBaseCluster(conf, nMasterNodes, 0,
206 masterClass, regionserverClass);
207
208
209 for (int i=0; i<nRegionNodes; i++) {
210 Configuration rsConf = HBaseConfiguration.create(conf);
211 User user = HBaseTestingUtility.getDifferentUser(rsConf,
212 ".hfs."+index++);
213 hbaseCluster.addRegionServer(rsConf, i, user);
214 }
215
216 hbaseCluster.startup();
217 } catch (IOException e) {
218 shutdown();
219 throw e;
220 } catch (Throwable t) {
221 LOG.error("Error starting cluster", t);
222 shutdown();
223 throw new IOException("Shutting down", t);
224 }
225 }
226
227 @Override
228 public void startRegionServer(String hostname) throws IOException {
229 this.startRegionServer();
230 }
231
232 @Override
233 public void killRegionServer(ServerName serverName) throws IOException {
234 HRegionServer server = getRegionServer(getRegionServerIndex(serverName));
235 if (server instanceof MiniHBaseClusterRegionServer) {
236 LOG.info("Killing " + server.toString());
237 ((MiniHBaseClusterRegionServer) server).kill();
238 } else {
239 abortRegionServer(getRegionServerIndex(serverName));
240 }
241 }
242
243 @Override
244 public void stopRegionServer(ServerName serverName) throws IOException {
245 stopRegionServer(getRegionServerIndex(serverName));
246 }
247
248 @Override
249 public void waitForRegionServerToStop(ServerName serverName, long timeout) throws IOException {
250
251 waitOnRegionServer(getRegionServerIndex(serverName));
252 }
253
254 @Override
255 public void startMaster(String hostname) throws IOException {
256 this.startMaster();
257 }
258
259 @Override
260 public void killMaster(ServerName serverName) throws IOException {
261 abortMaster(getMasterIndex(serverName));
262 }
263
264 @Override
265 public void stopMaster(ServerName serverName) throws IOException {
266 stopMaster(getMasterIndex(serverName));
267 }
268
269 @Override
270 public void waitForMasterToStop(ServerName serverName, long timeout) throws IOException {
271
272 waitOnMaster(getMasterIndex(serverName));
273 }
274
275
276
277
278
279
280
281 public JVMClusterUtil.RegionServerThread startRegionServer()
282 throws IOException {
283 final Configuration newConf = HBaseConfiguration.create(conf);
284 User rsUser =
285 HBaseTestingUtility.getDifferentUser(newConf, ".hfs."+index++);
286 JVMClusterUtil.RegionServerThread t = null;
287 try {
288 t = hbaseCluster.addRegionServer(
289 newConf, hbaseCluster.getRegionServers().size(), rsUser);
290 t.start();
291 t.waitForServerOnline();
292 } catch (InterruptedException ie) {
293 throw new IOException("Interrupted adding regionserver to cluster", ie);
294 }
295 return t;
296 }
297
298
299
300
301
302 public String abortRegionServer(int serverNumber) {
303 HRegionServer server = getRegionServer(serverNumber);
304 LOG.info("Aborting " + server.toString());
305 server.abort("Aborting for tests", new Exception("Trace info"));
306 return server.toString();
307 }
308
309
310
311
312
313
314
315 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber) {
316 return stopRegionServer(serverNumber, true);
317 }
318
319
320
321
322
323
324
325
326
327
328
329 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber,
330 final boolean shutdownFS) {
331 JVMClusterUtil.RegionServerThread server =
332 hbaseCluster.getRegionServers().get(serverNumber);
333 LOG.info("Stopping " + server.toString());
334 server.getRegionServer().stop("Stopping rs " + serverNumber);
335 return server;
336 }
337
338
339
340
341
342
343
344 public String waitOnRegionServer(final int serverNumber) {
345 return this.hbaseCluster.waitOnRegionServer(serverNumber);
346 }
347
348
349
350
351
352
353
354
355 public JVMClusterUtil.MasterThread startMaster() throws IOException {
356 Configuration c = HBaseConfiguration.create(conf);
357 User user =
358 HBaseTestingUtility.getDifferentUser(c, ".hfs."+index++);
359
360 JVMClusterUtil.MasterThread t = null;
361 try {
362 t = hbaseCluster.addMaster(c, hbaseCluster.getMasters().size(), user);
363 t.start();
364 } catch (InterruptedException ie) {
365 throw new IOException("Interrupted adding master to cluster", ie);
366 }
367 return t;
368 }
369
370 @Override
371 public HMasterInterface getMasterAdmin() {
372 return this.hbaseCluster.getActiveMaster();
373 }
374
375
376
377
378
379 public HMaster getMaster() {
380 return this.hbaseCluster.getActiveMaster();
381 }
382
383
384
385
386
387 public HMaster getMaster(final int serverNumber) {
388 return this.hbaseCluster.getMaster(serverNumber);
389 }
390
391
392
393
394
395 public String abortMaster(int serverNumber) {
396 HMaster server = getMaster(serverNumber);
397 LOG.info("Aborting " + server.toString());
398 server.abort("Aborting for tests", new Exception("Trace info"));
399 return server.toString();
400 }
401
402
403
404
405
406
407
408 public JVMClusterUtil.MasterThread stopMaster(int serverNumber) {
409 return stopMaster(serverNumber, true);
410 }
411
412
413
414
415
416
417
418
419
420
421
422 public JVMClusterUtil.MasterThread stopMaster(int serverNumber,
423 final boolean shutdownFS) {
424 JVMClusterUtil.MasterThread server =
425 hbaseCluster.getMasters().get(serverNumber);
426 LOG.info("Stopping " + server.toString());
427 server.getMaster().stop("Stopping master " + serverNumber);
428 return server;
429 }
430
431
432
433
434
435
436
437 public String waitOnMaster(final int serverNumber) {
438 return this.hbaseCluster.waitOnMaster(serverNumber);
439 }
440
441
442
443
444
445
446
447
448
449 public boolean waitForActiveAndReadyMaster(long timeout) throws IOException {
450 List<JVMClusterUtil.MasterThread> mts;
451 long start = System.currentTimeMillis();
452 while (!(mts = getMasterThreads()).isEmpty()
453 && (System.currentTimeMillis() - start) < timeout) {
454 for (JVMClusterUtil.MasterThread mt : mts) {
455 if (mt.getMaster().isActiveMaster() && mt.getMaster().isInitialized()) {
456 return true;
457 }
458 }
459
460 Threads.sleep(100);
461 }
462 return false;
463 }
464
465
466
467
468 public List<JVMClusterUtil.MasterThread> getMasterThreads() {
469 return this.hbaseCluster.getMasters();
470 }
471
472
473
474
475 public List<JVMClusterUtil.MasterThread> getLiveMasterThreads() {
476 return this.hbaseCluster.getLiveMasters();
477 }
478
479
480
481
482 public void join() {
483 this.hbaseCluster.join();
484 }
485
486
487
488
489
490 public void shutdown() throws IOException {
491 if (this.hbaseCluster != null) {
492 this.hbaseCluster.shutdown();
493 }
494 HConnectionManager.deleteAllConnections();
495 }
496
497 @Override
498 public void close() throws IOException {
499 }
500
501 @Override
502 public ClusterStatus getClusterStatus() throws IOException {
503 HMaster master = getMaster();
504 return master == null ? null : master.getClusterStatus();
505 }
506
507
508
509
510
511 public void flushcache() throws IOException {
512 for (JVMClusterUtil.RegionServerThread t:
513 this.hbaseCluster.getRegionServers()) {
514 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
515 r.flushcache();
516 }
517 }
518 }
519
520
521
522
523
524 public void flushcache(byte [] tableName) throws IOException {
525 for (JVMClusterUtil.RegionServerThread t:
526 this.hbaseCluster.getRegionServers()) {
527 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
528 if(Bytes.equals(r.getTableDesc().getName(), tableName)) {
529 r.flushcache();
530 }
531 }
532 }
533 }
534
535
536
537
538
539 public void compact(boolean major) throws IOException {
540 for (JVMClusterUtil.RegionServerThread t:
541 this.hbaseCluster.getRegionServers()) {
542 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
543 r.compactStores(major);
544 }
545 }
546 }
547
548
549
550
551
552 public void compact(byte [] tableName, boolean major) throws IOException {
553 for (JVMClusterUtil.RegionServerThread t:
554 this.hbaseCluster.getRegionServers()) {
555 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
556 if(Bytes.equals(r.getTableDesc().getName(), tableName)) {
557 r.compactStores(major);
558 }
559 }
560 }
561 }
562
563
564
565
566 public List<JVMClusterUtil.RegionServerThread> getRegionServerThreads() {
567 return this.hbaseCluster.getRegionServers();
568 }
569
570
571
572
573 public List<JVMClusterUtil.RegionServerThread> getLiveRegionServerThreads() {
574 return this.hbaseCluster.getLiveRegionServers();
575 }
576
577
578
579
580
581
582 public HRegionServer getRegionServer(int serverNumber) {
583 return hbaseCluster.getRegionServer(serverNumber);
584 }
585
586 public List<HRegion> getRegions(byte[] tableName) {
587 List<HRegion> ret = new ArrayList<HRegion>();
588 for (JVMClusterUtil.RegionServerThread rst : getRegionServerThreads()) {
589 HRegionServer hrs = rst.getRegionServer();
590 for (HRegion region : hrs.getOnlineRegionsLocalContext()) {
591 if (Bytes.equals(region.getTableDesc().getName(), tableName)) {
592 ret.add(region);
593 }
594 }
595 }
596 return ret;
597 }
598
599
600
601
602
603 public int getServerWithMeta() {
604 return getServerWith(HRegionInfo.FIRST_META_REGIONINFO.getRegionName());
605 }
606
607
608
609
610
611
612
613 public int getServerWith(byte[] regionName) {
614 int index = -1;
615 int count = 0;
616 for (JVMClusterUtil.RegionServerThread rst: getRegionServerThreads()) {
617 HRegionServer hrs = rst.getRegionServer();
618 HRegion metaRegion =
619 hrs.getOnlineRegion(regionName);
620 if (metaRegion != null) {
621 index = count;
622 break;
623 }
624 count++;
625 }
626 return index;
627 }
628
629 @Override
630 public ServerName getServerHoldingRegion(byte[] regionName) throws IOException {
631 int index = getServerWith(regionName);
632 if (index < 0) {
633 return null;
634 }
635 return getRegionServer(index).getServerName();
636 }
637
638
639
640
641
642
643
644 public long countServedRegions() {
645 long count = 0;
646 for (JVMClusterUtil.RegionServerThread rst : getLiveRegionServerThreads()) {
647 count += rst.getRegionServer().getNumberOfOnlineRegions();
648 }
649 return count;
650 }
651
652 @Override
653 public void waitUntilShutDown() {
654 this.hbaseCluster.join();
655 }
656
657 protected int getRegionServerIndex(ServerName serverName) {
658
659 List<RegionServerThread> servers = getRegionServerThreads();
660 for (int i=0; i < servers.size(); i++) {
661 if (servers.get(i).getRegionServer().getServerName().equals(serverName)) {
662 return i;
663 }
664 }
665 return -1;
666 }
667
668 protected int getMasterIndex(ServerName serverName) {
669 List<MasterThread> masters = getMasterThreads();
670 for (int i = 0; i < masters.size(); i++) {
671 if (masters.get(i).getMaster().getServerName().equals(serverName)) {
672 return i;
673 }
674 }
675 return -1;
676 }
677 }