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