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