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.client.HConnectionManager;
33 import org.apache.hadoop.hbase.master.HMaster;
34 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
35 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ClientService;
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)
113 throws IOException, InterruptedException {
114 super(conf);
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 @Deprecated
236 public void startRegionServer(String hostname) throws IOException {
237 this.startRegionServer();
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 waitForRegionServerToStop(ServerName serverName, long timeout) throws IOException {
263
264 waitOnRegionServer(getRegionServerIndex(serverName));
265 }
266
267 @Override
268 public void startZkNode(String hostname, int port) throws IOException {
269 LOG.warn("Starting zookeeper nodes on mini cluster is not supported");
270 }
271
272 @Override
273 public void killZkNode(ServerName serverName) throws IOException {
274 LOG.warn("Aborting zookeeper nodes on mini cluster is not supported");
275 }
276
277 @Override
278 public void stopZkNode(ServerName serverName) throws IOException {
279 LOG.warn("Stopping zookeeper nodes on mini cluster is not supported");
280 }
281
282 @Override
283 public void waitForZkNodeToStart(ServerName serverName, long timeout) throws IOException {
284 LOG.warn("Waiting for zookeeper nodes to start on mini cluster is not supported");
285 }
286
287 @Override
288 public void waitForZkNodeToStop(ServerName serverName, long timeout) throws IOException {
289 LOG.warn("Waiting for zookeeper nodes to stop on mini cluster is not supported");
290 }
291
292 @Override
293 public void startDataNode(ServerName serverName) throws IOException {
294 LOG.warn("Starting datanodes on mini cluster is not supported");
295 }
296
297 @Override
298 public void killDataNode(ServerName serverName) throws IOException {
299 LOG.warn("Aborting datanodes on mini cluster is not supported");
300 }
301
302 @Override
303 public void stopDataNode(ServerName serverName) throws IOException {
304 LOG.warn("Stopping datanodes on mini cluster is not supported");
305 }
306
307 @Override
308 public void waitForDataNodeToStart(ServerName serverName, long timeout) throws IOException {
309 LOG.warn("Waiting for datanodes to start on mini cluster is not supported");
310 }
311
312 @Override
313 public void waitForDataNodeToStop(ServerName serverName, long timeout) throws IOException {
314 LOG.warn("Waiting for datanodes to stop on mini cluster is not supported");
315 }
316
317 @Override
318 public void startMaster(String hostname, int port) throws IOException {
319 this.startMaster();
320 }
321
322 @Override
323 public void killMaster(ServerName serverName) throws IOException {
324 abortMaster(getMasterIndex(serverName));
325 }
326
327 @Override
328 public void stopMaster(ServerName serverName) throws IOException {
329 stopMaster(getMasterIndex(serverName));
330 }
331
332 @Override
333 public void waitForMasterToStop(ServerName serverName, long timeout) throws IOException {
334
335 waitOnMaster(getMasterIndex(serverName));
336 }
337
338
339
340
341
342
343
344 public JVMClusterUtil.RegionServerThread startRegionServer()
345 throws IOException {
346 final Configuration newConf = HBaseConfiguration.create(conf);
347 User rsUser =
348 HBaseTestingUtility.getDifferentUser(newConf, ".hfs."+index++);
349 JVMClusterUtil.RegionServerThread t = null;
350 try {
351 t = hbaseCluster.addRegionServer(
352 newConf, hbaseCluster.getRegionServers().size(), rsUser);
353 t.start();
354 t.waitForServerOnline();
355 } catch (InterruptedException ie) {
356 throw new IOException("Interrupted adding regionserver to cluster", ie);
357 }
358 return t;
359 }
360
361
362
363
364
365 public String abortRegionServer(int serverNumber) {
366 HRegionServer server = getRegionServer(serverNumber);
367 LOG.info("Aborting " + server.toString());
368 server.abort("Aborting for tests", new Exception("Trace info"));
369 return server.toString();
370 }
371
372
373
374
375
376
377
378 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber) {
379 return stopRegionServer(serverNumber, true);
380 }
381
382
383
384
385
386
387
388
389
390
391
392 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber,
393 final boolean shutdownFS) {
394 JVMClusterUtil.RegionServerThread server =
395 hbaseCluster.getRegionServers().get(serverNumber);
396 LOG.info("Stopping " + server.toString());
397 server.getRegionServer().stop("Stopping rs " + serverNumber);
398 return server;
399 }
400
401
402
403
404
405
406
407 public String waitOnRegionServer(final int serverNumber) {
408 return this.hbaseCluster.waitOnRegionServer(serverNumber);
409 }
410
411
412
413
414
415
416
417
418 public JVMClusterUtil.MasterThread startMaster() throws IOException {
419 Configuration c = HBaseConfiguration.create(conf);
420 User user =
421 HBaseTestingUtility.getDifferentUser(c, ".hfs."+index++);
422
423 JVMClusterUtil.MasterThread t = null;
424 try {
425 t = hbaseCluster.addMaster(c, hbaseCluster.getMasters().size(), user);
426 t.start();
427 } catch (InterruptedException ie) {
428 throw new IOException("Interrupted adding master to cluster", ie);
429 }
430 return t;
431 }
432
433
434
435
436
437 public HMaster getMaster() {
438 return this.hbaseCluster.getActiveMaster();
439 }
440
441
442
443
444
445 public HMaster getMaster(final int serverNumber) {
446 return this.hbaseCluster.getMaster(serverNumber);
447 }
448
449
450
451
452
453 public String abortMaster(int serverNumber) {
454 HMaster server = getMaster(serverNumber);
455 LOG.info("Aborting " + server.toString());
456 server.abort("Aborting for tests", new Exception("Trace info"));
457 return server.toString();
458 }
459
460
461
462
463
464
465
466 public JVMClusterUtil.MasterThread stopMaster(int serverNumber) {
467 return stopMaster(serverNumber, true);
468 }
469
470
471
472
473
474
475
476
477
478
479
480 public JVMClusterUtil.MasterThread stopMaster(int serverNumber,
481 final boolean shutdownFS) {
482 JVMClusterUtil.MasterThread server =
483 hbaseCluster.getMasters().get(serverNumber);
484 LOG.info("Stopping " + server.toString());
485 server.getMaster().stop("Stopping master " + serverNumber);
486 return server;
487 }
488
489
490
491
492
493
494
495 public String waitOnMaster(final int serverNumber) {
496 return this.hbaseCluster.waitOnMaster(serverNumber);
497 }
498
499
500
501
502
503
504
505
506
507 public boolean waitForActiveAndReadyMaster(long timeout) throws IOException {
508 List<JVMClusterUtil.MasterThread> mts;
509 long start = System.currentTimeMillis();
510 while (!(mts = getMasterThreads()).isEmpty()
511 && (System.currentTimeMillis() - start) < timeout) {
512 for (JVMClusterUtil.MasterThread mt : mts) {
513 if (mt.getMaster().isActiveMaster() && mt.getMaster().isInitialized()) {
514 return true;
515 }
516 }
517
518 Threads.sleep(100);
519 }
520 return false;
521 }
522
523
524
525
526 public List<JVMClusterUtil.MasterThread> getMasterThreads() {
527 return this.hbaseCluster.getMasters();
528 }
529
530
531
532
533 public List<JVMClusterUtil.MasterThread> getLiveMasterThreads() {
534 return this.hbaseCluster.getLiveMasters();
535 }
536
537
538
539
540 public void join() {
541 this.hbaseCluster.join();
542 }
543
544
545
546
547
548 public void shutdown() throws IOException {
549 if (this.hbaseCluster != null) {
550 this.hbaseCluster.shutdown();
551 }
552 HConnectionManager.deleteAllConnections(false);
553 }
554
555 @Override
556 public void close() throws IOException {
557 }
558
559 @Override
560 public ClusterStatus getClusterStatus() throws IOException {
561 HMaster master = getMaster();
562 return master == null ? null : master.getClusterStatus();
563 }
564
565
566
567
568
569 public void flushcache() throws IOException {
570 for (JVMClusterUtil.RegionServerThread t:
571 this.hbaseCluster.getRegionServers()) {
572 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
573 r.flushcache();
574 }
575 }
576 }
577
578
579
580
581
582 public void flushcache(TableName tableName) throws IOException {
583 for (JVMClusterUtil.RegionServerThread t:
584 this.hbaseCluster.getRegionServers()) {
585 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
586 if(r.getTableDesc().getTableName().equals(tableName)) {
587 r.flushcache();
588 }
589 }
590 }
591 }
592
593
594
595
596
597 public void compact(boolean major) throws IOException {
598 for (JVMClusterUtil.RegionServerThread t:
599 this.hbaseCluster.getRegionServers()) {
600 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
601 r.compactStores(major);
602 }
603 }
604 }
605
606
607
608
609
610 public void compact(TableName tableName, boolean major) throws IOException {
611 for (JVMClusterUtil.RegionServerThread t:
612 this.hbaseCluster.getRegionServers()) {
613 for(HRegion r: t.getRegionServer().getOnlineRegionsLocalContext()) {
614 if(r.getTableDesc().getTableName().equals(tableName)) {
615 r.compactStores(major);
616 }
617 }
618 }
619 }
620
621
622
623
624 public List<JVMClusterUtil.RegionServerThread> getRegionServerThreads() {
625 return this.hbaseCluster.getRegionServers();
626 }
627
628
629
630
631 public List<JVMClusterUtil.RegionServerThread> getLiveRegionServerThreads() {
632 return this.hbaseCluster.getLiveRegionServers();
633 }
634
635
636
637
638
639
640 public HRegionServer getRegionServer(int serverNumber) {
641 return hbaseCluster.getRegionServer(serverNumber);
642 }
643
644 public List<HRegion> getRegions(byte[] tableName) {
645 return getRegions(TableName.valueOf(tableName));
646 }
647
648 public List<HRegion> getRegions(TableName tableName) {
649 List<HRegion> ret = new ArrayList<HRegion>();
650 for (JVMClusterUtil.RegionServerThread rst : getRegionServerThreads()) {
651 HRegionServer hrs = rst.getRegionServer();
652 for (HRegion region : hrs.getOnlineRegionsLocalContext()) {
653 if (region.getTableDesc().getTableName().equals(tableName)) {
654 ret.add(region);
655 }
656 }
657 }
658 return ret;
659 }
660
661
662
663
664
665 public int getServerWithMeta() {
666 return getServerWith(HRegionInfo.FIRST_META_REGIONINFO.getRegionName());
667 }
668
669
670
671
672
673
674
675 public int getServerWith(byte[] regionName) {
676 int index = -1;
677 int count = 0;
678 for (JVMClusterUtil.RegionServerThread rst: getRegionServerThreads()) {
679 HRegionServer hrs = rst.getRegionServer();
680 HRegion metaRegion =
681 hrs.getOnlineRegion(regionName);
682 if (metaRegion != null) {
683 index = count;
684 break;
685 }
686 count++;
687 }
688 return index;
689 }
690
691 @Override
692 public ServerName getServerHoldingRegion(byte[] regionName) throws IOException {
693 int index = getServerWith(regionName);
694 if (index < 0) {
695 return null;
696 }
697 return getRegionServer(index).getServerName();
698 }
699
700
701
702
703
704
705
706 public long countServedRegions() {
707 long count = 0;
708 for (JVMClusterUtil.RegionServerThread rst : getLiveRegionServerThreads()) {
709 count += rst.getRegionServer().getNumberOfOnlineRegions();
710 }
711 return count;
712 }
713
714
715
716
717
718 public void killAll() {
719 for (RegionServerThread rst : getRegionServerThreads()) {
720 rst.getRegionServer().abort("killAll");
721 }
722 for (MasterThread masterThread : getMasterThreads()) {
723 masterThread.getMaster().abort("killAll", new Throwable());
724 }
725 }
726
727 @Override
728 public void waitUntilShutDown() {
729 this.hbaseCluster.join();
730 }
731
732 public List<HRegion> findRegionsForTable(TableName tableName) {
733 ArrayList<HRegion> ret = new ArrayList<HRegion>();
734 for (JVMClusterUtil.RegionServerThread rst : getRegionServerThreads()) {
735 HRegionServer hrs = rst.getRegionServer();
736 for (HRegion region : hrs.getOnlineRegions(tableName)) {
737 if (region.getTableDesc().getTableName().equals(tableName)) {
738 ret.add(region);
739 }
740 }
741 }
742 return ret;
743 }
744
745
746 protected int getRegionServerIndex(ServerName serverName) {
747
748 List<RegionServerThread> servers = getRegionServerThreads();
749 for (int i=0; i < servers.size(); i++) {
750 if (servers.get(i).getRegionServer().getServerName().equals(serverName)) {
751 return i;
752 }
753 }
754 return -1;
755 }
756
757 protected int getMasterIndex(ServerName serverName) {
758 List<MasterThread> masters = getMasterThreads();
759 for (int i = 0; i < masters.size(); i++) {
760 if (masters.get(i).getMaster().getServerName().equals(serverName)) {
761 return i;
762 }
763 }
764 return -1;
765 }
766
767 @Override
768 public AdminService.BlockingInterface getAdminProtocol(ServerName serverName) throws IOException {
769 return getRegionServer(getRegionServerIndex(serverName));
770 }
771
772 @Override
773 public ClientService.BlockingInterface getClientProtocol(ServerName serverName)
774 throws IOException {
775 return getRegionServer(getRegionServerIndex(serverName));
776 }
777 }