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