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.master;
21
22 import java.io.IOException;
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.InvocationTargetException;
25 import java.net.InetSocketAddress;
26 import java.net.UnknownHostException;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.concurrent.atomic.AtomicReference;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.hbase.Chore;
37 import org.apache.hadoop.hbase.ClusterStatus;
38 import org.apache.hadoop.hbase.HColumnDescriptor;
39 import org.apache.hadoop.hbase.HConstants;
40 import org.apache.hadoop.hbase.HMsg;
41 import org.apache.hadoop.hbase.HRegionInfo;
42 import org.apache.hadoop.hbase.HServerAddress;
43 import org.apache.hadoop.hbase.HServerInfo;
44 import org.apache.hadoop.hbase.HTableDescriptor;
45 import org.apache.hadoop.hbase.MasterNotRunningException;
46 import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException;
47 import org.apache.hadoop.hbase.Server;
48 import org.apache.hadoop.hbase.TableExistsException;
49 import org.apache.hadoop.hbase.TableNotDisabledException;
50 import org.apache.hadoop.hbase.TableNotFoundException;
51 import org.apache.hadoop.hbase.UnknownRegionException;
52 import org.apache.hadoop.hbase.catalog.CatalogTracker;
53 import org.apache.hadoop.hbase.catalog.MetaEditor;
54 import org.apache.hadoop.hbase.catalog.MetaReader;
55 import org.apache.hadoop.hbase.client.HConnection;
56 import org.apache.hadoop.hbase.client.HConnectionManager;
57 import org.apache.hadoop.hbase.client.MetaScanner;
58 import org.apache.hadoop.hbase.client.Result;
59 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
60 import org.apache.hadoop.hbase.executor.ExecutorService;
61 import org.apache.hadoop.hbase.executor.ExecutorService.ExecutorType;
62 import org.apache.hadoop.hbase.ipc.HBaseRPC;
63 import org.apache.hadoop.hbase.ipc.HBaseRPCProtocolVersion;
64 import org.apache.hadoop.hbase.ipc.HBaseServer;
65 import org.apache.hadoop.hbase.ipc.HMasterInterface;
66 import org.apache.hadoop.hbase.ipc.HMasterRegionInterface;
67 import org.apache.hadoop.hbase.master.LoadBalancer.RegionPlan;
68 import org.apache.hadoop.hbase.master.handler.DeleteTableHandler;
69 import org.apache.hadoop.hbase.master.handler.DisableTableHandler;
70 import org.apache.hadoop.hbase.master.handler.EnableTableHandler;
71 import org.apache.hadoop.hbase.master.handler.ModifyTableHandler;
72 import org.apache.hadoop.hbase.master.handler.TableAddFamilyHandler;
73 import org.apache.hadoop.hbase.master.handler.TableDeleteFamilyHandler;
74 import org.apache.hadoop.hbase.master.handler.TableModifyFamilyHandler;
75 import org.apache.hadoop.hbase.master.metrics.MasterMetrics;
76 import org.apache.hadoop.hbase.regionserver.HRegion;
77 import org.apache.hadoop.hbase.replication.regionserver.Replication;
78 import org.apache.hadoop.hbase.util.Bytes;
79 import org.apache.hadoop.hbase.util.InfoServer;
80 import org.apache.hadoop.hbase.util.Pair;
81 import org.apache.hadoop.hbase.util.Sleeper;
82 import org.apache.hadoop.hbase.util.Threads;
83 import org.apache.hadoop.hbase.util.VersionInfo;
84 import org.apache.hadoop.hbase.zookeeper.ClusterStatusTracker;
85 import org.apache.hadoop.hbase.zookeeper.RegionServerTracker;
86 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
87 import org.apache.hadoop.io.MapWritable;
88 import org.apache.hadoop.io.Text;
89 import org.apache.hadoop.ipc.RemoteException;
90 import org.apache.hadoop.net.DNS;
91 import org.apache.zookeeper.KeeperException;
92 import org.apache.zookeeper.Watcher;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 public class HMaster extends Thread
112 implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
113 private static final Log LOG = LogFactory.getLog(HMaster.class.getName());
114
115
116
117 public static final String MASTER = "master";
118
119
120 private final Configuration conf;
121
122 private InfoServer infoServer;
123
124
125 private ZooKeeperWatcher zooKeeper;
126
127 private ActiveMasterManager activeMasterManager;
128
129 private RegionServerTracker regionServerTracker;
130
131
132 private final HBaseServer rpcServer;
133
134 private final HServerAddress address;
135
136 private final MasterMetrics metrics;
137
138 private MasterFileSystem fileSystemManager;
139
140 private HConnection connection;
141
142
143 private ServerManager serverManager;
144
145
146 AssignmentManager assignmentManager;
147
148 private CatalogTracker catalogTracker;
149
150 private ClusterStatusTracker clusterStatusTracker;
151
152
153
154 private volatile boolean stopped = false;
155
156 private volatile boolean abort = false;
157
158 private volatile boolean isActiveMaster = false;
159
160 private volatile boolean initialized = false;
161
162
163 ExecutorService executorService;
164
165 private LoadBalancer balancer = new LoadBalancer();
166 private Thread balancerChore;
167
168 private volatile boolean balanceSwitch = true;
169
170 private Thread catalogJanitorChore;
171 private LogCleaner logCleaner;
172
173
174
175
176
177
178
179
180
181
182
183
184
185 public HMaster(final Configuration conf)
186 throws IOException, KeeperException, InterruptedException {
187 this.conf = conf;
188
189
190
191
192
193 HServerAddress a = new HServerAddress(getMyAddress(this.conf));
194 int numHandlers = conf.getInt("hbase.regionserver.handler.count", 10);
195 this.rpcServer = HBaseRPC.getServer(this,
196 new Class<?>[]{HMasterInterface.class, HMasterRegionInterface.class},
197 a.getBindAddress(), a.getPort(),
198 numHandlers,
199 0,
200 false, conf,
201 0);
202 this.address = new HServerAddress(rpcServer.getListenerAddress());
203
204
205 setName(MASTER + "-" + this.address);
206
207 Replication.decorateMasterConfiguration(this.conf);
208
209 this.rpcServer.startThreads();
210
211
212
213 if (this.conf.get("mapred.task.id") == null) {
214 this.conf.set("mapred.task.id", "hb_m_" + this.address.toString() +
215 "_" + System.currentTimeMillis());
216 }
217
218 this.zooKeeper = new ZooKeeperWatcher(conf, MASTER + ":" +
219 address.getPort(), this);
220
221 this.metrics = new MasterMetrics(getServerName());
222 }
223
224
225
226
227
228
229
230
231 private static void stallIfBackupMaster(final Configuration c,
232 final ActiveMasterManager amm)
233 throws InterruptedException {
234
235 if (!c.getBoolean(HConstants.MASTER_TYPE_BACKUP,
236 HConstants.DEFAULT_MASTER_TYPE_BACKUP)) {
237 return;
238 }
239 LOG.debug("HMaster started in backup mode. " +
240 "Stalling until master znode is written.");
241
242
243 while (!amm.isActiveMaster()) {
244 LOG.debug("Waiting for master address ZNode to be written " +
245 "(Also watching cluster state node)");
246 Thread.sleep(c.getInt("zookeeper.session.timeout", 180 * 1000));
247 }
248 }
249
250
251
252
253
254
255
256
257
258
259 @Override
260 public void run() {
261 try {
262
263
264
265
266
267
268
269
270
271
272 this.activeMasterManager = new ActiveMasterManager(zooKeeper, address, this);
273 this.zooKeeper.registerListener(activeMasterManager);
274 stallIfBackupMaster(this.conf, this.activeMasterManager);
275 this.activeMasterManager.blockUntilBecomingActiveMaster();
276
277 if (!this.stopped) {
278 finishInitialization();
279 loop();
280 }
281 } catch (Throwable t) {
282 abort("Unhandled exception. Starting shutdown.", t);
283 } finally {
284 stopChores();
285
286
287 if (!this.abort && this.serverManager != null &&
288 this.serverManager.isClusterShutdown()) {
289 this.serverManager.letRegionServersShutdown();
290 }
291 stopServiceThreads();
292
293 if (this.activeMasterManager != null) this.activeMasterManager.stop();
294 if (this.catalogTracker != null) this.catalogTracker.stop();
295 if (this.serverManager != null) this.serverManager.stop();
296 if (this.assignmentManager != null) this.assignmentManager.stop();
297 HConnectionManager.deleteConnection(this.conf, true);
298 this.zooKeeper.close();
299 }
300 LOG.info("HMaster main thread exiting");
301 }
302
303 private void loop() {
304
305 Sleeper sleeper = new Sleeper(1000, this);
306 while (!this.stopped) {
307 sleeper.sleep();
308 }
309 }
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 private void finishInitialization()
331 throws IOException, InterruptedException, KeeperException {
332
333 isActiveMaster = true;
334
335
336
337
338
339
340
341
342 this.fileSystemManager = new MasterFileSystem(this, metrics);
343 this.connection = HConnectionManager.getConnection(conf);
344 this.executorService = new ExecutorService(getServerName());
345
346 this.serverManager = new ServerManager(this, this, metrics);
347
348 this.catalogTracker = new CatalogTracker(this.zooKeeper, this.connection,
349 this, conf.getInt("hbase.master.catalog.timeout", Integer.MAX_VALUE));
350 this.catalogTracker.start();
351
352 this.assignmentManager = new AssignmentManager(this, serverManager,
353 this.catalogTracker, this.executorService);
354 zooKeeper.registerListenerFirst(assignmentManager);
355
356 this.regionServerTracker = new RegionServerTracker(zooKeeper, this,
357 this.serverManager);
358 this.regionServerTracker.start();
359
360
361
362 this.clusterStatusTracker = new ClusterStatusTracker(getZooKeeper(), this);
363 this.clusterStatusTracker.start();
364 boolean wasUp = this.clusterStatusTracker.isClusterUp();
365 if (!wasUp) this.clusterStatusTracker.setClusterUp();
366
367 LOG.info("Server active/primary master; " + this.address +
368 ", sessionid=0x" +
369 Long.toHexString(this.zooKeeper.getZooKeeper().getSessionId()) +
370 ", cluster-up flag was=" + wasUp);
371
372
373 startServiceThreads();
374
375
376 int regionCount = this.serverManager.waitForRegionServers();
377
378
379 this.fileSystemManager.
380 splitLogAfterStartup(this.serverManager.getOnlineServers());
381
382
383 assignRootAndMeta();
384
385
386
387
388
389
390 if (regionCount == 0) {
391 LOG.info("Master startup proceeding: cluster startup");
392 this.assignmentManager.cleanoutUnassigned();
393 this.assignmentManager.assignAllUserRegions();
394 } else {
395 LOG.info("Master startup proceeding: master failover");
396 this.assignmentManager.processFailover();
397 }
398
399
400
401 this.balancerChore = getAndStartBalancerChore(this);
402 this.catalogJanitorChore =
403 Threads.setDaemonThreadRunning(new CatalogJanitor(this, this));
404
405 LOG.info("Master has completed initialization");
406 initialized = true;
407 }
408
409
410
411
412
413
414
415
416
417 int assignRootAndMeta()
418 throws InterruptedException, IOException, KeeperException {
419 int assigned = 0;
420 long timeout = this.conf.getLong("hbase.catalog.verification.timeout", 1000);
421
422
423 boolean rit = this.assignmentManager.
424 processRegionInTransitionAndBlockUntilAssigned(HRegionInfo.ROOT_REGIONINFO);
425 if (!catalogTracker.verifyRootRegionLocation(timeout)) {
426 this.assignmentManager.assignRoot();
427 this.catalogTracker.waitForRoot();
428 assigned++;
429 }
430 LOG.info("-ROOT- assigned=" + assigned + ", rit=" + rit +
431 ", location=" + catalogTracker.getRootLocation());
432
433
434 rit = this.assignmentManager.
435 processRegionInTransitionAndBlockUntilAssigned(HRegionInfo.FIRST_META_REGIONINFO);
436 if (!this.catalogTracker.verifyMetaRegionLocation(timeout)) {
437 this.assignmentManager.assignMeta();
438 this.catalogTracker.waitForMeta();
439
440
441 this.assignmentManager.waitForAssignment(HRegionInfo.FIRST_META_REGIONINFO);
442 assigned++;
443 }
444 LOG.info(".META. assigned=" + assigned + ", rit=" + rit +
445 ", location=" + catalogTracker.getMetaLocation());
446 return assigned;
447 }
448
449
450
451
452
453 private static String getMyAddress(final Configuration c)
454 throws UnknownHostException {
455
456 String s = DNS.getDefaultHost(c.get("hbase.master.dns.interface","default"),
457 c.get("hbase.master.dns.nameserver","default"));
458 s += ":" + c.get(HConstants.MASTER_PORT,
459 Integer.toString(HConstants.DEFAULT_MASTER_PORT));
460 return s;
461 }
462
463
464 public HServerAddress getMasterAddress() {
465 return this.address;
466 }
467
468 public long getProtocolVersion(String protocol, long clientVersion) {
469 return HBaseRPCProtocolVersion.versionID;
470 }
471
472
473 public InfoServer getInfoServer() {
474 return this.infoServer;
475 }
476
477 @Override
478 public Configuration getConfiguration() {
479 return this.conf;
480 }
481
482 @Override
483 public ServerManager getServerManager() {
484 return this.serverManager;
485 }
486
487 @Override
488 public ExecutorService getExecutorService() {
489 return this.executorService;
490 }
491
492 @Override
493 public MasterFileSystem getMasterFileSystem() {
494 return this.fileSystemManager;
495 }
496
497
498
499
500
501 public ZooKeeperWatcher getZooKeeperWatcher() {
502 return this.zooKeeper;
503 }
504
505
506
507
508
509
510
511
512 private void startServiceThreads() {
513 try {
514
515 this.executorService.startExecutorService(ExecutorType.MASTER_OPEN_REGION,
516 conf.getInt("hbase.master.executor.openregion.threads", 5));
517 this.executorService.startExecutorService(ExecutorType.MASTER_CLOSE_REGION,
518 conf.getInt("hbase.master.executor.closeregion.threads", 5));
519 this.executorService.startExecutorService(ExecutorType.MASTER_SERVER_OPERATIONS,
520 conf.getInt("hbase.master.executor.serverops.threads", 3));
521 this.executorService.startExecutorService(ExecutorType.MASTER_META_SERVER_OPERATIONS,
522 conf.getInt("hbase.master.executor.serverops.threads", 5));
523
524
525
526 this.executorService.startExecutorService(ExecutorType.MASTER_TABLE_OPERATIONS, 1);
527
528
529 String n = Thread.currentThread().getName();
530 this.logCleaner =
531 new LogCleaner(conf.getInt("hbase.master.cleaner.interval", 60 * 1000),
532 this, conf, getMasterFileSystem().getFileSystem(),
533 getMasterFileSystem().getOldLogDir());
534 Threads.setDaemonThreadRunning(logCleaner, n + ".oldLogCleaner");
535
536
537 int port = this.conf.getInt("hbase.master.info.port", 60010);
538 if (port >= 0) {
539 String a = this.conf.get("hbase.master.info.bindAddress", "0.0.0.0");
540 this.infoServer = new InfoServer(MASTER, a, port, false);
541 this.infoServer.setAttribute(MASTER, this);
542 this.infoServer.start();
543 }
544
545 this.rpcServer.openServer();
546 if (LOG.isDebugEnabled()) {
547 LOG.debug("Started service threads");
548 }
549 } catch (IOException e) {
550 if (e instanceof RemoteException) {
551 e = ((RemoteException)e).unwrapRemoteException();
552 }
553
554 abort("Failed startup", e);
555 }
556 }
557
558 private void stopServiceThreads() {
559 if (LOG.isDebugEnabled()) {
560 LOG.debug("Stopping service threads");
561 }
562 if (this.rpcServer != null) this.rpcServer.stop();
563
564 if (this.logCleaner!= null) this.logCleaner.interrupt();
565 if (this.infoServer != null) {
566 LOG.info("Stopping infoServer");
567 try {
568 this.infoServer.stop();
569 } catch (Exception ex) {
570 ex.printStackTrace();
571 }
572 }
573 if (this.executorService != null) this.executorService.shutdown();
574 }
575
576 private static Thread getAndStartBalancerChore(final HMaster master) {
577 String name = master.getServerName() + "-BalancerChore";
578 int period = master.getConfiguration().getInt("hbase.balancer.period", 300000);
579
580 Chore chore = new Chore(name, period, master) {
581 @Override
582 protected void chore() {
583 master.balance();
584 }
585 };
586 return Threads.setDaemonThreadRunning(chore);
587 }
588
589 private void stopChores() {
590 if (this.balancerChore != null) {
591 this.balancerChore.interrupt();
592 }
593 if (this.catalogJanitorChore != null) {
594 this.catalogJanitorChore.interrupt();
595 }
596 }
597
598 @Override
599 public MapWritable regionServerStartup(final HServerInfo serverInfo,
600 final long serverCurrentTime)
601 throws IOException {
602
603
604
605
606
607 InetSocketAddress address = new InetSocketAddress(
608 HBaseServer.getRemoteIp().getHostName(),
609 serverInfo.getServerAddress().getPort());
610 serverInfo.setServerAddress(new HServerAddress(address));
611
612
613 this.serverManager.regionServerStartup(serverInfo, serverCurrentTime);
614
615 MapWritable mw = createConfigurationSubset();
616 mw.put(new Text("hbase.regionserver.address"),
617 serverInfo.getServerAddress());
618 return mw;
619 }
620
621
622
623
624
625 protected MapWritable createConfigurationSubset() {
626 MapWritable mw = addConfig(new MapWritable(), HConstants.HBASE_DIR);
627 return addConfig(mw, "fs.default.name");
628 }
629
630 private MapWritable addConfig(final MapWritable mw, final String key) {
631 mw.put(new Text(key), new Text(this.conf.get(key)));
632 return mw;
633 }
634
635 @Override
636 public HMsg [] regionServerReport(HServerInfo serverInfo, HMsg msgs[],
637 HRegionInfo[] mostLoadedRegions)
638 throws IOException {
639 return adornRegionServerAnswer(serverInfo,
640 this.serverManager.regionServerReport(serverInfo, msgs, mostLoadedRegions));
641 }
642
643
644
645
646
647
648
649
650 protected HMsg [] adornRegionServerAnswer(final HServerInfo hsi,
651 final HMsg [] msgs) throws IOException {
652 return msgs;
653 }
654
655 public boolean isMasterRunning() {
656 return !isStopped();
657 }
658
659 @Override
660 public boolean balance() {
661
662 if (!this.balanceSwitch) return false;
663 synchronized (this.balancer) {
664
665 if (this.assignmentManager.isRegionsInTransition()) {
666 LOG.debug("Not running balancer because " +
667 this.assignmentManager.getRegionsInTransition().size() +
668 " region(s) in transition: " +
669 org.apache.commons.lang.StringUtils.
670 abbreviate(this.assignmentManager.getRegionsInTransition().toString(), 256));
671 return false;
672 }
673 if (this.serverManager.areDeadServersInProgress()) {
674 LOG.debug("Not running balancer because processing dead regionserver(s): " +
675 this.serverManager.getDeadServers());
676 return false;
677 }
678 Map<HServerInfo, List<HRegionInfo>> assignments =
679 this.assignmentManager.getAssignments();
680
681 for (Map.Entry<String, HServerInfo> e:
682 this.serverManager.getOnlineServers().entrySet()) {
683 HServerInfo hsi = e.getValue();
684 if (!assignments.containsKey(hsi)) {
685 assignments.put(hsi, new ArrayList<HRegionInfo>());
686 }
687 }
688 List<RegionPlan> plans = this.balancer.balanceCluster(assignments);
689 if (plans != null && !plans.isEmpty()) {
690 for (RegionPlan plan: plans) {
691 LOG.info("balance " + plan);
692 this.assignmentManager.balance(plan);
693 }
694 }
695 }
696 return true;
697 }
698
699 @Override
700 public boolean balanceSwitch(final boolean b) {
701 boolean oldValue = this.balanceSwitch;
702 this.balanceSwitch = b;
703 LOG.info("Balance=" + b);
704 return oldValue;
705 }
706
707
708
709
710
711
712
713 public void setCatalogJanitorEnabled(final boolean b) {
714 ((CatalogJanitor)this.catalogJanitorChore).setEnabled(b);
715 }
716
717 @Override
718 public void move(final byte[] encodedRegionName, final byte[] destServerName)
719 throws UnknownRegionException {
720 Pair<HRegionInfo, HServerInfo> p =
721 this.assignmentManager.getAssignment(encodedRegionName);
722 if (p == null)
723 throw new UnknownRegionException(Bytes.toString(encodedRegionName));
724 HRegionInfo hri = p.getFirst();
725 HServerInfo dest = null;
726 if (destServerName == null || destServerName.length == 0) {
727 LOG.info("Passed destination servername is null/empty so " +
728 "choosing a server at random");
729 this.assignmentManager.clearRegionPlan(hri);
730
731 this.assignmentManager.unassign(hri);
732 } else {
733 dest = this.serverManager.getServerInfo(new String(destServerName));
734 RegionPlan rp = new RegionPlan(p.getFirst(), p.getSecond(), dest);
735 this.assignmentManager.balance(rp);
736 }
737 }
738
739 public void createTable(HTableDescriptor desc, byte [][] splitKeys)
740 throws IOException {
741 createTable(desc, splitKeys, false);
742 }
743
744 public void createTable(HTableDescriptor desc, byte [][] splitKeys,
745 boolean sync)
746 throws IOException {
747 if (!isMasterRunning()) {
748 throw new MasterNotRunningException();
749 }
750 HRegionInfo [] newRegions = null;
751 if(splitKeys == null || splitKeys.length == 0) {
752 newRegions = new HRegionInfo [] { new HRegionInfo(desc, null, null) };
753 } else {
754 int numRegions = splitKeys.length + 1;
755 newRegions = new HRegionInfo[numRegions];
756 byte [] startKey = null;
757 byte [] endKey = null;
758 for(int i=0;i<numRegions;i++) {
759 endKey = (i == splitKeys.length) ? null : splitKeys[i];
760 newRegions[i] = new HRegionInfo(desc, startKey, endKey);
761 startKey = endKey;
762 }
763 }
764 int timeout = conf.getInt("hbase.client.catalog.timeout", 10000);
765
766 try {
767 if(catalogTracker.waitForMeta(timeout) == null) {
768 throw new NotAllMetaRegionsOnlineException();
769 }
770 } catch (InterruptedException e) {
771 LOG.warn("Interrupted waiting for meta availability", e);
772 throw new IOException(e);
773 }
774 createTable(newRegions, sync);
775 }
776
777 private synchronized void createTable(final HRegionInfo [] newRegions,
778 boolean sync)
779 throws IOException {
780 String tableName = newRegions[0].getTableDesc().getNameAsString();
781 if(MetaReader.tableExists(catalogTracker, tableName)) {
782 throw new TableExistsException(tableName);
783 }
784 for(HRegionInfo newRegion : newRegions) {
785
786
787 try {
788 assignmentManager.getZKTable().setEnabledTable(tableName);
789 } catch (KeeperException e) {
790 throw new IOException("Unable to ensure that the table will be" +
791 " enabled because of a ZooKeeper issue", e);
792 }
793
794
795 HRegion region = HRegion.createHRegion(newRegion,
796 fileSystemManager.getRootDir(), conf);
797
798
799 MetaEditor.addRegionToMeta(catalogTracker, region.getRegionInfo());
800
801
802 region.close();
803 region.getLog().closeAndDelete();
804 }
805
806
807 List<HServerInfo> servers = serverManager.getOnlineServersList();
808 try {
809 this.assignmentManager.assignUserRegions(Arrays.asList(newRegions), servers);
810 } catch (InterruptedException ie) {
811 LOG.error("Caught " + ie + " during round-robin assignment");
812 throw new IOException(ie);
813 }
814
815
816 if(sync) {
817 LOG.debug("Waiting for " + newRegions.length + " region(s) to be " +
818 "assigned before returning");
819 for(HRegionInfo regionInfo : newRegions) {
820 try {
821 assignmentManager.waitForAssignment(regionInfo);
822 } catch (InterruptedException e) {
823 LOG.info("Interrupted waiting for region to be assigned during " +
824 "create table call");
825 return;
826 }
827 }
828 }
829 }
830
831 private static boolean isCatalogTable(final byte [] tableName) {
832 return Bytes.equals(tableName, HConstants.ROOT_TABLE_NAME) ||
833 Bytes.equals(tableName, HConstants.META_TABLE_NAME);
834 }
835
836 public void deleteTable(final byte [] tableName) throws IOException {
837 this.executorService.submit(new DeleteTableHandler(tableName, this, this));
838 }
839
840 public void addColumn(byte [] tableName, HColumnDescriptor column)
841 throws IOException {
842 new TableAddFamilyHandler(tableName, column, this, this).process();
843 }
844
845 public void modifyColumn(byte [] tableName, HColumnDescriptor descriptor)
846 throws IOException {
847 new TableModifyFamilyHandler(tableName, descriptor, this, this).process();
848 }
849
850 public void deleteColumn(final byte [] tableName, final byte [] c)
851 throws IOException {
852 new TableDeleteFamilyHandler(tableName, c, this, this).process();
853 }
854
855 public void enableTable(final byte [] tableName) throws IOException {
856 this.executorService.submit(new EnableTableHandler(this, tableName,
857 catalogTracker, assignmentManager));
858 }
859
860 public void disableTable(final byte [] tableName) throws IOException {
861 this.executorService.submit(new DisableTableHandler(this, tableName,
862 catalogTracker, assignmentManager));
863 }
864
865
866
867
868
869
870
871 Pair<HRegionInfo,HServerAddress> getTableRegionForRow(
872 final byte [] tableName, final byte [] rowKey)
873 throws IOException {
874 final AtomicReference<Pair<HRegionInfo, HServerAddress>> result =
875 new AtomicReference<Pair<HRegionInfo, HServerAddress>>(null);
876
877 MetaScannerVisitor visitor =
878 new MetaScannerVisitor() {
879 @Override
880 public boolean processRow(Result data) throws IOException {
881 if (data == null || data.size() <= 0) {
882 return true;
883 }
884 Pair<HRegionInfo, HServerAddress> pair =
885 MetaReader.metaRowToRegionPair(data);
886 if (pair == null) {
887 return false;
888 }
889 if (!Bytes.equals(pair.getFirst().getTableDesc().getName(),
890 tableName)) {
891 return false;
892 }
893 result.set(pair);
894 return true;
895 }
896 };
897
898 MetaScanner.metaScan(conf, visitor, tableName, rowKey, 1);
899 return result.get();
900 }
901
902 @Override
903 public void modifyTable(final byte[] tableName, HTableDescriptor htd)
904 throws IOException {
905 this.executorService.submit(new ModifyTableHandler(tableName, htd, this, this));
906 }
907
908 @Override
909 public void checkTableModifiable(final byte [] tableName)
910 throws IOException {
911 String tableNameStr = Bytes.toString(tableName);
912 if (isCatalogTable(tableName)) {
913 throw new IOException("Can't modify catalog tables");
914 }
915 if (!MetaReader.tableExists(getCatalogTracker(), tableNameStr)) {
916 throw new TableNotFoundException(tableNameStr);
917 }
918 if (!getAssignmentManager().getZKTable().
919 isDisabledTable(Bytes.toString(tableName))) {
920 throw new TableNotDisabledException(tableName);
921 }
922 }
923
924 public void clearFromTransition(HRegionInfo hri) {
925 if (this.assignmentManager.isRegionInTransition(hri) != null) {
926 this.assignmentManager.clearRegionFromTransition(hri);
927 }
928 }
929
930
931
932 public ClusterStatus getClusterStatus() {
933 ClusterStatus status = new ClusterStatus();
934 status.setHBaseVersion(VersionInfo.getVersion());
935 status.setServerInfo(serverManager.getOnlineServers().values());
936 status.setDeadServers(serverManager.getDeadServers());
937 status.setRegionsInTransition(assignmentManager.getRegionsInTransition());
938 return status;
939 }
940
941 @Override
942 public void abort(final String msg, final Throwable t) {
943 if (t != null) LOG.fatal(msg, t);
944 else LOG.fatal(msg);
945 this.abort = true;
946 stop("Aborting");
947 }
948
949 @Override
950 public ZooKeeperWatcher getZooKeeper() {
951 return zooKeeper;
952 }
953
954 @Override
955 public String getServerName() {
956 return address.toString();
957 }
958
959 @Override
960 public CatalogTracker getCatalogTracker() {
961 return catalogTracker;
962 }
963
964 @Override
965 public AssignmentManager getAssignmentManager() {
966 return this.assignmentManager;
967 }
968
969 @Override
970 public void shutdown() {
971 this.serverManager.shutdownCluster();
972 try {
973 this.clusterStatusTracker.setClusterDown();
974 } catch (KeeperException e) {
975 LOG.error("ZooKeeper exception trying to set cluster as down in ZK", e);
976 }
977 }
978
979 @Override
980 public void stopMaster() {
981 stop("Stopped by " + Thread.currentThread().getName());
982 }
983
984 @Override
985 public void stop(final String why) {
986 LOG.info(why);
987 this.stopped = true;
988
989 synchronized (this.activeMasterManager.clusterHasActiveMaster) {
990 this.activeMasterManager.clusterHasActiveMaster.notifyAll();
991 }
992 }
993
994 @Override
995 public boolean isStopped() {
996 return this.stopped;
997 }
998
999
1000
1001
1002
1003
1004
1005
1006
1007 public boolean isActiveMaster() {
1008 return isActiveMaster;
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 public boolean isInitialized() {
1021 return initialized;
1022 }
1023
1024 @Override
1025 public void assign(final byte [] regionName, final boolean force)
1026 throws IOException {
1027 Pair<HRegionInfo, HServerAddress> pair =
1028 MetaReader.getRegion(this.catalogTracker, regionName);
1029 if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
1030 assignRegion(pair.getFirst());
1031 }
1032
1033 public void assignRegion(HRegionInfo hri) {
1034 assignmentManager.assign(hri, true);
1035 }
1036
1037 @Override
1038 public void unassign(final byte [] regionName, final boolean force)
1039 throws IOException {
1040 Pair<HRegionInfo, HServerAddress> pair =
1041 MetaReader.getRegion(this.catalogTracker, regionName);
1042 if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
1043 HRegionInfo hri = pair.getFirst();
1044 if (force) this.assignmentManager.clearRegionFromTransition(hri);
1045 this.assignmentManager.unassign(hri, force);
1046 }
1047
1048
1049
1050
1051
1052
1053
1054 public static HMaster constructMaster(Class<? extends HMaster> masterClass,
1055 final Configuration conf) {
1056 try {
1057 Constructor<? extends HMaster> c =
1058 masterClass.getConstructor(Configuration.class);
1059 return c.newInstance(conf);
1060 } catch (InvocationTargetException ite) {
1061 Throwable target = ite.getTargetException() != null?
1062 ite.getTargetException(): ite;
1063 if (target.getCause() != null) target = target.getCause();
1064 throw new RuntimeException("Failed construction of Master: " +
1065 masterClass.toString(), target);
1066 } catch (Exception e) {
1067 throw new RuntimeException("Failed construction of Master: " +
1068 masterClass.toString() + ((e.getCause() != null)?
1069 e.getCause().getMessage(): ""), e);
1070 }
1071 }
1072
1073
1074
1075
1076
1077 public static void main(String [] args) throws Exception {
1078 new HMasterCommandLine(HMaster.class).doMain(args);
1079 }
1080 }