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