1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master;
20
21 import java.io.IOException;
22 import java.io.InterruptedIOException;
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.InvocationTargetException;
25 import java.net.InetAddress;
26 import java.net.InetSocketAddress;
27 import java.net.UnknownHostException;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Map.Entry;
37 import java.util.Set;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.atomic.AtomicReference;
40 import java.util.regex.Pattern;
41
42 import javax.servlet.ServletException;
43 import javax.servlet.http.HttpServlet;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49 import org.apache.hadoop.conf.Configuration;
50 import org.apache.hadoop.fs.Path;
51 import org.apache.hadoop.hbase.ClusterStatus;
52 import org.apache.hadoop.hbase.CoordinatedStateException;
53 import org.apache.hadoop.hbase.CoordinatedStateManager;
54 import org.apache.hadoop.hbase.DoNotRetryIOException;
55 import org.apache.hadoop.hbase.HBaseIOException;
56 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
57 import org.apache.hadoop.hbase.HColumnDescriptor;
58 import org.apache.hadoop.hbase.HConstants;
59 import org.apache.hadoop.hbase.HRegionInfo;
60 import org.apache.hadoop.hbase.HTableDescriptor;
61 import org.apache.hadoop.hbase.MasterNotRunningException;
62 import org.apache.hadoop.hbase.MetaMigrationConvertingToPB;
63 import org.apache.hadoop.hbase.MetaTableAccessor;
64 import org.apache.hadoop.hbase.NamespaceDescriptor;
65 import org.apache.hadoop.hbase.NamespaceNotFoundException;
66 import org.apache.hadoop.hbase.PleaseHoldException;
67 import org.apache.hadoop.hbase.ProcedureInfo;
68 import org.apache.hadoop.hbase.RegionStateListener;
69 import org.apache.hadoop.hbase.ScheduledChore;
70 import org.apache.hadoop.hbase.Server;
71 import org.apache.hadoop.hbase.ServerLoad;
72 import org.apache.hadoop.hbase.ServerName;
73 import org.apache.hadoop.hbase.TableDescriptors;
74 import org.apache.hadoop.hbase.TableName;
75 import org.apache.hadoop.hbase.TableNotDisabledException;
76 import org.apache.hadoop.hbase.TableNotFoundException;
77 import org.apache.hadoop.hbase.UnknownRegionException;
78 import org.apache.hadoop.hbase.classification.InterfaceAudience;
79 import org.apache.hadoop.hbase.client.Admin;
80 import org.apache.hadoop.hbase.client.MetaScanner;
81 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
82 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
83 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
84 import org.apache.hadoop.hbase.client.Result;
85 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
86 import org.apache.hadoop.hbase.exceptions.DeserializationException;
87 import org.apache.hadoop.hbase.executor.ExecutorType;
88 import org.apache.hadoop.hbase.http.InfoServer;
89 import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
90 import org.apache.hadoop.hbase.ipc.RpcServer;
91 import org.apache.hadoop.hbase.ipc.ServerNotRunningYetException;
92 import org.apache.hadoop.hbase.master.MasterRpcServices.BalanceSwitchMode;
93 import org.apache.hadoop.hbase.master.RegionState.State;
94 import org.apache.hadoop.hbase.master.balancer.BalancerChore;
95 import org.apache.hadoop.hbase.master.balancer.BaseLoadBalancer;
96 import org.apache.hadoop.hbase.master.balancer.ClusterStatusChore;
97 import org.apache.hadoop.hbase.master.balancer.LoadBalancerFactory;
98 import org.apache.hadoop.hbase.master.cleaner.HFileCleaner;
99 import org.apache.hadoop.hbase.master.cleaner.LogCleaner;
100 import org.apache.hadoop.hbase.master.cleaner.ReplicationZKLockCleanerChore;
101 import org.apache.hadoop.hbase.master.handler.DispatchMergingRegionHandler;
102 import org.apache.hadoop.hbase.master.normalizer.RegionNormalizer;
103 import org.apache.hadoop.hbase.master.normalizer.RegionNormalizerChore;
104 import org.apache.hadoop.hbase.master.normalizer.RegionNormalizerFactory;
105 import org.apache.hadoop.hbase.master.procedure.AddColumnFamilyProcedure;
106 import org.apache.hadoop.hbase.master.procedure.CreateNamespaceProcedure;
107 import org.apache.hadoop.hbase.master.procedure.CreateTableProcedure;
108 import org.apache.hadoop.hbase.master.procedure.DeleteColumnFamilyProcedure;
109 import org.apache.hadoop.hbase.master.procedure.DeleteNamespaceProcedure;
110 import org.apache.hadoop.hbase.master.procedure.DeleteTableProcedure;
111 import org.apache.hadoop.hbase.master.procedure.DisableTableProcedure;
112 import org.apache.hadoop.hbase.master.procedure.EnableTableProcedure;
113 import org.apache.hadoop.hbase.master.procedure.MasterProcedureConstants;
114 import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
115 import org.apache.hadoop.hbase.master.procedure.MasterProcedureScheduler.ProcedureEvent;
116 import org.apache.hadoop.hbase.master.procedure.ModifyColumnFamilyProcedure;
117 import org.apache.hadoop.hbase.master.procedure.ModifyNamespaceProcedure;
118 import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil;
119 import org.apache.hadoop.hbase.master.procedure.ModifyTableProcedure;
120 import org.apache.hadoop.hbase.master.procedure.ProcedurePrepareLatch;
121 import org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait;
122 import org.apache.hadoop.hbase.master.procedure.TruncateTableProcedure;
123 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
124 import org.apache.hadoop.hbase.monitoring.MemoryBoundedLogMessageBuffer;
125 import org.apache.hadoop.hbase.monitoring.MonitoredTask;
126 import org.apache.hadoop.hbase.monitoring.TaskMonitor;
127 import org.apache.hadoop.hbase.master.normalizer.NormalizationPlan;
128 import org.apache.hadoop.hbase.master.normalizer.NormalizationPlan.PlanType;
129 import org.apache.hadoop.hbase.procedure.MasterProcedureManagerHost;
130 import org.apache.hadoop.hbase.procedure.flush.MasterFlushTableProcedureManager;
131 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
132 import org.apache.hadoop.hbase.procedure2.store.wal.WALProcedureStore;
133 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionServerInfo;
134 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
135 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos.SplitLogTask.RecoveryMode;
136 import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
137 import org.apache.hadoop.hbase.regionserver.DefaultStoreEngine;
138 import org.apache.hadoop.hbase.regionserver.HRegionServer;
139 import org.apache.hadoop.hbase.regionserver.HStore;
140 import org.apache.hadoop.hbase.regionserver.RSRpcServices;
141 import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
142 import org.apache.hadoop.hbase.regionserver.RegionSplitPolicy;
143 import org.apache.hadoop.hbase.regionserver.compactions.ExploringCompactionPolicy;
144 import org.apache.hadoop.hbase.regionserver.compactions.FIFOCompactionPolicy;
145 import org.apache.hadoop.hbase.replication.regionserver.Replication;
146 import org.apache.hadoop.hbase.security.User;
147 import org.apache.hadoop.hbase.security.UserProvider;
148 import org.apache.hadoop.hbase.util.Addressing;
149 import org.apache.hadoop.hbase.util.Bytes;
150 import org.apache.hadoop.hbase.util.CompressionTest;
151 import org.apache.hadoop.hbase.util.ConfigUtil;
152 import org.apache.hadoop.hbase.util.EncryptionTest;
153 import org.apache.hadoop.hbase.util.FSUtils;
154 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
155 import org.apache.hadoop.hbase.util.HasThread;
156 import org.apache.hadoop.hbase.util.ModifyRegionUtils;
157 import org.apache.hadoop.hbase.util.Pair;
158 import org.apache.hadoop.hbase.util.Threads;
159 import org.apache.hadoop.hbase.util.VersionInfo;
160 import org.apache.hadoop.hbase.zookeeper.DrainingServerTracker;
161 import org.apache.hadoop.hbase.zookeeper.LoadBalancerTracker;
162 import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
163 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
164 import org.apache.hadoop.hbase.zookeeper.RegionNormalizerTracker;
165 import org.apache.hadoop.hbase.zookeeper.RegionServerTracker;
166 import org.apache.hadoop.hbase.zookeeper.SplitOrMergeTracker;
167 import org.apache.hadoop.hbase.zookeeper.ZKClusterId;
168 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
169 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
170 import org.apache.zookeeper.KeeperException;
171 import org.mortbay.jetty.Connector;
172 import org.mortbay.jetty.nio.SelectChannelConnector;
173 import org.mortbay.jetty.servlet.Context;
174 import org.mortbay.jetty.servlet.ServletHolder;
175
176 import com.google.common.annotations.VisibleForTesting;
177 import com.google.common.collect.Maps;
178 import com.google.protobuf.Descriptors;
179 import com.google.protobuf.Service;
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
197 @SuppressWarnings("deprecation")
198 public class HMaster extends HRegionServer implements MasterServices, Server {
199 private static final Log LOG = LogFactory.getLog(HMaster.class.getName());
200
201
202
203
204
205 private static class InitializationMonitor extends HasThread {
206
207 public static final String TIMEOUT_KEY = "hbase.master.initializationmonitor.timeout";
208 public static final long TIMEOUT_DEFAULT = TimeUnit.MILLISECONDS.convert(15, TimeUnit.MINUTES);
209
210
211
212
213
214 public static final String HALT_KEY = "hbase.master.initializationmonitor.haltontimeout";
215 public static final boolean HALT_DEFAULT = false;
216
217 private final HMaster master;
218 private final long timeout;
219 private final boolean haltOnTimeout;
220
221
222 InitializationMonitor(HMaster master) {
223 super("MasterInitializationMonitor");
224 this.master = master;
225 this.timeout = master.getConfiguration().getLong(TIMEOUT_KEY, TIMEOUT_DEFAULT);
226 this.haltOnTimeout = master.getConfiguration().getBoolean(HALT_KEY, HALT_DEFAULT);
227 this.setDaemon(true);
228 }
229
230 @Override
231 public void run() {
232 try {
233 while (!master.isStopped() && master.isActiveMaster()) {
234 Thread.sleep(timeout);
235 if (master.isInitialized()) {
236 LOG.debug("Initialization completed within allotted tolerance. Monitor exiting.");
237 } else {
238 LOG.error("Master failed to complete initialization after " + timeout + "ms. Please"
239 + " consider submitting a bug report including a thread dump of this process.");
240 if (haltOnTimeout) {
241 LOG.error("Zombie Master exiting. Thread dump to stdout");
242 Threads.printThreadInfo(System.out, "Zombie HMaster");
243 System.exit(-1);
244 }
245 }
246 }
247 } catch (InterruptedException ie) {
248 LOG.trace("InitMonitor thread interrupted. Existing.");
249 }
250 }
251 }
252
253
254
255 public static final String MASTER = "master";
256
257
258 private final ActiveMasterManager activeMasterManager;
259
260 RegionServerTracker regionServerTracker;
261
262 private DrainingServerTracker drainingServerTracker;
263
264 LoadBalancerTracker loadBalancerTracker;
265
266
267 private SplitOrMergeTracker splitOrMergeTracker;
268
269
270 private RegionNormalizerTracker regionNormalizerTracker;
271
272
273 private TableNamespaceManager tableNamespaceManager;
274
275
276 final MetricsMaster metricsMaster;
277
278 private MasterFileSystem fileSystemManager;
279
280
281 volatile ServerManager serverManager;
282
283
284 AssignmentManager assignmentManager;
285
286
287
288
289 MemoryBoundedLogMessageBuffer rsFatals;
290
291
292 private volatile boolean isActiveMaster = false;
293
294
295
296 private final ProcedureEvent initialized = new ProcedureEvent("master initialized");
297
298
299
300 volatile boolean serviceStarted = false;
301
302
303 private final ProcedureEvent serverCrashProcessingEnabled =
304 new ProcedureEvent("server crash processing");
305
306 LoadBalancer balancer;
307 private RegionNormalizer normalizer;
308 private BalancerChore balancerChore;
309 private RegionNormalizerChore normalizerChore;
310 private ClusterStatusChore clusterStatusChore;
311 private ClusterStatusPublisher clusterStatusPublisherChore = null;
312 private PeriodicDoMetrics periodicDoMetricsChore = null;
313
314 CatalogJanitor catalogJanitorChore;
315 private ReplicationZKLockCleanerChore replicationZKLockCleanerChore;
316 private LogCleaner logCleaner;
317 private HFileCleaner hfileCleaner;
318
319 MasterCoprocessorHost cpHost;
320
321 private final boolean preLoadTableDescriptors;
322
323
324 private long masterActiveTime;
325
326
327 private final boolean masterCheckCompression;
328
329
330 private final boolean masterCheckEncryption;
331
332 Map<String, Service> coprocessorServiceHandlers = Maps.newHashMap();
333
334
335 SnapshotManager snapshotManager;
336
337 MasterProcedureManagerHost mpmHost;
338
339
340 private volatile MasterQuotaManager quotaManager;
341
342 private ProcedureExecutor<MasterProcedureEnv> procedureExecutor;
343 private WALProcedureStore procedureStore;
344
345 private long splitPlanCount;
346 private long mergePlanCount;
347
348
349 private volatile boolean initializationBeforeMetaAssignment = false;
350
351
352 private org.mortbay.jetty.Server masterJettyServer;
353
354 public static class RedirectServlet extends HttpServlet {
355 private static final long serialVersionUID = 2894774810058302473L;
356 private final int regionServerInfoPort;
357 private final String regionServerHostname;
358
359
360
361
362
363 public RedirectServlet(InfoServer infoServer, String hostname) {
364 regionServerInfoPort = infoServer.getPort();
365 regionServerHostname = hostname;
366 }
367
368 @Override
369 public void doGet(HttpServletRequest request,
370 HttpServletResponse response) throws ServletException, IOException {
371 String redirectHost = regionServerHostname;
372 if(redirectHost == null) {
373 redirectHost = request.getServerName();
374 if(!Addressing.isLocalAddress(InetAddress.getByName(redirectHost))) {
375 LOG.warn("Couldn't resolve '" + redirectHost + "' as an address local to this node and '" +
376 MASTER_HOSTNAME_KEY + "' is not set; client will get a HTTP 400 response. If " +
377 "your HBase deployment relies on client accessible names that the region server process " +
378 "can't resolve locally, then you should set the previously mentioned configuration variable " +
379 "to an appropriate hostname.");
380
381 response.sendError(400, "Request was to a host that I can't resolve for any of the network interfaces on " +
382 "this node. If this is due to an intermediary such as an HTTP load balancer or other proxy, your HBase " +
383 "administrator can set '" + MASTER_HOSTNAME_KEY + "' to point to the correct hostname.");
384 return;
385 }
386 }
387
388
389 String redirectUrl = request.getScheme() + "://"
390 + redirectHost + ":" + regionServerInfoPort
391 + request.getRequestURI();
392 response.sendRedirect(redirectUrl);
393 }
394 }
395
396 private static class PeriodicDoMetrics extends ScheduledChore {
397 private final HMaster server;
398 public PeriodicDoMetrics(int doMetricsInterval, final HMaster server) {
399 super(server.getServerName() + "-DoMetricsChore", server, doMetricsInterval);
400 this.server = server;
401 }
402
403 @Override
404 protected void chore() {
405 server.doMetrics();
406 }
407 }
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425 public HMaster(final Configuration conf, CoordinatedStateManager csm)
426 throws IOException, KeeperException, InterruptedException {
427 super(conf, csm);
428 this.rsFatals = new MemoryBoundedLogMessageBuffer(
429 conf.getLong("hbase.master.buffer.for.rs.fatals", 1*1024*1024));
430
431 LOG.info("hbase.rootdir=" + FSUtils.getRootDir(this.conf) +
432 ", hbase.cluster.distributed=" + this.conf.getBoolean(HConstants.CLUSTER_DISTRIBUTED, false));
433
434
435 this.conf.setBoolean(HConstants.USE_META_REPLICAS, false);
436
437 Replication.decorateMasterConfiguration(this.conf);
438
439
440
441 if (this.conf.get("mapreduce.task.attempt.id") == null) {
442 this.conf.set("mapreduce.task.attempt.id", "hb_m_" + this.serverName.toString());
443 }
444
445
446 this.masterCheckCompression = conf.getBoolean("hbase.master.check.compression", true);
447
448
449 this.masterCheckEncryption = conf.getBoolean("hbase.master.check.encryption", true);
450
451 this.metricsMaster = new MetricsMaster(new MetricsMasterWrapperImpl(this));
452
453
454 this.preLoadTableDescriptors = conf.getBoolean("hbase.master.preload.tabledescriptors", true);
455
456
457
458 boolean shouldPublish = conf.getBoolean(HConstants.STATUS_PUBLISHED,
459 HConstants.STATUS_PUBLISHED_DEFAULT);
460 Class<? extends ClusterStatusPublisher.Publisher> publisherClass =
461 conf.getClass(ClusterStatusPublisher.STATUS_PUBLISHER_CLASS,
462 ClusterStatusPublisher.DEFAULT_STATUS_PUBLISHER_CLASS,
463 ClusterStatusPublisher.Publisher.class);
464
465 if (shouldPublish) {
466 if (publisherClass == null) {
467 LOG.warn(HConstants.STATUS_PUBLISHED + " is true, but " +
468 ClusterStatusPublisher.DEFAULT_STATUS_PUBLISHER_CLASS +
469 " is not set - not publishing status");
470 } else {
471 clusterStatusPublisherChore = new ClusterStatusPublisher(this, conf, publisherClass);
472 getChoreService().scheduleChore(clusterStatusPublisherChore);
473 }
474 }
475
476
477 if (!conf.getBoolean("hbase.testing.nocluster", false)) {
478 activeMasterManager = new ActiveMasterManager(zooKeeper, this.serverName, this);
479 int infoPort = putUpJettyServer();
480 startActiveMasterManager(infoPort);
481 } else {
482 activeMasterManager = null;
483 }
484 }
485
486
487 private int putUpJettyServer() throws IOException {
488 if (!conf.getBoolean("hbase.master.infoserver.redirect", true)) {
489 return -1;
490 }
491 final int infoPort = conf.getInt("hbase.master.info.port.orig",
492 HConstants.DEFAULT_MASTER_INFOPORT);
493
494 if (infoPort < 0 || infoServer == null) {
495 return -1;
496 }
497 if(infoPort == infoServer.getPort()) {
498 return infoPort;
499 }
500 final String addr = conf.get("hbase.master.info.bindAddress", "0.0.0.0");
501 if (!Addressing.isLocalAddress(InetAddress.getByName(addr))) {
502 String msg =
503 "Failed to start redirecting jetty server. Address " + addr
504 + " does not belong to this host. Correct configuration parameter: "
505 + "hbase.master.info.bindAddress";
506 LOG.error(msg);
507 throw new IOException(msg);
508 }
509
510
511
512
513 masterJettyServer = new org.mortbay.jetty.Server();
514 Connector connector = new SelectChannelConnector();
515 connector.setHost(addr);
516 connector.setPort(infoPort);
517 masterJettyServer.addConnector(connector);
518 masterJettyServer.setStopAtShutdown(true);
519
520 final String redirectHostname = shouldUseThisHostnameInstead() ? useThisHostnameInstead : null;
521
522 final RedirectServlet redirect = new RedirectServlet(infoServer, redirectHostname);
523 Context context = new Context(masterJettyServer, "/", Context.NO_SESSIONS);
524 context.addServlet(new ServletHolder(redirect), "/*");
525
526 try {
527 masterJettyServer.start();
528 } catch (Exception e) {
529 throw new IOException("Failed to start redirecting jetty server", e);
530 }
531 return connector.getLocalPort();
532 }
533
534
535
536
537 @Override
538 protected void login(UserProvider user, String host) throws IOException {
539 try {
540 super.login(user, host);
541 } catch (IOException ie) {
542 user.login("hbase.master.keytab.file",
543 "hbase.master.kerberos.principal", host);
544 }
545 }
546
547
548
549
550
551
552 @Override
553 protected void waitForMasterActive(){
554 boolean tablesOnMaster = BaseLoadBalancer.tablesOnMaster(conf);
555 while (!(tablesOnMaster && isActiveMaster)
556 && !isStopped() && !isAborted()) {
557 sleeper.sleep();
558 }
559 }
560
561 @VisibleForTesting
562 public MasterRpcServices getMasterRpcServices() {
563 return (MasterRpcServices)rpcServices;
564 }
565
566 public boolean balanceSwitch(final boolean b) throws IOException {
567 return getMasterRpcServices().switchBalancer(b, BalanceSwitchMode.ASYNC);
568 }
569
570 @Override
571 protected String getProcessName() {
572 return MASTER;
573 }
574
575 @Override
576 protected boolean canCreateBaseZNode() {
577 return true;
578 }
579
580 @Override
581 protected boolean canUpdateTableDescriptor() {
582 return true;
583 }
584
585 @Override
586 protected RSRpcServices createRpcServices() throws IOException {
587 return new MasterRpcServices(this);
588 }
589
590 @Override
591 protected void configureInfoServer() {
592 infoServer.addServlet("master-status", "/master-status", MasterStatusServlet.class);
593 infoServer.setAttribute(MASTER, this);
594 if (BaseLoadBalancer.tablesOnMaster(conf)) {
595 super.configureInfoServer();
596 }
597 }
598
599 @Override
600 protected Class<? extends HttpServlet> getDumpServlet() {
601 return MasterDumpServlet.class;
602 }
603
604
605
606
607
608 private void doMetrics() {
609 try {
610 if (assignmentManager != null) {
611 assignmentManager.updateRegionsInTransitionMetrics();
612 }
613 } catch (Throwable e) {
614 LOG.error("Couldn't update metrics: " + e.getMessage());
615 }
616 }
617
618 MetricsMaster getMasterMetrics() {
619 return metricsMaster;
620 }
621
622
623
624
625
626
627
628
629 void initializeZKBasedSystemTrackers() throws IOException,
630 InterruptedException, KeeperException, CoordinatedStateException {
631 this.balancer = LoadBalancerFactory.getLoadBalancer(conf);
632 this.normalizer = RegionNormalizerFactory.getRegionNormalizer(conf);
633 this.normalizer.setMasterServices(this);
634 this.normalizer.setMasterRpcServices((MasterRpcServices)rpcServices);
635 this.loadBalancerTracker = new LoadBalancerTracker(zooKeeper, this);
636 this.loadBalancerTracker.start();
637
638 this.regionNormalizerTracker = new RegionNormalizerTracker(zooKeeper, this);
639 this.regionNormalizerTracker.start();
640
641 this.splitOrMergeTracker = new SplitOrMergeTracker(zooKeeper, conf, this);
642 this.splitOrMergeTracker.start();
643
644 this.assignmentManager = new AssignmentManager(this, serverManager,
645 this.balancer, this.service, this.metricsMaster,
646 this.tableLockManager);
647 zooKeeper.registerListenerFirst(assignmentManager);
648
649 this.regionServerTracker = new RegionServerTracker(zooKeeper, this,
650 this.serverManager);
651 this.regionServerTracker.start();
652
653 this.drainingServerTracker = new DrainingServerTracker(zooKeeper, this,
654 this.serverManager);
655 this.drainingServerTracker.start();
656
657
658
659 boolean wasUp = this.clusterStatusTracker.isClusterUp();
660 if (!wasUp) this.clusterStatusTracker.setClusterUp();
661
662 LOG.info("Server active/primary master=" + this.serverName +
663 ", sessionid=0x" +
664 Long.toHexString(this.zooKeeper.getRecoverableZooKeeper().getSessionId()) +
665 ", setting cluster-up flag (Was=" + wasUp + ")");
666
667
668 this.snapshotManager = new SnapshotManager();
669 this.mpmHost = new MasterProcedureManagerHost();
670 this.mpmHost.register(this.snapshotManager);
671 this.mpmHost.register(new MasterFlushTableProcedureManager());
672 this.mpmHost.loadProcedures(conf);
673 this.mpmHost.initialize(this, this.metricsMaster);
674 }
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696 private void finishActiveMasterInitialization(MonitoredTask status)
697 throws IOException, InterruptedException, KeeperException, CoordinatedStateException {
698
699 isActiveMaster = true;
700 Thread zombieDetector = new Thread(new InitializationMonitor(this),
701 "ActiveMasterInitializationMonitor-" + System.currentTimeMillis());
702 zombieDetector.start();
703
704
705
706
707
708
709
710 status.setStatus("Initializing Master file system");
711
712 this.masterActiveTime = System.currentTimeMillis();
713
714 this.fileSystemManager = new MasterFileSystem(this, this);
715
716
717 this.tableDescriptors.setCacheOn();
718
719 this.tableDescriptors.get(TableName.META_TABLE_NAME).setRegionReplication(
720 conf.getInt(HConstants.META_REPLICAS_NUM, HConstants.DEFAULT_META_REPLICA_NUM));
721
722 if (preLoadTableDescriptors) {
723 status.setStatus("Pre-loading table descriptors");
724 this.tableDescriptors.getAll();
725 }
726
727
728 status.setStatus("Publishing Cluster ID in ZooKeeper");
729 ZKClusterId.setClusterId(this.zooKeeper, fileSystemManager.getClusterId());
730 this.serverManager = createServerManager(this, this);
731
732 setupClusterConnection();
733
734
735 this.tableLockManager.reapWriteLocks();
736
737 status.setStatus("Initializing ZK system trackers");
738 initializeZKBasedSystemTrackers();
739
740
741 status.setStatus("Initializing master coprocessors");
742 this.cpHost = new MasterCoprocessorHost(this, this.conf);
743
744
745 status.setStatus("Initializing master service threads");
746 startServiceThreads();
747
748
749 sleeper.skipSleepCycle();
750
751
752 this.serverManager.waitForRegionServers(status);
753
754 for (ServerName sn: this.regionServerTracker.getOnlineServers()) {
755
756 if (!this.serverManager.isServerOnline(sn)
757 && serverManager.checkAndRecordNewServer(sn, ServerLoad.EMPTY_SERVERLOAD)) {
758 LOG.info("Registered server found up in zk but who has not yet reported in: " + sn);
759 }
760 }
761
762
763
764
765 Set<ServerName> previouslyFailedServers =
766 this.fileSystemManager.getFailedServersFromLogFolders();
767
768
769 ServerName oldMetaServerLocation = metaTableLocator.getMetaRegionLocation(this.getZooKeeper());
770 if (oldMetaServerLocation != null && previouslyFailedServers.contains(oldMetaServerLocation)) {
771 splitMetaLogBeforeAssignment(oldMetaServerLocation);
772
773
774 }
775 Set<ServerName> previouslyFailedMetaRSs = getPreviouselyFailedMetaServersFromZK();
776
777
778
779
780
781
782
783
784 previouslyFailedMetaRSs.addAll(previouslyFailedServers);
785
786 this.initializationBeforeMetaAssignment = true;
787
788
789 if (BaseLoadBalancer.tablesOnMaster(conf)) {
790 waitForServerOnline();
791 }
792
793
794 this.balancer.setClusterStatus(getClusterStatus());
795 this.balancer.setMasterServices(this);
796 this.balancer.initialize();
797
798
799
800 if (isStopped()) return;
801
802
803 status.setStatus("Assigning Meta Region");
804 assignMeta(status, previouslyFailedMetaRSs, HRegionInfo.DEFAULT_REPLICA_ID);
805
806
807 if (isStopped()) return;
808
809 status.setStatus("Submitting log splitting work for previously failed region servers");
810
811
812 for (ServerName tmpServer : previouslyFailedServers) {
813 this.serverManager.processDeadServer(tmpServer, true);
814 }
815
816
817
818 if (this.conf.getBoolean("hbase.MetaMigrationConvertingToPB", true)) {
819 MetaMigrationConvertingToPB.updateMetaIfNecessary(this);
820 }
821
822
823 status.setStatus("Starting assignment manager");
824 this.assignmentManager.joinCluster();
825
826
827 this.balancer.setClusterStatus(getClusterStatus());
828
829
830 status.setStatus("Starting balancer and catalog janitor");
831 this.clusterStatusChore = new ClusterStatusChore(this, balancer);
832 getChoreService().scheduleChore(clusterStatusChore);
833 this.balancerChore = new BalancerChore(this);
834 getChoreService().scheduleChore(balancerChore);
835 this.normalizerChore = new RegionNormalizerChore(this);
836 getChoreService().scheduleChore(normalizerChore);
837 this.catalogJanitorChore = new CatalogJanitor(this, this);
838 getChoreService().scheduleChore(catalogJanitorChore);
839
840
841 periodicDoMetricsChore = new PeriodicDoMetrics(msgInterval, this);
842 getChoreService().scheduleChore(periodicDoMetricsChore);
843
844 status.setStatus("Starting namespace manager");
845 initNamespace();
846
847 if (this.cpHost != null) {
848 try {
849 this.cpHost.preMasterInitialization();
850 } catch (IOException e) {
851 LOG.error("Coprocessor preMasterInitialization() hook failed", e);
852 }
853 }
854
855 status.markComplete("Initialization successful");
856 LOG.info("Master has completed initialization");
857 configurationManager.registerObserver(this.balancer);
858
859
860 setInitialized(true);
861
862 status.setStatus("Starting quota manager");
863 initQuotaManager();
864
865
866 Set<ServerName> EMPTY_SET = new HashSet<ServerName>();
867 int numReplicas = conf.getInt(HConstants.META_REPLICAS_NUM,
868 HConstants.DEFAULT_META_REPLICA_NUM);
869 for (int i = 1; i < numReplicas; i++) {
870 assignMeta(status, EMPTY_SET, i);
871 }
872 unassignExcessMetaReplica(zooKeeper, numReplicas);
873
874
875
876
877 this.serverManager.clearDeadServersWithSameHostNameAndPortOfOnlineServer();
878
879
880 status.setStatus("Checking ZNode ACLs");
881 zooKeeper.checkAndSetZNodeAcls();
882
883 status.setStatus("Calling postStartMaster coprocessors");
884 if (this.cpHost != null) {
885
886 try {
887 this.cpHost.postStartMaster();
888 } catch (IOException ioe) {
889 LOG.error("Coprocessor postStartMaster() hook failed", ioe);
890 }
891 }
892
893 zombieDetector.interrupt();
894 }
895
896 private void initQuotaManager() throws IOException {
897 quotaManager = new MasterQuotaManager(this);
898 this.assignmentManager.setRegionStateListener((RegionStateListener) quotaManager);
899 quotaManager.start();
900 }
901
902
903
904
905
906
907
908
909
910 ServerManager createServerManager(final Server master,
911 final MasterServices services)
912 throws IOException {
913
914
915 return new ServerManager(master, services);
916 }
917
918 private void unassignExcessMetaReplica(ZooKeeperWatcher zkw, int numMetaReplicasConfigured) {
919
920
921 try {
922 List<String> metaReplicaZnodes = zooKeeper.getMetaReplicaNodes();
923 for (String metaReplicaZnode : metaReplicaZnodes) {
924 int replicaId = zooKeeper.getMetaReplicaIdFromZnode(metaReplicaZnode);
925 if (replicaId >= numMetaReplicasConfigured) {
926 RegionState r = MetaTableLocator.getMetaRegionState(zkw, replicaId);
927 LOG.info("Closing excess replica of meta region " + r.getRegion());
928
929 ServerManager.closeRegionSilentlyAndWait(getConnection(), r.getServerName(),
930 r.getRegion(), 30000);
931 ZKUtil.deleteNode(zkw, zkw.getZNodeForReplica(replicaId));
932 }
933 }
934 } catch (Exception ex) {
935
936
937 LOG.warn("Ignoring exception " + ex);
938 }
939 }
940
941
942
943
944
945
946
947
948
949
950 void assignMeta(MonitoredTask status, Set<ServerName> previouslyFailedMetaRSs, int replicaId)
951 throws InterruptedException, IOException, KeeperException {
952
953 int assigned = 0;
954 long timeout = this.conf.getLong("hbase.catalog.verification.timeout", 1000);
955 if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
956 status.setStatus("Assigning hbase:meta region");
957 } else {
958 status.setStatus("Assigning hbase:meta region, replicaId " + replicaId);
959 }
960
961 RegionStates regionStates = assignmentManager.getRegionStates();
962 RegionState metaState = MetaTableLocator.getMetaRegionState(getZooKeeper(), replicaId);
963 HRegionInfo hri = RegionReplicaUtil.getRegionInfoForReplica(HRegionInfo.FIRST_META_REGIONINFO,
964 replicaId);
965 ServerName currentMetaServer = metaState.getServerName();
966 if (!ConfigUtil.useZKForAssignment(conf)) {
967 regionStates.createRegionState(hri, metaState.getState(),
968 currentMetaServer, null);
969 } else {
970 regionStates.createRegionState(hri);
971 }
972 boolean rit = this.assignmentManager.
973 processRegionInTransitionAndBlockUntilAssigned(hri);
974 boolean metaRegionLocation = metaTableLocator.verifyMetaRegionLocation(
975 this.getConnection(), this.getZooKeeper(), timeout, replicaId);
976 if (!metaRegionLocation || !metaState.isOpened()) {
977
978
979 assigned++;
980 if (!ConfigUtil.useZKForAssignment(conf)) {
981 assignMetaZkLess(regionStates, metaState, timeout, previouslyFailedMetaRSs);
982 } else if (!rit) {
983
984 if (currentMetaServer != null) {
985
986
987
988
989
990
991
992 if (serverManager.isServerOnline(currentMetaServer)) {
993 LOG.info("Forcing expire of " + currentMetaServer);
994 serverManager.expireServer(currentMetaServer);
995 }
996 if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
997 splitMetaLogBeforeAssignment(currentMetaServer);
998 previouslyFailedMetaRSs.add(currentMetaServer);
999 }
1000 }
1001 assignmentManager.assignMeta(hri);
1002 }
1003 } else {
1004
1005 regionStates.updateRegionState(hri, State.OPEN, currentMetaServer);
1006 this.assignmentManager.regionOnline(hri, currentMetaServer);
1007 }
1008
1009 if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) enableMeta(TableName.META_TABLE_NAME);
1010
1011 if ((RecoveryMode.LOG_REPLAY == this.getMasterFileSystem().getLogRecoveryMode())
1012 && (!previouslyFailedMetaRSs.isEmpty())) {
1013
1014 status.setStatus("replaying log for Meta Region");
1015 this.fileSystemManager.splitMetaLog(previouslyFailedMetaRSs);
1016 }
1017
1018
1019
1020
1021
1022 if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) enableCrashedServerProcessing(assigned != 0);
1023 LOG.info("hbase:meta with replicaId " + replicaId + " assigned=" + assigned + ", rit=" + rit +
1024 ", location=" + metaTableLocator.getMetaRegionLocation(this.getZooKeeper(), replicaId));
1025 status.setStatus("META assigned.");
1026 }
1027
1028 private void assignMetaZkLess(RegionStates regionStates, RegionState regionState, long timeout,
1029 Set<ServerName> previouslyFailedRs) throws IOException, KeeperException {
1030 ServerName currentServer = regionState.getServerName();
1031 if (serverManager.isServerOnline(currentServer)) {
1032 LOG.info("Meta was in transition on " + currentServer);
1033 assignmentManager.processRegionInTransitionZkLess();
1034 } else {
1035 if (currentServer != null) {
1036 if (regionState.getRegion().getReplicaId() == HRegionInfo.DEFAULT_REPLICA_ID) {
1037 splitMetaLogBeforeAssignment(currentServer);
1038 regionStates.logSplit(HRegionInfo.FIRST_META_REGIONINFO);
1039 previouslyFailedRs.add(currentServer);
1040 }
1041 }
1042 LOG.info("Re-assigning hbase:meta, it was on " + currentServer);
1043 regionStates.updateRegionState(regionState.getRegion(), State.OFFLINE);
1044 assignmentManager.assignMeta(regionState.getRegion());
1045 }
1046 }
1047
1048 void initNamespace() throws IOException {
1049
1050 tableNamespaceManager = new TableNamespaceManager(this);
1051 tableNamespaceManager.start();
1052 }
1053
1054 boolean isCatalogJanitorEnabled() {
1055 return catalogJanitorChore != null ?
1056 catalogJanitorChore.getEnabled() : false;
1057 }
1058
1059 private void splitMetaLogBeforeAssignment(ServerName currentMetaServer) throws IOException {
1060 if (RecoveryMode.LOG_REPLAY == this.getMasterFileSystem().getLogRecoveryMode()) {
1061
1062 Set<HRegionInfo> regions = new HashSet<HRegionInfo>();
1063 regions.add(HRegionInfo.FIRST_META_REGIONINFO);
1064 this.fileSystemManager.prepareLogReplay(currentMetaServer, regions);
1065 } else {
1066
1067 this.fileSystemManager.splitMetaLog(currentMetaServer);
1068 }
1069 }
1070
1071 private void enableCrashedServerProcessing(final boolean waitForMeta)
1072 throws IOException, InterruptedException {
1073
1074
1075
1076
1077 if (!isServerCrashProcessingEnabled()) {
1078 setServerCrashProcessingEnabled(true);
1079 this.serverManager.processQueuedDeadServers();
1080 }
1081
1082 if (waitForMeta) {
1083 metaTableLocator.waitMetaRegionLocation(this.getZooKeeper());
1084
1085
1086 this.assignmentManager.waitForAssignment(HRegionInfo.FIRST_META_REGIONINFO);
1087 }
1088 }
1089
1090 private void enableMeta(TableName metaTableName) {
1091 if (!this.assignmentManager.getTableStateManager().isTableState(metaTableName,
1092 ZooKeeperProtos.Table.State.ENABLED)) {
1093 this.assignmentManager.setEnabledTable(metaTableName);
1094 }
1095 }
1096
1097
1098
1099
1100
1101
1102 private Set<ServerName> getPreviouselyFailedMetaServersFromZK() throws KeeperException {
1103 Set<ServerName> result = new HashSet<ServerName>();
1104 String metaRecoveringZNode = ZKUtil.joinZNode(zooKeeper.recoveringRegionsZNode,
1105 HRegionInfo.FIRST_META_REGIONINFO.getEncodedName());
1106 List<String> regionFailedServers = ZKUtil.listChildrenNoWatch(zooKeeper, metaRecoveringZNode);
1107 if (regionFailedServers == null) return result;
1108
1109 for(String failedServer : regionFailedServers) {
1110 ServerName server = ServerName.parseServerName(failedServer);
1111 result.add(server);
1112 }
1113 return result;
1114 }
1115
1116 @Override
1117 public TableDescriptors getTableDescriptors() {
1118 return this.tableDescriptors;
1119 }
1120
1121 @Override
1122 public ServerManager getServerManager() {
1123 return this.serverManager;
1124 }
1125
1126 @Override
1127 public MasterFileSystem getMasterFileSystem() {
1128 return this.fileSystemManager;
1129 }
1130
1131 @Override
1132 public TableNamespaceManager getTableNamespaceManager() {
1133 return tableNamespaceManager;
1134 }
1135
1136
1137
1138
1139
1140
1141
1142
1143 private void startServiceThreads() throws IOException{
1144
1145 this.service.startExecutorService(ExecutorType.MASTER_OPEN_REGION,
1146 conf.getInt("hbase.master.executor.openregion.threads", 5));
1147 this.service.startExecutorService(ExecutorType.MASTER_CLOSE_REGION,
1148 conf.getInt("hbase.master.executor.closeregion.threads", 5));
1149 this.service.startExecutorService(ExecutorType.MASTER_SERVER_OPERATIONS,
1150 conf.getInt("hbase.master.executor.serverops.threads", 5));
1151 this.service.startExecutorService(ExecutorType.MASTER_META_SERVER_OPERATIONS,
1152 conf.getInt("hbase.master.executor.serverops.threads", 5));
1153 this.service.startExecutorService(ExecutorType.M_LOG_REPLAY_OPS,
1154 conf.getInt("hbase.master.executor.logreplayops.threads", 10));
1155
1156
1157
1158
1159
1160
1161 this.service.startExecutorService(ExecutorType.MASTER_TABLE_OPERATIONS, 1);
1162 startProcedureExecutor();
1163
1164
1165 int cleanerInterval = conf.getInt("hbase.master.cleaner.interval", 60 * 1000);
1166 this.logCleaner =
1167 new LogCleaner(cleanerInterval,
1168 this, conf, getMasterFileSystem().getFileSystem(),
1169 getMasterFileSystem().getOldLogDir());
1170 getChoreService().scheduleChore(logCleaner);
1171
1172
1173 Path archiveDir = HFileArchiveUtil.getArchivePath(conf);
1174 this.hfileCleaner = new HFileCleaner(cleanerInterval, this, conf, getMasterFileSystem()
1175 .getFileSystem(), archiveDir);
1176 getChoreService().scheduleChore(hfileCleaner);
1177 serviceStarted = true;
1178 if (LOG.isTraceEnabled()) {
1179 LOG.trace("Started service threads");
1180 }
1181 if (!conf.getBoolean(HConstants.ZOOKEEPER_USEMULTI, true)) {
1182 try {
1183 replicationZKLockCleanerChore = new ReplicationZKLockCleanerChore(this, this,
1184 cleanerInterval, this.getZooKeeper(), this.conf);
1185 getChoreService().scheduleChore(replicationZKLockCleanerChore);
1186 } catch (Exception e) {
1187 LOG.error("start replicationZKLockCleanerChore failed", e);
1188 }
1189 }
1190 }
1191
1192 @Override
1193 protected void sendShutdownInterrupt() {
1194 super.sendShutdownInterrupt();
1195 stopProcedureExecutor();
1196 }
1197
1198 @Override
1199 protected void stopServiceThreads() {
1200 if (masterJettyServer != null) {
1201 LOG.info("Stopping master jetty server");
1202 try {
1203 masterJettyServer.stop();
1204 } catch (Exception e) {
1205 LOG.error("Failed to stop master jetty server", e);
1206 }
1207 }
1208 super.stopServiceThreads();
1209 stopChores();
1210
1211
1212
1213 if (!isAborted() && this.serverManager != null &&
1214 this.serverManager.isClusterShutdown()) {
1215 this.serverManager.letRegionServersShutdown();
1216 }
1217 if (LOG.isDebugEnabled()) {
1218 LOG.debug("Stopping service threads");
1219 }
1220
1221 if (this.logCleaner != null) this.logCleaner.cancel(true);
1222 if (this.hfileCleaner != null) this.hfileCleaner.cancel(true);
1223 if (this.replicationZKLockCleanerChore != null) this.replicationZKLockCleanerChore.cancel(true);
1224 if (this.quotaManager != null) this.quotaManager.stop();
1225 if (this.activeMasterManager != null) this.activeMasterManager.stop();
1226 if (this.serverManager != null) this.serverManager.stop();
1227 if (this.assignmentManager != null) this.assignmentManager.stop();
1228 if (this.fileSystemManager != null) this.fileSystemManager.stop();
1229 if (this.mpmHost != null) this.mpmHost.stop("server shutting down.");
1230 }
1231
1232 private void startProcedureExecutor() throws IOException {
1233 final MasterProcedureEnv procEnv = new MasterProcedureEnv(this);
1234 final Path logDir = new Path(fileSystemManager.getRootDir(),
1235 MasterProcedureConstants.MASTER_PROCEDURE_LOGDIR);
1236
1237 procedureStore = new WALProcedureStore(conf, fileSystemManager.getFileSystem(), logDir,
1238 new MasterProcedureEnv.WALStoreLeaseRecovery(this));
1239 procedureStore.registerListener(new MasterProcedureEnv.MasterProcedureStoreListener(this));
1240 procedureExecutor = new ProcedureExecutor(conf, procEnv, procedureStore,
1241 procEnv.getProcedureQueue());
1242
1243 final int numThreads = conf.getInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS,
1244 Math.max(Runtime.getRuntime().availableProcessors(),
1245 MasterProcedureConstants.DEFAULT_MIN_MASTER_PROCEDURE_THREADS));
1246 final boolean abortOnCorruption = conf.getBoolean(
1247 MasterProcedureConstants.EXECUTOR_ABORT_ON_CORRUPTION,
1248 MasterProcedureConstants.DEFAULT_EXECUTOR_ABORT_ON_CORRUPTION);
1249 procedureStore.start(numThreads);
1250 procedureExecutor.start(numThreads, abortOnCorruption);
1251 }
1252
1253 private void stopProcedureExecutor() {
1254 if (procedureExecutor != null) {
1255 procedureExecutor.stop();
1256 }
1257
1258 if (procedureStore != null) {
1259 procedureStore.stop(isAborted());
1260 }
1261 }
1262
1263 private void stopChores() {
1264 if (this.balancerChore != null) {
1265 this.balancerChore.cancel(true);
1266 }
1267 if (this.normalizerChore != null) {
1268 this.normalizerChore.cancel(true);
1269 }
1270 if (this.clusterStatusChore != null) {
1271 this.clusterStatusChore.cancel(true);
1272 }
1273 if (this.catalogJanitorChore != null) {
1274 this.catalogJanitorChore.cancel(true);
1275 }
1276 if (this.clusterStatusPublisherChore != null){
1277 clusterStatusPublisherChore.cancel(true);
1278 }
1279 if (this.periodicDoMetricsChore != null) {
1280 periodicDoMetricsChore.cancel();
1281 }
1282 }
1283
1284
1285
1286
1287
1288 InetAddress getRemoteInetAddress(final int port,
1289 final long serverStartCode) throws UnknownHostException {
1290
1291
1292 InetAddress ia = RpcServer.getRemoteIp();
1293
1294
1295
1296 if (ia == null && serverStartCode == startcode) {
1297 InetSocketAddress isa = rpcServices.getSocketAddress();
1298 if (isa != null && isa.getPort() == port) {
1299 ia = isa.getAddress();
1300 }
1301 }
1302 return ia;
1303 }
1304
1305
1306
1307
1308 private int getBalancerCutoffTime() {
1309 int balancerCutoffTime =
1310 getConfiguration().getInt("hbase.balancer.max.balancing", -1);
1311 if (balancerCutoffTime == -1) {
1312
1313 int balancerPeriod =
1314 getConfiguration().getInt("hbase.balancer.period", 300000);
1315 balancerCutoffTime = balancerPeriod;
1316
1317 if (balancerCutoffTime <= 0) balancerCutoffTime = balancerPeriod;
1318 }
1319 return balancerCutoffTime;
1320 }
1321
1322 public boolean balance() throws IOException {
1323 return balance(false);
1324 }
1325
1326 public boolean balance(boolean force) throws IOException {
1327
1328 if (!isInitialized()) {
1329 LOG.debug("Master has not been initialized, don't run balancer.");
1330 return false;
1331 }
1332
1333 int maximumBalanceTime = getBalancerCutoffTime();
1334 synchronized (this.balancer) {
1335
1336 if (!this.loadBalancerTracker.isBalancerOn()) return false;
1337
1338 if (this.assignmentManager.getRegionStates().isRegionsInTransition()) {
1339 Map<String, RegionState> regionsInTransition =
1340 this.assignmentManager.getRegionStates().getRegionsInTransition();
1341
1342
1343 boolean metaInTransition = assignmentManager.getRegionStates().isMetaRegionInTransition();
1344 String prefix = force && !metaInTransition ? "R" : "Not r";
1345 LOG.debug(prefix + "unning balancer because " + regionsInTransition.size() +
1346 " region(s) in transition: " + org.apache.commons.lang.StringUtils.
1347 abbreviate(regionsInTransition.toString(), 256));
1348 if (!force || metaInTransition) return false;
1349 }
1350 if (this.serverManager.areDeadServersInProgress()) {
1351 LOG.debug("Not running balancer because processing dead regionserver(s): " +
1352 this.serverManager.getDeadServers());
1353 return false;
1354 }
1355
1356 if (this.cpHost != null) {
1357 try {
1358 if (this.cpHost.preBalance()) {
1359 LOG.debug("Coprocessor bypassing balancer request");
1360 return false;
1361 }
1362 } catch (IOException ioe) {
1363 LOG.error("Error invoking master coprocessor preBalance()", ioe);
1364 return false;
1365 }
1366 }
1367
1368 Map<TableName, Map<ServerName, List<HRegionInfo>>> assignmentsByTable =
1369 this.assignmentManager.getRegionStates().getAssignmentsByTable();
1370
1371 List<RegionPlan> plans = new ArrayList<RegionPlan>();
1372
1373
1374 this.balancer.setClusterStatus(getClusterStatus());
1375 for (Entry<TableName, Map<ServerName, List<HRegionInfo>>> e : assignmentsByTable.entrySet()) {
1376 List<RegionPlan> partialPlans = this.balancer.balanceCluster(e.getKey(), e.getValue());
1377 if (partialPlans != null) plans.addAll(partialPlans);
1378 }
1379
1380 long cutoffTime = System.currentTimeMillis() + maximumBalanceTime;
1381 int rpCount = 0;
1382 long totalRegPlanExecTime = 0;
1383 if (plans != null && !plans.isEmpty()) {
1384 for (RegionPlan plan: plans) {
1385 LOG.info("balance " + plan);
1386 long balStartTime = System.currentTimeMillis();
1387
1388 this.assignmentManager.balance(plan);
1389 totalRegPlanExecTime += System.currentTimeMillis()-balStartTime;
1390 rpCount++;
1391 if (rpCount < plans.size() &&
1392
1393 (System.currentTimeMillis() + (totalRegPlanExecTime / rpCount)) > cutoffTime) {
1394
1395 LOG.debug("No more balancing till next balance run; maximumBalanceTime=" +
1396 maximumBalanceTime);
1397 break;
1398 }
1399 }
1400 }
1401 if (this.cpHost != null) {
1402 try {
1403 this.cpHost.postBalance(rpCount < plans.size() ? plans.subList(0, rpCount) : plans);
1404 } catch (IOException ioe) {
1405
1406 LOG.error("Error invoking master coprocessor postBalance()", ioe);
1407 }
1408 }
1409 }
1410
1411
1412 return true;
1413 }
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424 public boolean normalizeRegions() throws IOException, CoordinatedStateException {
1425 if (!isInitialized()) {
1426 LOG.debug("Master has not been initialized, don't run region normalizer.");
1427 return false;
1428 }
1429
1430 if (!this.regionNormalizerTracker.isNormalizerOn()) {
1431 LOG.debug("Region normalization is disabled, don't run region normalizer.");
1432 return false;
1433 }
1434
1435 synchronized (this.normalizer) {
1436
1437 List<TableName> allEnabledTables = new ArrayList<>(
1438 this.assignmentManager.getTableStateManager().getTablesInStates(
1439 ZooKeeperProtos.Table.State.ENABLED));
1440
1441 Collections.shuffle(allEnabledTables);
1442
1443 for (TableName table : allEnabledTables) {
1444 if (quotaManager.getNamespaceQuotaManager() != null &&
1445 quotaManager.getNamespaceQuotaManager().getState(table.getNamespaceAsString()) != null){
1446 LOG.debug("Skipping normalizing " + table + " since its namespace has quota");
1447 continue;
1448 }
1449 if (table.isSystemTable() || (getTableDescriptors().get(table) != null &&
1450 !getTableDescriptors().get(table).isNormalizationEnabled())) {
1451 LOG.debug("Skipping normalization for table: " + table + ", as it's either system"
1452 + " table or doesn't have auto normalization turned on");
1453 continue;
1454 }
1455 List<NormalizationPlan> plans = this.normalizer.computePlanForTable(table);
1456 if (plans != null) {
1457 for (NormalizationPlan plan : plans) {
1458 plan.execute(clusterConnection.getAdmin());
1459 if (plan.getType() == PlanType.SPLIT) {
1460 splitPlanCount++;
1461 } else if (plan.getType() == PlanType.MERGE) {
1462 mergePlanCount++;
1463 }
1464 }
1465 }
1466 }
1467 }
1468
1469
1470 return true;
1471 }
1472
1473
1474
1475
1476 String getClientIdAuditPrefix() {
1477 return "Client=" + RpcServer.getRequestUserName() + "/" + RpcServer.getRemoteAddress();
1478 }
1479
1480
1481
1482
1483
1484
1485
1486 public void setCatalogJanitorEnabled(final boolean b) {
1487 this.catalogJanitorChore.setEnabled(b);
1488 }
1489
1490 @Override
1491 public void dispatchMergingRegions(final HRegionInfo region_a,
1492 final HRegionInfo region_b, final boolean forcible, final User user) throws IOException {
1493 checkInitialized();
1494 this.service.submit(new DispatchMergingRegionHandler(this,
1495 this.catalogJanitorChore, region_a, region_b, forcible, user));
1496 }
1497
1498 void move(final byte[] encodedRegionName,
1499 final byte[] destServerName) throws HBaseIOException {
1500 RegionState regionState = assignmentManager.getRegionStates().
1501 getRegionState(Bytes.toString(encodedRegionName));
1502 if (regionState == null) {
1503 throw new UnknownRegionException(Bytes.toStringBinary(encodedRegionName));
1504 }
1505
1506 HRegionInfo hri = regionState.getRegion();
1507 ServerName dest;
1508 if (destServerName == null || destServerName.length == 0) {
1509 LOG.info("Passed destination servername is null/empty so " +
1510 "choosing a server at random");
1511 final List<ServerName> destServers = this.serverManager.createDestinationServersList(
1512 regionState.getServerName());
1513 dest = balancer.randomAssignment(hri, destServers);
1514 if (dest == null) {
1515 LOG.debug("Unable to determine a plan to assign " + hri);
1516 return;
1517 }
1518 } else {
1519 dest = ServerName.valueOf(Bytes.toString(destServerName));
1520 if (dest.equals(serverName) && balancer instanceof BaseLoadBalancer
1521 && !((BaseLoadBalancer)balancer).shouldBeOnMaster(hri)) {
1522
1523
1524
1525 LOG.debug("Skipping move of region " + hri.getRegionNameAsString()
1526 + " to avoid unnecessary region moving later by load balancer,"
1527 + " because it should not be on master");
1528 return;
1529 }
1530 }
1531
1532 if (dest.equals(regionState.getServerName())) {
1533 LOG.debug("Skipping move of region " + hri.getRegionNameAsString()
1534 + " because region already assigned to the same server " + dest + ".");
1535 return;
1536 }
1537
1538
1539 RegionPlan rp = new RegionPlan(hri, regionState.getServerName(), dest);
1540
1541 try {
1542 checkInitialized();
1543 if (this.cpHost != null) {
1544 if (this.cpHost.preMove(hri, rp.getSource(), rp.getDestination())) {
1545 return;
1546 }
1547 }
1548
1549
1550
1551 serverManager.sendRegionWarmup(rp.getDestination(), hri);
1552
1553 LOG.info(getClientIdAuditPrefix() + " move " + rp + ", running balancer");
1554 this.assignmentManager.balance(rp);
1555 if (this.cpHost != null) {
1556 this.cpHost.postMove(hri, rp.getSource(), rp.getDestination());
1557 }
1558 } catch (IOException ioe) {
1559 if (ioe instanceof HBaseIOException) {
1560 throw (HBaseIOException)ioe;
1561 }
1562 throw new HBaseIOException(ioe);
1563 }
1564 }
1565
1566 @Override
1567 public long createTable(
1568 final HTableDescriptor hTableDescriptor,
1569 final byte [][] splitKeys,
1570 final long nonceGroup,
1571 final long nonce) throws IOException {
1572 if (isStopped()) {
1573 throw new MasterNotRunningException();
1574 }
1575
1576 String namespace = hTableDescriptor.getTableName().getNamespaceAsString();
1577 ensureNamespaceExists(namespace);
1578
1579 final HRegionInfo[] newRegions =
1580 ModifyRegionUtils.createHRegionInfos(hTableDescriptor, splitKeys);
1581 checkInitialized();
1582 sanityCheckTableDescriptor(hTableDescriptor);
1583
1584 return MasterProcedureUtil.submitProcedure(
1585 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
1586 @Override
1587 protected void run() throws IOException {
1588 getMaster().getMasterCoprocessorHost().preCreateTable(hTableDescriptor, newRegions);
1589
1590 LOG.info(getClientIdAuditPrefix() + " create " + hTableDescriptor);
1591
1592
1593
1594 ProcedurePrepareLatch latch = ProcedurePrepareLatch.createLatch();
1595 submitProcedure(new CreateTableProcedure(
1596 procedureExecutor.getEnvironment(), hTableDescriptor, newRegions, latch));
1597 latch.await();
1598
1599 getMaster().getMasterCoprocessorHost().postCreateTable(hTableDescriptor, newRegions);
1600 }
1601
1602 @Override
1603 protected String getDescription() {
1604 return "CreateTableProcedure";
1605 }
1606 });
1607 }
1608
1609 @Override
1610 public long createSystemTable(final HTableDescriptor hTableDescriptor) throws IOException {
1611 if (isStopped()) {
1612 throw new MasterNotRunningException();
1613 }
1614
1615 TableName tableName = hTableDescriptor.getTableName();
1616 if (!(tableName.isSystemTable())) {
1617 throw new IllegalArgumentException(
1618 "Only system table creation can use this createSystemTable API");
1619 }
1620
1621 HRegionInfo[] newRegions = ModifyRegionUtils.createHRegionInfos(hTableDescriptor, null);
1622
1623 LOG.info(getClientIdAuditPrefix() + " create " + hTableDescriptor);
1624
1625
1626
1627 long procId = this.procedureExecutor.submitProcedure(
1628 new CreateTableProcedure(procedureExecutor.getEnvironment(), hTableDescriptor, newRegions));
1629
1630 return procId;
1631 }
1632
1633
1634
1635
1636
1637
1638 private void sanityCheckTableDescriptor(final HTableDescriptor htd) throws IOException {
1639 final String CONF_KEY = "hbase.table.sanity.checks";
1640 boolean logWarn = false;
1641 if (!conf.getBoolean(CONF_KEY, true)) {
1642 logWarn = true;
1643 }
1644 String tableVal = htd.getConfigurationValue(CONF_KEY);
1645 if (tableVal != null && !Boolean.valueOf(tableVal)) {
1646 logWarn = true;
1647 }
1648
1649
1650 long maxFileSizeLowerLimit = 2 * 1024 * 1024L;
1651 long maxFileSize = htd.getMaxFileSize();
1652 if (maxFileSize < 0) {
1653 maxFileSize = conf.getLong(HConstants.HREGION_MAX_FILESIZE, maxFileSizeLowerLimit);
1654 }
1655 if (maxFileSize < conf.getLong("hbase.hregion.max.filesize.limit", maxFileSizeLowerLimit)) {
1656 String message = "MAX_FILESIZE for table descriptor or "
1657 + "\"hbase.hregion.max.filesize\" (" + maxFileSize
1658 + ") is too small, which might cause over splitting into unmanageable "
1659 + "number of regions.";
1660 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1661 }
1662
1663
1664 long flushSizeLowerLimit = 1024 * 1024L;
1665 long flushSize = htd.getMemStoreFlushSize();
1666 if (flushSize < 0) {
1667 flushSize = conf.getLong(HConstants.HREGION_MEMSTORE_FLUSH_SIZE, flushSizeLowerLimit);
1668 }
1669 if (flushSize < conf.getLong("hbase.hregion.memstore.flush.size.limit", flushSizeLowerLimit)) {
1670 String message = "MEMSTORE_FLUSHSIZE for table descriptor or "
1671 + "\"hbase.hregion.memstore.flush.size\" ("+flushSize+") is too small, which might cause"
1672 + " very frequent flushing.";
1673 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1674 }
1675
1676
1677 try {
1678 checkClassLoading(conf, htd);
1679 } catch (Exception ex) {
1680 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, ex.getMessage(), null);
1681 }
1682
1683
1684 try {
1685 checkCompression(htd);
1686 } catch (IOException e) {
1687 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, e.getMessage(), e);
1688 }
1689
1690
1691 try {
1692 checkEncryption(conf, htd);
1693 } catch (IOException e) {
1694 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, e.getMessage(), e);
1695 }
1696
1697 try{
1698 checkCompactionPolicy(conf, htd);
1699 } catch(IOException e){
1700 warnOrThrowExceptionForFailure(false, CONF_KEY, e.getMessage(), e);
1701 }
1702
1703 if (htd.getColumnFamilies().length == 0) {
1704 String message = "Table should have at least one column family.";
1705 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1706 }
1707
1708 for (HColumnDescriptor hcd : htd.getColumnFamilies()) {
1709 if (hcd.getTimeToLive() <= 0) {
1710 String message = "TTL for column family " + hcd.getNameAsString() + " must be positive.";
1711 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1712 }
1713
1714
1715 if (hcd.getBlocksize() < 1024 || hcd.getBlocksize() > 16 * 1024 * 1024) {
1716 String message = "Block size for column family " + hcd.getNameAsString()
1717 + " must be between 1K and 16MB.";
1718 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1719 }
1720
1721
1722 if (hcd.getMinVersions() < 0) {
1723 String message = "Min versions for column family " + hcd.getNameAsString()
1724 + " must be positive.";
1725 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1726 }
1727
1728
1729
1730
1731
1732 if (hcd.getMinVersions() > hcd.getMaxVersions()) {
1733 String message = "Min versions for column family " + hcd.getNameAsString()
1734 + " must be less than the Max versions.";
1735 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1736 }
1737
1738
1739 if (hcd.getScope() < 0) {
1740 String message = "Replication scope for column family "
1741 + hcd.getNameAsString() + " must be positive.";
1742 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1743 }
1744
1745
1746
1747 if (hcd.getDFSReplication() < 0) {
1748 String message = "HFile Replication for column family " + hcd.getNameAsString()
1749 + " must be greater than zero.";
1750 warnOrThrowExceptionForFailure(logWarn, CONF_KEY, message, null);
1751 }
1752
1753
1754 }
1755 }
1756
1757 private void checkCompactionPolicy(Configuration conf, HTableDescriptor htd)
1758 throws IOException {
1759
1760
1761 String className =
1762 htd.getConfigurationValue(DefaultStoreEngine.DEFAULT_COMPACTION_POLICY_CLASS_KEY);
1763 if (className == null) {
1764 className =
1765 conf.get(DefaultStoreEngine.DEFAULT_COMPACTION_POLICY_CLASS_KEY,
1766 ExploringCompactionPolicy.class.getName());
1767 }
1768
1769 int blockingFileCount = HStore.DEFAULT_BLOCKING_STOREFILE_COUNT;
1770 String sv = htd.getConfigurationValue(HStore.BLOCKING_STOREFILES_KEY);
1771 if (sv != null) {
1772 blockingFileCount = Integer.parseInt(sv);
1773 } else {
1774 blockingFileCount = conf.getInt(HStore.BLOCKING_STOREFILES_KEY, blockingFileCount);
1775 }
1776
1777 for (HColumnDescriptor hcd : htd.getColumnFamilies()) {
1778 String compactionPolicy =
1779 hcd.getConfigurationValue(DefaultStoreEngine.DEFAULT_COMPACTION_POLICY_CLASS_KEY);
1780 if (compactionPolicy == null) {
1781 compactionPolicy = className;
1782 }
1783 if (!compactionPolicy.equals(FIFOCompactionPolicy.class.getName())) {
1784 continue;
1785 }
1786
1787 String message = null;
1788
1789
1790 if (hcd.getTimeToLive() == HColumnDescriptor.DEFAULT_TTL) {
1791 message = "Default TTL is not supported for FIFO compaction";
1792 throw new IOException(message);
1793 }
1794
1795
1796 if (hcd.getMinVersions() > 0) {
1797 message = "MIN_VERSION > 0 is not supported for FIFO compaction";
1798 throw new IOException(message);
1799 }
1800
1801
1802 String sbfc = htd.getConfigurationValue(HStore.BLOCKING_STOREFILES_KEY);
1803 if (sbfc != null) {
1804 blockingFileCount = Integer.parseInt(sbfc);
1805 }
1806 if (blockingFileCount < 1000) {
1807 message =
1808 "blocking file count '" + HStore.BLOCKING_STOREFILES_KEY + "' " + blockingFileCount
1809 + " is below recommended minimum of 1000";
1810 throw new IOException(message);
1811 }
1812 }
1813 }
1814
1815
1816 private static void warnOrThrowExceptionForFailure(boolean logWarn, String confKey,
1817 String message, Exception cause) throws IOException {
1818 if (!logWarn) {
1819 throw new DoNotRetryIOException(message + " Set " + confKey +
1820 " to false at conf or table descriptor if you want to bypass sanity checks", cause);
1821 }
1822 LOG.warn(message);
1823 }
1824
1825 private void startActiveMasterManager(int infoPort) throws KeeperException {
1826 String backupZNode = ZKUtil.joinZNode(
1827 zooKeeper.backupMasterAddressesZNode, serverName.toString());
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838 LOG.info("Adding backup master ZNode " + backupZNode);
1839 if (!MasterAddressTracker.setMasterAddress(zooKeeper, backupZNode,
1840 serverName, infoPort)) {
1841 LOG.warn("Failed create of " + backupZNode + " by " + serverName);
1842 }
1843
1844 activeMasterManager.setInfoPort(infoPort);
1845
1846 Threads.setDaemonThreadRunning(new Thread(new Runnable() {
1847 @Override
1848 public void run() {
1849 int timeout = conf.getInt(HConstants.ZK_SESSION_TIMEOUT,
1850 HConstants.DEFAULT_ZK_SESSION_TIMEOUT);
1851
1852 if (conf.getBoolean(HConstants.MASTER_TYPE_BACKUP,
1853 HConstants.DEFAULT_MASTER_TYPE_BACKUP)) {
1854 LOG.debug("HMaster started in backup mode. "
1855 + "Stalling until master znode is written.");
1856
1857
1858 while (!activeMasterManager.hasActiveMaster()) {
1859 LOG.debug("Waiting for master address ZNode to be written "
1860 + "(Also watching cluster state node)");
1861 Threads.sleep(timeout);
1862 }
1863 }
1864 MonitoredTask status = TaskMonitor.get().createStatus("Master startup");
1865 status.setDescription("Master startup");
1866 try {
1867 if (activeMasterManager.blockUntilBecomingActiveMaster(timeout, status)) {
1868 finishActiveMasterInitialization(status);
1869 }
1870 } catch (Throwable t) {
1871 status.setStatus("Failed to become active: " + t.getMessage());
1872 LOG.fatal("Failed to become active master", t);
1873
1874 if (t instanceof NoClassDefFoundError &&
1875 t.getMessage()
1876 .contains("org/apache/hadoop/hdfs/protocol/HdfsConstants$SafeModeAction")) {
1877
1878 abort("HBase is having a problem with its Hadoop jars. You may need to "
1879 + "recompile HBase against Hadoop version "
1880 + org.apache.hadoop.util.VersionInfo.getVersion()
1881 + " or change your hadoop jars to start properly", t);
1882 } else {
1883 abort("Unhandled exception. Starting shutdown.", t);
1884 }
1885 } finally {
1886 status.cleanup();
1887 }
1888 }
1889 }, getServerName().toShortString() + ".activeMasterManager"));
1890 }
1891
1892 private void checkCompression(final HTableDescriptor htd)
1893 throws IOException {
1894 if (!this.masterCheckCompression) return;
1895 for (HColumnDescriptor hcd : htd.getColumnFamilies()) {
1896 checkCompression(hcd);
1897 }
1898 }
1899
1900 private void checkCompression(final HColumnDescriptor hcd)
1901 throws IOException {
1902 if (!this.masterCheckCompression) return;
1903 CompressionTest.testCompression(hcd.getCompression());
1904 CompressionTest.testCompression(hcd.getCompactionCompression());
1905 }
1906
1907 private void checkEncryption(final Configuration conf, final HTableDescriptor htd)
1908 throws IOException {
1909 if (!this.masterCheckEncryption) return;
1910 for (HColumnDescriptor hcd : htd.getColumnFamilies()) {
1911 checkEncryption(conf, hcd);
1912 }
1913 }
1914
1915 private void checkEncryption(final Configuration conf, final HColumnDescriptor hcd)
1916 throws IOException {
1917 if (!this.masterCheckEncryption) return;
1918 EncryptionTest.testEncryption(conf, hcd.getEncryptionType(), hcd.getEncryptionKey());
1919 }
1920
1921 private void checkClassLoading(final Configuration conf, final HTableDescriptor htd)
1922 throws IOException {
1923 RegionSplitPolicy.getSplitPolicyClass(htd, conf);
1924 RegionCoprocessorHost.testTableCoprocessorAttrs(conf, htd);
1925 }
1926
1927 private static boolean isCatalogTable(final TableName tableName) {
1928 return tableName.equals(TableName.META_TABLE_NAME);
1929 }
1930
1931 @Override
1932 public long deleteTable(
1933 final TableName tableName,
1934 final long nonceGroup,
1935 final long nonce) throws IOException {
1936 checkInitialized();
1937
1938 return MasterProcedureUtil.submitProcedure(
1939 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
1940 @Override
1941 protected void run() throws IOException {
1942 getMaster().getMasterCoprocessorHost().preDeleteTable(tableName);
1943
1944 LOG.info(getClientIdAuditPrefix() + " delete " + tableName);
1945
1946
1947 ProcedurePrepareLatch latch = ProcedurePrepareLatch.createLatch();
1948 submitProcedure(new DeleteTableProcedure(procedureExecutor.getEnvironment(),
1949 tableName, latch));
1950 latch.await();
1951
1952 getMaster().getMasterCoprocessorHost().postDeleteTable(tableName);
1953 }
1954
1955 @Override
1956 protected String getDescription() {
1957 return "DeleteTableProcedure";
1958 }
1959 });
1960 }
1961
1962 @Override
1963 public void truncateTable(
1964 final TableName tableName,
1965 final boolean preserveSplits,
1966 final long nonceGroup,
1967 final long nonce) throws IOException {
1968 checkInitialized();
1969
1970 MasterProcedureUtil.submitProcedure(
1971 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
1972 @Override
1973 protected void run() throws IOException {
1974 getMaster().getMasterCoprocessorHost().preTruncateTable(tableName);
1975
1976 LOG.info(getClientIdAuditPrefix() + " truncate " + tableName);
1977
1978 long procId = submitProcedure(new TruncateTableProcedure(procedureExecutor.getEnvironment(),
1979 tableName, preserveSplits));
1980 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
1981
1982 getMaster().getMasterCoprocessorHost().postTruncateTable(tableName);
1983 }
1984
1985 @Override
1986 protected String getDescription() {
1987 return "TruncateTableProcedure";
1988 }
1989 });
1990 }
1991
1992 @Override
1993 public void addColumn(
1994 final TableName tableName,
1995 final HColumnDescriptor columnDescriptor,
1996 final long nonceGroup,
1997 final long nonce)
1998 throws IOException {
1999 checkInitialized();
2000 checkCompression(columnDescriptor);
2001 checkEncryption(conf, columnDescriptor);
2002
2003 MasterProcedureUtil.submitProcedure(
2004 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2005 @Override
2006 protected void run() throws IOException {
2007 if (getMaster().getMasterCoprocessorHost().preAddColumn(tableName, columnDescriptor)) {
2008 return;
2009 }
2010
2011
2012 long procId = submitProcedure(new AddColumnFamilyProcedure(
2013 procedureExecutor.getEnvironment(), tableName, columnDescriptor));
2014 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
2015
2016 getMaster().getMasterCoprocessorHost().postAddColumn(tableName, columnDescriptor);
2017 }
2018
2019 @Override
2020 protected String getDescription() {
2021 return "AddColumnFamilyProcedure";
2022 }
2023 });
2024 }
2025
2026 @Override
2027 public void modifyColumn(
2028 final TableName tableName,
2029 final HColumnDescriptor descriptor,
2030 final long nonceGroup,
2031 final long nonce)
2032 throws IOException {
2033 checkInitialized();
2034 checkCompression(descriptor);
2035 checkEncryption(conf, descriptor);
2036
2037 MasterProcedureUtil.submitProcedure(
2038 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2039 @Override
2040 protected void run() throws IOException {
2041 if (getMaster().getMasterCoprocessorHost().preModifyColumn(tableName, descriptor)) {
2042 return;
2043 }
2044
2045 LOG.info(getClientIdAuditPrefix() + " modify " + descriptor);
2046
2047
2048 long procId = submitProcedure(new ModifyColumnFamilyProcedure(
2049 procedureExecutor.getEnvironment(), tableName, descriptor));
2050 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
2051
2052 getMaster().getMasterCoprocessorHost().postModifyColumn(tableName, descriptor);
2053 }
2054
2055 @Override
2056 protected String getDescription() {
2057 return "ModifyColumnFamilyProcedure";
2058 }
2059 });
2060 }
2061
2062 @Override
2063 public void deleteColumn(
2064 final TableName tableName,
2065 final byte[] columnName,
2066 final long nonceGroup,
2067 final long nonce)
2068 throws IOException {
2069 checkInitialized();
2070
2071 MasterProcedureUtil.submitProcedure(
2072 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2073 @Override
2074 protected void run() throws IOException {
2075 if (getMaster().getMasterCoprocessorHost().preDeleteColumn(tableName, columnName)) {
2076 return;
2077 }
2078
2079 LOG.info(getClientIdAuditPrefix() + " delete " + Bytes.toString(columnName));
2080
2081
2082
2083 long procId = submitProcedure(new DeleteColumnFamilyProcedure(
2084 procedureExecutor.getEnvironment(), tableName, columnName));
2085 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
2086
2087 getMaster().getMasterCoprocessorHost().postDeleteColumn(tableName, columnName);
2088 }
2089
2090 @Override
2091 protected String getDescription() {
2092 return "DeleteColumnFamilyProcedure";
2093 }
2094 });
2095 }
2096
2097 @Override
2098 public long enableTable(final TableName tableName, final long nonceGroup, final long nonce)
2099 throws IOException {
2100 checkInitialized();
2101
2102 return MasterProcedureUtil.submitProcedure(
2103 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2104 @Override
2105 protected void run() throws IOException {
2106 getMaster().getMasterCoprocessorHost().preEnableTable(tableName);
2107
2108 LOG.info(getClientIdAuditPrefix() + " enable " + tableName);
2109
2110
2111
2112
2113
2114
2115 final ProcedurePrepareLatch prepareLatch = ProcedurePrepareLatch.createLatch();
2116 submitProcedure(new EnableTableProcedure(procedureExecutor.getEnvironment(),
2117 tableName, false, prepareLatch));
2118 prepareLatch.await();
2119
2120 getMaster().getMasterCoprocessorHost().postEnableTable(tableName);
2121 }
2122
2123 @Override
2124 protected String getDescription() {
2125 return "EnableTableProcedure";
2126 }
2127 });
2128 }
2129
2130 @Override
2131 public long disableTable(final TableName tableName, final long nonceGroup, final long nonce)
2132 throws IOException {
2133 checkInitialized();
2134
2135 return MasterProcedureUtil.submitProcedure(
2136 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2137 @Override
2138 protected void run() throws IOException {
2139 getMaster().getMasterCoprocessorHost().preDisableTable(tableName);
2140
2141 LOG.info(getClientIdAuditPrefix() + " disable " + tableName);
2142
2143
2144
2145
2146
2147
2148 final ProcedurePrepareLatch prepareLatch = ProcedurePrepareLatch.createLatch();
2149 submitProcedure(new DisableTableProcedure(procedureExecutor.getEnvironment(),
2150 tableName, false, prepareLatch));
2151 prepareLatch.await();
2152
2153 getMaster().getMasterCoprocessorHost().postDisableTable(tableName);
2154 }
2155
2156 @Override
2157 protected String getDescription() {
2158 return "DisableTableProcedure";
2159 }
2160 });
2161 }
2162
2163
2164
2165
2166
2167
2168
2169 @VisibleForTesting
2170 Pair<HRegionInfo, ServerName> getTableRegionForRow(
2171 final TableName tableName, final byte [] rowKey)
2172 throws IOException {
2173 final AtomicReference<Pair<HRegionInfo, ServerName>> result =
2174 new AtomicReference<Pair<HRegionInfo, ServerName>>(null);
2175
2176 MetaScannerVisitor visitor =
2177 new MetaScannerVisitorBase() {
2178 @Override
2179 public boolean processRow(Result data) throws IOException {
2180 if (data == null || data.size() <= 0) {
2181 return true;
2182 }
2183 Pair<HRegionInfo, ServerName> pair = HRegionInfo.getHRegionInfoAndServerName(data);
2184 if (pair == null) {
2185 return false;
2186 }
2187 if (!pair.getFirst().getTable().equals(tableName)) {
2188 return false;
2189 }
2190 result.set(pair);
2191 return true;
2192 }
2193 };
2194
2195 MetaScanner.metaScan(clusterConnection, visitor, tableName, rowKey, 1);
2196 return result.get();
2197 }
2198
2199 @Override
2200 public void modifyTable(
2201 final TableName tableName,
2202 final HTableDescriptor descriptor,
2203 final long nonceGroup,
2204 final long nonce)
2205 throws IOException {
2206 checkInitialized();
2207 sanityCheckTableDescriptor(descriptor);
2208
2209 MasterProcedureUtil.submitProcedure(
2210 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2211 @Override
2212 protected void run() throws IOException {
2213 getMaster().getMasterCoprocessorHost().preModifyTable(tableName, descriptor);
2214
2215 LOG.info(getClientIdAuditPrefix() + " modify " + tableName);
2216
2217
2218 long procId = submitProcedure(new ModifyTableProcedure(
2219 procedureExecutor.getEnvironment(), descriptor));
2220 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
2221
2222 getMaster().getMasterCoprocessorHost().postModifyTable(tableName, descriptor);
2223 }
2224
2225 @Override
2226 protected String getDescription() {
2227 return "ModifyTableProcedure";
2228 }
2229 });
2230 }
2231
2232 @Override
2233 public void checkTableModifiable(final TableName tableName)
2234 throws IOException, TableNotFoundException, TableNotDisabledException {
2235 if (isCatalogTable(tableName)) {
2236 throw new IOException("Can't modify catalog tables");
2237 }
2238 if (!MetaTableAccessor.tableExists(getConnection(), tableName)) {
2239 throw new TableNotFoundException(tableName);
2240 }
2241 if (!getAssignmentManager().getTableStateManager().
2242 isTableState(tableName, ZooKeeperProtos.Table.State.DISABLED)) {
2243 throw new TableNotDisabledException(tableName);
2244 }
2245 }
2246
2247
2248
2249
2250 public ClusterStatus getClusterStatus() throws InterruptedIOException {
2251
2252 List<String> backupMasterStrings;
2253 try {
2254 backupMasterStrings = ZKUtil.listChildrenNoWatch(this.zooKeeper,
2255 this.zooKeeper.backupMasterAddressesZNode);
2256 } catch (KeeperException e) {
2257 LOG.warn(this.zooKeeper.prefix("Unable to list backup servers"), e);
2258 backupMasterStrings = null;
2259 }
2260
2261 List<ServerName> backupMasters = null;
2262 if (backupMasterStrings != null && !backupMasterStrings.isEmpty()) {
2263 backupMasters = new ArrayList<ServerName>(backupMasterStrings.size());
2264 for (String s: backupMasterStrings) {
2265 try {
2266 byte [] bytes;
2267 try {
2268 bytes = ZKUtil.getData(this.zooKeeper, ZKUtil.joinZNode(
2269 this.zooKeeper.backupMasterAddressesZNode, s));
2270 } catch (InterruptedException e) {
2271 throw new InterruptedIOException();
2272 }
2273 if (bytes != null) {
2274 ServerName sn;
2275 try {
2276 sn = ServerName.parseFrom(bytes);
2277 } catch (DeserializationException e) {
2278 LOG.warn("Failed parse, skipping registering backup server", e);
2279 continue;
2280 }
2281 backupMasters.add(sn);
2282 }
2283 } catch (KeeperException e) {
2284 LOG.warn(this.zooKeeper.prefix("Unable to get information about " +
2285 "backup servers"), e);
2286 }
2287 }
2288 Collections.sort(backupMasters, new Comparator<ServerName>() {
2289 @Override
2290 public int compare(ServerName s1, ServerName s2) {
2291 return s1.getServerName().compareTo(s2.getServerName());
2292 }});
2293 }
2294
2295 String clusterId = fileSystemManager != null ?
2296 fileSystemManager.getClusterId().toString() : null;
2297 Map<String, RegionState> regionsInTransition = assignmentManager != null ?
2298 assignmentManager.getRegionStates().getRegionsInTransition() : null;
2299 String[] coprocessors = cpHost != null ? getMasterCoprocessors() : null;
2300 boolean balancerOn = loadBalancerTracker != null ?
2301 loadBalancerTracker.isBalancerOn() : false;
2302 Map<ServerName, ServerLoad> onlineServers = null;
2303 Set<ServerName> deadServers = null;
2304 if (serverManager != null) {
2305 deadServers = serverManager.getDeadServers().copyServerNames();
2306 onlineServers = serverManager.getOnlineServers();
2307 }
2308 return new ClusterStatus(VersionInfo.getVersion(), clusterId,
2309 onlineServers, deadServers, serverName, backupMasters,
2310 regionsInTransition, coprocessors, balancerOn);
2311 }
2312
2313
2314
2315
2316
2317
2318
2319
2320 public static String getLoadedCoprocessors() {
2321 return CoprocessorHost.getLoadedCoprocessors().toString();
2322 }
2323
2324
2325
2326
2327 public long getMasterStartTime() {
2328 return startcode;
2329 }
2330
2331
2332
2333
2334 public long getMasterActiveTime() {
2335 return masterActiveTime;
2336 }
2337
2338 public int getNumWALFiles() {
2339 return procedureStore != null ? procedureStore.getActiveLogs().size() : 0;
2340 }
2341
2342 public WALProcedureStore getWalProcedureStore() {
2343 return procedureStore;
2344 }
2345
2346 public int getRegionServerInfoPort(final ServerName sn) {
2347 RegionServerInfo info = this.regionServerTracker.getRegionServerInfo(sn);
2348 if (info == null || info.getInfoPort() == 0) {
2349 return conf.getInt(HConstants.REGIONSERVER_INFO_PORT,
2350 HConstants.DEFAULT_REGIONSERVER_INFOPORT);
2351 }
2352 return info.getInfoPort();
2353 }
2354
2355 public String getRegionServerVersion(final ServerName sn) {
2356 RegionServerInfo info = this.regionServerTracker.getRegionServerInfo(sn);
2357 if (info != null && info.hasVersionInfo()) {
2358 return info.getVersionInfo().getVersion();
2359 }
2360 return "Unknown";
2361 }
2362
2363
2364
2365
2366 public String[] getMasterCoprocessors() {
2367 Set<String> masterCoprocessors = getMasterCoprocessorHost().getCoprocessors();
2368 return masterCoprocessors.toArray(new String[masterCoprocessors.size()]);
2369 }
2370
2371 @Override
2372 public void abort(final String msg, final Throwable t) {
2373 if (isAborted() || isStopped()) {
2374 return;
2375 }
2376 if (cpHost != null) {
2377
2378 LOG.fatal("Master server abort: loaded coprocessors are: " +
2379 getLoadedCoprocessors());
2380 }
2381 if (t != null) LOG.fatal(msg, t);
2382 stop(msg);
2383 }
2384
2385 @Override
2386 public ZooKeeperWatcher getZooKeeper() {
2387 return zooKeeper;
2388 }
2389
2390 @Override
2391 public MasterCoprocessorHost getMasterCoprocessorHost() {
2392 return cpHost;
2393 }
2394
2395 @Override
2396 public MasterQuotaManager getMasterQuotaManager() {
2397 return quotaManager;
2398 }
2399
2400 @Override
2401 public ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
2402 return procedureExecutor;
2403 }
2404
2405 @Override
2406 public ServerName getServerName() {
2407 return this.serverName;
2408 }
2409
2410 @Override
2411 public AssignmentManager getAssignmentManager() {
2412 return this.assignmentManager;
2413 }
2414
2415 public MemoryBoundedLogMessageBuffer getRegionServerFatalLogBuffer() {
2416 return rsFatals;
2417 }
2418
2419 public void shutdown() throws IOException {
2420 if (cpHost != null) {
2421 cpHost.preShutdown();
2422 }
2423
2424 if (this.serverManager != null) {
2425 this.serverManager.shutdownCluster();
2426 }
2427 if (this.clusterStatusTracker != null){
2428 try {
2429 this.clusterStatusTracker.setClusterDown();
2430 } catch (KeeperException e) {
2431 LOG.error("ZooKeeper exception trying to set cluster as down in ZK", e);
2432 }
2433 }
2434 }
2435
2436 public void stopMaster() throws IOException {
2437 if (cpHost != null) {
2438 cpHost.preStopMaster();
2439 }
2440 stop("Stopped by " + Thread.currentThread().getName());
2441 }
2442
2443 void checkServiceStarted() throws ServerNotRunningYetException {
2444 if (!serviceStarted) {
2445 throw new ServerNotRunningYetException("Server is not running yet");
2446 }
2447 }
2448
2449 void checkInitialized() throws PleaseHoldException, ServerNotRunningYetException {
2450 checkServiceStarted();
2451 if (!isInitialized()) {
2452 throw new PleaseHoldException("Master is initializing");
2453 }
2454 }
2455
2456 void checkNamespaceManagerReady() throws IOException {
2457 checkInitialized();
2458 if (tableNamespaceManager == null ||
2459 !tableNamespaceManager.isTableAvailableAndInitialized(true)) {
2460 throw new IOException("Table Namespace Manager not ready yet, try again later");
2461 }
2462 }
2463
2464
2465
2466
2467
2468
2469
2470
2471 public boolean isActiveMaster() {
2472 return isActiveMaster;
2473 }
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484 @Override
2485 public boolean isInitialized() {
2486 return initialized.isReady();
2487 }
2488
2489 @VisibleForTesting
2490 public void setInitialized(boolean isInitialized) {
2491 procedureExecutor.getEnvironment().setEventReady(initialized, isInitialized);
2492 }
2493
2494 public ProcedureEvent getInitializedEvent() {
2495 return initialized;
2496 }
2497
2498
2499
2500
2501
2502
2503 @Override
2504 public boolean isServerCrashProcessingEnabled() {
2505 return serverCrashProcessingEnabled.isReady();
2506 }
2507
2508 @VisibleForTesting
2509 public void setServerCrashProcessingEnabled(final boolean b) {
2510 procedureExecutor.getEnvironment().setEventReady(serverCrashProcessingEnabled, b);
2511 }
2512
2513 public ProcedureEvent getServerCrashProcessingEnabledEvent() {
2514 return serverCrashProcessingEnabled;
2515 }
2516
2517
2518
2519
2520
2521 public boolean isInitializationStartsMetaRegionAssignment() {
2522 return this.initializationBeforeMetaAssignment;
2523 }
2524
2525 public void assignRegion(HRegionInfo hri) {
2526 assignmentManager.assign(hri, true);
2527 }
2528
2529
2530
2531
2532
2533
2534
2535 public double getAverageLoad() {
2536 if (this.assignmentManager == null) {
2537 return 0;
2538 }
2539
2540 RegionStates regionStates = this.assignmentManager.getRegionStates();
2541 if (regionStates == null) {
2542 return 0;
2543 }
2544 return regionStates.getAverageLoad();
2545 }
2546
2547
2548
2549
2550 public long getSplitPlanCount() {
2551 return splitPlanCount;
2552 }
2553
2554
2555
2556
2557 public long getMergePlanCount() {
2558 return mergePlanCount;
2559 }
2560
2561 @Override
2562 public boolean registerService(Service instance) {
2563
2564
2565
2566 Descriptors.ServiceDescriptor serviceDesc = instance.getDescriptorForType();
2567 String serviceName = CoprocessorRpcUtils.getServiceName(serviceDesc);
2568 if (coprocessorServiceHandlers.containsKey(serviceName)) {
2569 LOG.error("Coprocessor service "+serviceName+
2570 " already registered, rejecting request from "+instance
2571 );
2572 return false;
2573 }
2574
2575 coprocessorServiceHandlers.put(serviceName, instance);
2576 if (LOG.isDebugEnabled()) {
2577 LOG.debug("Registered master coprocessor service: service="+serviceName);
2578 }
2579 return true;
2580 }
2581
2582
2583
2584
2585
2586
2587
2588 public static HMaster constructMaster(Class<? extends HMaster> masterClass,
2589 final Configuration conf, final CoordinatedStateManager cp) {
2590 try {
2591 Constructor<? extends HMaster> c =
2592 masterClass.getConstructor(Configuration.class, CoordinatedStateManager.class);
2593 return c.newInstance(conf, cp);
2594 } catch(Exception e) {
2595 Throwable error = e;
2596 if (e instanceof InvocationTargetException &&
2597 ((InvocationTargetException)e).getTargetException() != null) {
2598 error = ((InvocationTargetException)e).getTargetException();
2599 }
2600 throw new RuntimeException("Failed construction of Master: " + masterClass.toString() + ". "
2601 , error);
2602 }
2603 }
2604
2605
2606
2607
2608 public static void main(String [] args) {
2609 VersionInfo.logVersion();
2610 new HMasterCommandLine(HMaster.class).doMain(args);
2611 }
2612
2613 public HFileCleaner getHFileCleaner() {
2614 return this.hfileCleaner;
2615 }
2616
2617
2618
2619
2620 public SnapshotManager getSnapshotManager() {
2621 return this.snapshotManager;
2622 }
2623
2624 @Override
2625 public void createNamespace(
2626 final NamespaceDescriptor descriptor,
2627 final long nonceGroup,
2628 final long nonce) throws IOException {
2629 TableName.isLegalNamespaceName(Bytes.toBytes(descriptor.getName()));
2630 checkNamespaceManagerReady();
2631
2632 createNamespaceSync(descriptor, nonceGroup, nonce, true);
2633 }
2634
2635 @Override
2636 public void createNamespaceSync(
2637 final NamespaceDescriptor descriptor,
2638 final long nonceGroup,
2639 final long nonce,
2640 final boolean executeCoprocessor) throws IOException {
2641 MasterProcedureUtil.submitProcedure(
2642 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2643 @Override
2644 protected void run() throws IOException {
2645 if (executeCoprocessor &&
2646 getMaster().getMasterCoprocessorHost().preCreateNamespace(descriptor)) {
2647 return;
2648 }
2649 LOG.info(getClientIdAuditPrefix() + " creating " + descriptor);
2650
2651
2652 long procId = submitProcedure(new CreateNamespaceProcedure(
2653 procedureExecutor.getEnvironment(), descriptor));
2654 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
2655 if (executeCoprocessor) {
2656 getMaster().getMasterCoprocessorHost().postCreateNamespace(descriptor);
2657 }
2658 }
2659
2660 @Override
2661 protected String getDescription() {
2662 return "CreateNamespaceProcedure";
2663 }
2664 });
2665 }
2666
2667 @Override
2668 public void modifyNamespace(
2669 final NamespaceDescriptor descriptor,
2670 final long nonceGroup,
2671 final long nonce) throws IOException {
2672 TableName.isLegalNamespaceName(Bytes.toBytes(descriptor.getName()));
2673 checkNamespaceManagerReady();
2674
2675 MasterProcedureUtil.submitProcedure(
2676 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2677 @Override
2678 protected void run() throws IOException {
2679 if (getMaster().getMasterCoprocessorHost().preModifyNamespace(descriptor)) {
2680 return;
2681 }
2682 LOG.info(getClientIdAuditPrefix() + " modify " + descriptor);
2683
2684
2685 long procId = submitProcedure(new ModifyNamespaceProcedure(
2686 procedureExecutor.getEnvironment(), descriptor));
2687 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
2688 getMaster().getMasterCoprocessorHost().postModifyNamespace(descriptor);
2689 }
2690
2691 @Override
2692 protected String getDescription() {
2693 return "ModifyNamespace";
2694 }
2695 });
2696 }
2697
2698 @Override
2699 public void deleteNamespace(
2700 final String name,
2701 final long nonceGroup,
2702 final long nonce) throws IOException {
2703 checkNamespaceManagerReady();
2704
2705 MasterProcedureUtil.submitProcedure(
2706 new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
2707 @Override
2708 protected void run() throws IOException {
2709 if (getMaster().getMasterCoprocessorHost().preDeleteNamespace(name)) {
2710 return;
2711 }
2712 LOG.info(getClientIdAuditPrefix() + " delete " + name);
2713
2714
2715 long procId = submitProcedure(new DeleteNamespaceProcedure(
2716 procedureExecutor.getEnvironment(), name));
2717 ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
2718 getMaster().getMasterCoprocessorHost().postDeleteNamespace(name);
2719 }
2720
2721 @Override
2722 protected String getDescription() {
2723 return "DeleteNamespaceProcedure";
2724 }
2725 });
2726 }
2727
2728
2729
2730
2731
2732
2733
2734
2735 protected void ensureNamespaceExists(final String name)
2736 throws IOException, NamespaceNotFoundException {
2737 checkNamespaceManagerReady();
2738 NamespaceDescriptor nsd = tableNamespaceManager.get(name);
2739 if (nsd == null) {
2740 throw new NamespaceNotFoundException(name);
2741 }
2742 }
2743
2744 @Override
2745 public NamespaceDescriptor getNamespaceDescriptor(String name) throws IOException {
2746 checkNamespaceManagerReady();
2747
2748 if (cpHost != null) {
2749 cpHost.preGetNamespaceDescriptor(name);
2750 }
2751
2752 NamespaceDescriptor nsd = tableNamespaceManager.get(name);
2753 if (nsd == null) {
2754 throw new NamespaceNotFoundException(name);
2755 }
2756
2757 if (cpHost != null) {
2758 cpHost.postGetNamespaceDescriptor(nsd);
2759 }
2760
2761 return nsd;
2762 }
2763
2764 @Override
2765 public List<NamespaceDescriptor> listNamespaceDescriptors() throws IOException {
2766 checkNamespaceManagerReady();
2767
2768 final List<NamespaceDescriptor> descriptors = new ArrayList<NamespaceDescriptor>();
2769 boolean bypass = false;
2770 if (cpHost != null) {
2771 bypass = cpHost.preListNamespaceDescriptors(descriptors);
2772 }
2773
2774 if (!bypass) {
2775 descriptors.addAll(tableNamespaceManager.list());
2776
2777 if (cpHost != null) {
2778 cpHost.postListNamespaceDescriptors(descriptors);
2779 }
2780 }
2781 return descriptors;
2782 }
2783
2784 @Override
2785 public boolean abortProcedure(final long procId, final boolean mayInterruptIfRunning)
2786 throws IOException {
2787 if (cpHost != null) {
2788 cpHost.preAbortProcedure(this.procedureExecutor, procId);
2789 }
2790
2791 final boolean result = this.procedureExecutor.abort(procId, mayInterruptIfRunning);
2792
2793 if (cpHost != null) {
2794 cpHost.postAbortProcedure();
2795 }
2796
2797 return result;
2798 }
2799
2800 @Override
2801 public List<ProcedureInfo> listProcedures() throws IOException {
2802 if (cpHost != null) {
2803 cpHost.preListProcedures();
2804 }
2805
2806 final List<ProcedureInfo> procInfoList = this.procedureExecutor.listProcedures();
2807
2808 if (cpHost != null) {
2809 cpHost.postListProcedures(procInfoList);
2810 }
2811
2812 return procInfoList;
2813 }
2814
2815 @Override
2816 public List<HTableDescriptor> listTableDescriptorsByNamespace(String name) throws IOException {
2817 ensureNamespaceExists(name);
2818 return listTableDescriptors(name, null, null, true);
2819 }
2820
2821 @Override
2822 public List<TableName> listTableNamesByNamespace(String name) throws IOException {
2823 ensureNamespaceExists(name);
2824 return listTableNames(name, null, true);
2825 }
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836 public List<HTableDescriptor> listTableDescriptors(final String namespace, final String regex,
2837 final List<TableName> tableNameList, final boolean includeSysTables)
2838 throws IOException {
2839 final List<HTableDescriptor> descriptors = new ArrayList<HTableDescriptor>();
2840
2841 boolean bypass = false;
2842 if (cpHost != null) {
2843 bypass = cpHost.preGetTableDescriptors(tableNameList, descriptors);
2844
2845 bypass |= cpHost.preGetTableDescriptors(tableNameList, descriptors, regex);
2846 }
2847
2848 if (!bypass) {
2849 if (tableNameList == null || tableNameList.size() == 0) {
2850
2851 Collection<HTableDescriptor> htds;
2852 if (namespace != null && namespace.length() > 0) {
2853 htds = tableDescriptors.getByNamespace(namespace).values();
2854 } else {
2855 htds = tableDescriptors.getAll().values();
2856 }
2857
2858 for (HTableDescriptor desc: htds) {
2859 if (includeSysTables || !desc.getTableName().isSystemTable()) {
2860 descriptors.add(desc);
2861 }
2862 }
2863 } else {
2864 for (TableName s: tableNameList) {
2865 HTableDescriptor desc = tableDescriptors.get(s);
2866 if (desc != null) {
2867 descriptors.add(desc);
2868 }
2869 }
2870 }
2871
2872
2873 if (regex != null) {
2874 filterTablesByRegex(descriptors, Pattern.compile(regex));
2875 }
2876
2877 if (cpHost != null) {
2878 cpHost.postGetTableDescriptors(descriptors);
2879
2880 cpHost.postGetTableDescriptors(tableNameList, descriptors, regex);
2881 }
2882 }
2883 return descriptors;
2884 }
2885
2886
2887
2888
2889
2890
2891
2892
2893 public List<TableName> listTableNames(final String namespace, final String regex,
2894 final boolean includeSysTables) throws IOException {
2895 final List<HTableDescriptor> descriptors = new ArrayList<HTableDescriptor>();
2896
2897 boolean bypass = false;
2898 if (cpHost != null) {
2899 bypass = cpHost.preGetTableNames(descriptors, regex);
2900 }
2901
2902 if (!bypass) {
2903
2904 Collection<HTableDescriptor> htds;
2905 if (namespace != null && namespace.length() > 0) {
2906 htds = tableDescriptors.getByNamespace(namespace).values();
2907 } else {
2908 htds = tableDescriptors.getAll().values();
2909 }
2910
2911 for (HTableDescriptor htd: htds) {
2912 if (includeSysTables || !htd.getTableName().isSystemTable()) {
2913 descriptors.add(htd);
2914 }
2915 }
2916
2917
2918 if (regex != null) {
2919 filterTablesByRegex(descriptors, Pattern.compile(regex));
2920 }
2921
2922 if (cpHost != null) {
2923 cpHost.postGetTableNames(descriptors, regex);
2924 }
2925 }
2926
2927 List<TableName> result = new ArrayList<TableName>(descriptors.size());
2928 for (HTableDescriptor htd: descriptors) {
2929 result.add(htd.getTableName());
2930 }
2931 return result;
2932 }
2933
2934
2935
2936
2937
2938
2939
2940 private static void filterTablesByRegex(final Collection<HTableDescriptor> descriptors,
2941 final Pattern pattern) {
2942 final String defaultNS = NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR;
2943 Iterator<HTableDescriptor> itr = descriptors.iterator();
2944 while (itr.hasNext()) {
2945 HTableDescriptor htd = itr.next();
2946 String tableName = htd.getTableName().getNameAsString();
2947 boolean matched = pattern.matcher(tableName).matches();
2948 if (!matched && htd.getTableName().getNamespaceAsString().equals(defaultNS)) {
2949 matched = pattern.matcher(defaultNS + TableName.NAMESPACE_DELIM + tableName).matches();
2950 }
2951 if (!matched) {
2952 itr.remove();
2953 }
2954 }
2955 }
2956
2957 @Override
2958 public long getLastMajorCompactionTimestamp(TableName table) throws IOException {
2959 return getClusterStatus().getLastMajorCompactionTsForTable(table);
2960 }
2961
2962 @Override
2963 public long getLastMajorCompactionTimestampForRegion(byte[] regionName) throws IOException {
2964 return getClusterStatus().getLastMajorCompactionTsForRegion(regionName);
2965 }
2966
2967
2968
2969
2970
2971
2972
2973 public boolean isBalancerOn() {
2974 if (null == loadBalancerTracker) return false;
2975 return loadBalancerTracker.isBalancerOn();
2976 }
2977
2978
2979
2980
2981
2982 public boolean isNormalizerOn() {
2983 if (null == regionNormalizerTracker) {
2984 return false;
2985 }
2986 return regionNormalizerTracker.isNormalizerOn();
2987 }
2988
2989
2990
2991
2992
2993
2994
2995
2996 public boolean isSplitOrMergeEnabled(Admin.MasterSwitchType switchType) {
2997 if (null == splitOrMergeTracker) {
2998 return false;
2999 }
3000 return splitOrMergeTracker.isSplitOrMergeEnabled(switchType);
3001 }
3002
3003
3004
3005
3006
3007
3008 public String getLoadBalancerClassName() {
3009 return conf.get(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, LoadBalancerFactory
3010 .getDefaultLoadBalancerClass().getName());
3011 }
3012
3013
3014
3015
3016 public RegionNormalizerTracker getRegionNormalizerTracker() {
3017 return regionNormalizerTracker;
3018 }
3019
3020 public SplitOrMergeTracker getSplitOrMergeTracker() {
3021 return splitOrMergeTracker;
3022 }
3023 }