001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase; 019 020import static org.apache.hadoop.hbase.ChoreService.CHORE_SERVICE_INITIAL_POOL_SIZE; 021import static org.apache.hadoop.hbase.ChoreService.DEFAULT_CHORE_SERVICE_INITIAL_POOL_SIZE; 022import static org.apache.hadoop.hbase.HConstants.DEFAULT_HBASE_SPLIT_COORDINATED_BY_ZK; 023import static org.apache.hadoop.hbase.HConstants.HBASE_SPLIT_WAL_COORDINATED_BY_ZK; 024 025import com.google.errorprone.annotations.RestrictedApi; 026import io.opentelemetry.api.trace.Span; 027import io.opentelemetry.api.trace.StatusCode; 028import io.opentelemetry.context.Scope; 029import java.io.IOException; 030import java.lang.management.MemoryType; 031import java.net.BindException; 032import java.net.InetAddress; 033import java.net.InetSocketAddress; 034import java.util.concurrent.atomic.AtomicBoolean; 035import java.util.concurrent.atomic.AtomicReference; 036import javax.servlet.http.HttpServlet; 037import org.apache.commons.lang3.StringUtils; 038import org.apache.commons.lang3.SystemUtils; 039import org.apache.hadoop.conf.Configuration; 040import org.apache.hadoop.fs.FileSystem; 041import org.apache.hadoop.fs.Path; 042import org.apache.hadoop.hbase.client.AsyncClusterConnection; 043import org.apache.hadoop.hbase.client.ClusterConnectionFactory; 044import org.apache.hadoop.hbase.client.Connection; 045import org.apache.hadoop.hbase.client.ConnectionFactory; 046import org.apache.hadoop.hbase.client.ConnectionRegistryEndpoint; 047import org.apache.hadoop.hbase.conf.ConfigurationManager; 048import org.apache.hadoop.hbase.conf.ConfigurationObserver; 049import org.apache.hadoop.hbase.coordination.ZkCoordinatedStateManager; 050import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 051import org.apache.hadoop.hbase.executor.ExecutorService; 052import org.apache.hadoop.hbase.fs.HFileSystem; 053import org.apache.hadoop.hbase.http.InfoServer; 054import org.apache.hadoop.hbase.io.util.MemorySizeUtil; 055import org.apache.hadoop.hbase.ipc.RpcServerInterface; 056import org.apache.hadoop.hbase.keymeta.KeyManagementService; 057import org.apache.hadoop.hbase.keymeta.KeymetaAdmin; 058import org.apache.hadoop.hbase.keymeta.ManagedKeyDataCache; 059import org.apache.hadoop.hbase.keymeta.SystemKeyCache; 060import org.apache.hadoop.hbase.master.HMaster; 061import org.apache.hadoop.hbase.master.MasterCoprocessorHost; 062import org.apache.hadoop.hbase.namequeues.NamedQueueRecorder; 063import org.apache.hadoop.hbase.regionserver.ChunkCreator; 064import org.apache.hadoop.hbase.regionserver.HeapMemoryManager; 065import org.apache.hadoop.hbase.regionserver.MemStoreLAB; 066import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost; 067import org.apache.hadoop.hbase.regionserver.ShutdownHook; 068import org.apache.hadoop.hbase.security.Superusers; 069import org.apache.hadoop.hbase.security.User; 070import org.apache.hadoop.hbase.security.UserProvider; 071import org.apache.hadoop.hbase.security.access.AccessChecker; 072import org.apache.hadoop.hbase.security.access.ZKPermissionWatcher; 073import org.apache.hadoop.hbase.trace.TraceUtil; 074import org.apache.hadoop.hbase.unsafe.HBasePlatformDependent; 075import org.apache.hadoop.hbase.util.Addressing; 076import org.apache.hadoop.hbase.util.CommonFSUtils; 077import org.apache.hadoop.hbase.util.ConfigurationUtil; 078import org.apache.hadoop.hbase.util.DNS; 079import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 080import org.apache.hadoop.hbase.util.FSTableDescriptors; 081import org.apache.hadoop.hbase.util.NettyEventLoopGroupConfig; 082import org.apache.hadoop.hbase.util.Pair; 083import org.apache.hadoop.hbase.util.Sleeper; 084import org.apache.hadoop.hbase.zookeeper.ClusterStatusTracker; 085import org.apache.hadoop.hbase.zookeeper.ZKAuthentication; 086import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 087import org.apache.yetus.audience.InterfaceAudience; 088import org.slf4j.Logger; 089import org.slf4j.LoggerFactory; 090 091/** 092 * Base class for hbase services, such as master or region server. 093 */ 094@InterfaceAudience.Private 095public abstract class HBaseServerBase<R extends HBaseRpcServicesBase<?>> extends Thread 096 implements Server, ConfigurationObserver, ConnectionRegistryEndpoint, KeyManagementService { 097 098 private static final Logger LOG = LoggerFactory.getLogger(HBaseServerBase.class); 099 100 protected final Configuration conf; 101 102 // Go down hard. Used if file system becomes unavailable and also in 103 // debugging and unit tests. 104 protected final AtomicBoolean abortRequested = new AtomicBoolean(false); 105 106 // Set when a report to the master comes back with a message asking us to 107 // shut down. Also set by call to stop when debugging or running unit tests 108 // of HRegionServer in isolation. 109 protected volatile boolean stopped = false; 110 111 // Flag set when a read-only to read-write transition is blocked because another active cluster 112 // exists 113 protected final AtomicBoolean readOnlyTransitionBlocked; 114 115 // Tracks the active cluster in a read-replica setup when a ReadOnlyTransitionException occurs 116 private final AtomicReference<String> blockingActiveClusterId; 117 118 // Only for testing 119 private boolean isShutdownHookInstalled = false; 120 121 /** 122 * This server's startcode. 123 */ 124 protected final long startcode; 125 126 protected final UserProvider userProvider; 127 128 // zookeeper connection and watcher 129 protected final ZKWatcher zooKeeper; 130 131 /** 132 * The server name the Master sees us as. Its made from the hostname the master passes us, port, 133 * and server startcode. Gets set after registration against Master. 134 */ 135 protected ServerName serverName; 136 137 protected final R rpcServices; 138 139 /** 140 * hostname specified by hostname config 141 */ 142 protected final String useThisHostnameInstead; 143 144 /** 145 * Provide online slow log responses from ringbuffer 146 */ 147 protected final NamedQueueRecorder namedQueueRecorder; 148 149 /** 150 * Configuration manager is used to register/deregister and notify the configuration observers 151 * when the regionserver is notified that there was a change in the on disk configs. 152 */ 153 protected final ConfigurationManager configurationManager; 154 155 /** 156 * ChoreService used to schedule tasks that we want to run periodically 157 */ 158 protected final ChoreService choreService; 159 160 // Instance of the hbase executor executorService. 161 protected final ExecutorService executorService; 162 163 // Cluster Status Tracker 164 protected final ClusterStatusTracker clusterStatusTracker; 165 166 protected final CoordinatedStateManager csm; 167 168 // Info server. Default access so can be used by unit tests. REGIONSERVER 169 // is name of the webapp and the attribute name used stuffing this instance 170 // into web context. 171 protected InfoServer infoServer; 172 173 protected HFileSystem dataFs; 174 175 protected HFileSystem walFs; 176 177 protected Path dataRootDir; 178 179 protected Path walRootDir; 180 181 protected final int msgInterval; 182 183 // A sleeper that sleeps for msgInterval. 184 protected final Sleeper sleeper; 185 186 /** 187 * Go here to get table descriptors. 188 */ 189 protected TableDescriptors tableDescriptors; 190 191 /** 192 * The asynchronous cluster connection to be shared by services. 193 */ 194 protected AsyncClusterConnection asyncClusterConnection; 195 196 /** 197 * Cache for the meta region replica's locations. Also tracks their changes to avoid stale cache 198 * entries. Used for serving ClientMetaService. 199 */ 200 protected final MetaRegionLocationCache metaRegionLocationCache; 201 202 protected final NettyEventLoopGroupConfig eventLoopGroupConfig; 203 204 private void setupSignalHandlers() { 205 if (!SystemUtils.IS_OS_WINDOWS) { 206 HBasePlatformDependent.handle("HUP", (number, name) -> { 207 try { 208 updateConfiguration(); 209 } catch (IOException e) { 210 LOG.error("Problem while reloading configuration", e); 211 } 212 }); 213 } 214 } 215 216 /** 217 * Setup our cluster connection if not already initialized. 218 */ 219 protected final synchronized void setupClusterConnection() throws IOException { 220 if (asyncClusterConnection == null) { 221 InetSocketAddress localAddress = 222 new InetSocketAddress(rpcServices.getSocketAddress().getAddress(), 0); 223 User user = userProvider.getCurrent(); 224 asyncClusterConnection = 225 ClusterConnectionFactory.createAsyncClusterConnection(this, conf, localAddress, user); 226 } 227 } 228 229 protected final void initializeFileSystem() throws IOException { 230 // Get fs instance used by this RS. Do we use checksum verification in the hbase? If hbase 231 // checksum verification enabled, then automatically switch off hdfs checksum verification. 232 boolean useHBaseChecksum = conf.getBoolean(HConstants.HBASE_CHECKSUM_VERIFICATION, true); 233 String walDirUri = CommonFSUtils.getDirUri(this.conf, 234 new Path(conf.get(CommonFSUtils.HBASE_WAL_DIR, conf.get(HConstants.HBASE_DIR)))); 235 // set WAL's uri 236 if (walDirUri != null) { 237 CommonFSUtils.setFsDefault(this.conf, walDirUri); 238 } 239 // init the WALFs 240 this.walFs = new HFileSystem(this.conf, useHBaseChecksum); 241 this.walRootDir = CommonFSUtils.getWALRootDir(this.conf); 242 // Set 'fs.defaultFS' to match the filesystem on hbase.rootdir else 243 // underlying hadoop hdfs accessors will be going against wrong filesystem 244 // (unless all is set to defaults). 245 String rootDirUri = 246 CommonFSUtils.getDirUri(this.conf, new Path(conf.get(HConstants.HBASE_DIR))); 247 if (rootDirUri != null) { 248 CommonFSUtils.setFsDefault(this.conf, rootDirUri); 249 } 250 // init the filesystem 251 this.dataFs = new HFileSystem(this.conf, useHBaseChecksum); 252 this.dataRootDir = CommonFSUtils.getRootDir(this.conf); 253 int tableDescriptorParallelLoadThreads = 254 conf.getInt("hbase.tabledescriptor.parallel.load.threads", 0); 255 this.tableDescriptors = new FSTableDescriptors(this.dataFs, this.dataRootDir, 256 !canUpdateTableDescriptor(), cacheTableDescriptor(), tableDescriptorParallelLoadThreads); 257 } 258 259 public HBaseServerBase(Configuration conf, String name) throws IOException { 260 super(name); // thread name 261 this.readOnlyTransitionBlocked = new AtomicBoolean(false); 262 this.blockingActiveClusterId = new AtomicReference<>(null); 263 final Span span = TraceUtil.createSpan("HBaseServerBase.cxtor"); 264 try (Scope ignored = span.makeCurrent()) { 265 this.conf = conf; 266 this.eventLoopGroupConfig = 267 NettyEventLoopGroupConfig.setup(conf, getClass().getSimpleName() + "-EventLoopGroup"); 268 this.startcode = EnvironmentEdgeManager.currentTime(); 269 this.userProvider = UserProvider.instantiate(conf); 270 this.msgInterval = conf.getInt("hbase.regionserver.msginterval", 3 * 1000); 271 this.sleeper = new Sleeper(this.msgInterval, this); 272 this.namedQueueRecorder = createNamedQueueRecord(); 273 useThisHostnameInstead = getUseThisHostnameInstead(conf); 274 // Resolve the hostname up-front and log in before creating the RpcServer. The RpcServer 275 // constructor reads UserGroupInformation.getCurrentUser() (HBASE-28321); if the server 276 // has not logged in yet, UGI bootstraps from the ticket cache and spawns a TGT renewer 277 // for whichever principal happens to be there. 278 String hostName = resolveHostName(conf, useThisHostnameInstead); 279 // login the zookeeper client principal (if using security) 280 ZKAuthentication.loginClient(this.conf, HConstants.ZK_CLIENT_KEYTAB_FILE, 281 HConstants.ZK_CLIENT_KERBEROS_PRINCIPAL, hostName); 282 // login the server principal (if using secure Hadoop) 283 login(userProvider, hostName); 284 this.rpcServices = createRpcServices(); 285 InetSocketAddress addr = rpcServices.getSocketAddress(); 286 serverName = ServerName.valueOf(hostName, addr.getPort(), this.startcode); 287 // init superusers and add the server principal (if using security) 288 // or process owner as default super user. 289 Superusers.initialize(conf); 290 zooKeeper = 291 new ZKWatcher(conf, getProcessName() + ":" + addr.getPort(), this, canCreateBaseZNode()); 292 293 this.configurationManager = new ConfigurationManager(); 294 setupSignalHandlers(); 295 296 initializeFileSystem(); 297 298 int choreServiceInitialSize = 299 conf.getInt(CHORE_SERVICE_INITIAL_POOL_SIZE, DEFAULT_CHORE_SERVICE_INITIAL_POOL_SIZE); 300 this.choreService = new ChoreService(getName(), choreServiceInitialSize, true); 301 this.executorService = new ExecutorService(getName()); 302 303 this.metaRegionLocationCache = new MetaRegionLocationCache(zooKeeper); 304 305 if (clusterMode()) { 306 if ( 307 conf.getBoolean(HBASE_SPLIT_WAL_COORDINATED_BY_ZK, DEFAULT_HBASE_SPLIT_COORDINATED_BY_ZK) 308 ) { 309 csm = new ZkCoordinatedStateManager(this); 310 } else { 311 csm = null; 312 } 313 clusterStatusTracker = new ClusterStatusTracker(zooKeeper, this); 314 clusterStatusTracker.start(); 315 } else { 316 csm = null; 317 clusterStatusTracker = null; 318 } 319 putUpWebUI(); 320 span.setStatus(StatusCode.OK); 321 } catch (Throwable t) { 322 TraceUtil.setError(span, t); 323 throw t; 324 } finally { 325 span.end(); 326 } 327 } 328 329 /** 330 * Puts up the webui. 331 */ 332 private void putUpWebUI() throws IOException { 333 int port = 334 this.conf.getInt(HConstants.REGIONSERVER_INFO_PORT, HConstants.DEFAULT_REGIONSERVER_INFOPORT); 335 String addr = this.conf.get("hbase.regionserver.info.bindAddress", "0.0.0.0"); 336 337 boolean isMaster = false; 338 if (this instanceof HMaster) { 339 port = conf.getInt(HConstants.MASTER_INFO_PORT, HConstants.DEFAULT_MASTER_INFOPORT); 340 addr = this.conf.get("hbase.master.info.bindAddress", "0.0.0.0"); 341 isMaster = true; 342 } 343 // -1 is for disabling info server 344 if (port < 0) { 345 return; 346 } 347 348 if (!Addressing.isLocalAddress(InetAddress.getByName(addr))) { 349 String msg = "Failed to start http info server. Address " + addr 350 + " does not belong to this host. Correct configuration parameter: " 351 + (isMaster ? "hbase.master.info.bindAddress" : "hbase.regionserver.info.bindAddress"); 352 LOG.error(msg); 353 throw new IOException(msg); 354 } 355 // check if auto port bind enabled 356 boolean auto = this.conf.getBoolean(HConstants.REGIONSERVER_INFO_PORT_AUTO, false); 357 while (true) { 358 try { 359 this.infoServer = new InfoServer(getProcessName(), addr, port, false, this.conf); 360 infoServer.addPrivilegedServlet("dump", "/dump", getDumpServlet()); 361 configureInfoServer(infoServer); 362 this.infoServer.start(); 363 break; 364 } catch (BindException e) { 365 if (!auto) { 366 // auto bind disabled throw BindException 367 LOG.error("Failed binding http info server to port: " + port); 368 throw e; 369 } 370 // auto bind enabled, try to use another port 371 LOG.info("Failed binding http info server to port: " + port); 372 port++; 373 LOG.info("Retry starting http info server with port: " + port); 374 } 375 } 376 port = this.infoServer.getPort(); 377 conf.setInt(HConstants.REGIONSERVER_INFO_PORT, port); 378 int masterInfoPort = 379 conf.getInt(HConstants.MASTER_INFO_PORT, HConstants.DEFAULT_MASTER_INFOPORT); 380 conf.setInt("hbase.master.info.port.orig", masterInfoPort); 381 conf.setInt(HConstants.MASTER_INFO_PORT, port); 382 } 383 384 /** 385 * Sets the abort state if not already set. 386 * @return True if abortRequested set to True successfully, false if an abort is already in 387 * progress. 388 */ 389 protected final boolean setAbortRequested() { 390 return abortRequested.compareAndSet(false, true); 391 } 392 393 @Override 394 public boolean isStopped() { 395 return stopped; 396 } 397 398 @Override 399 public boolean isAborted() { 400 return abortRequested.get(); 401 } 402 403 @Override 404 public Configuration getConfiguration() { 405 return conf; 406 } 407 408 @Override 409 public AsyncClusterConnection getAsyncClusterConnection() { 410 return asyncClusterConnection; 411 } 412 413 @Override 414 public ZKWatcher getZooKeeper() { 415 return zooKeeper; 416 } 417 418 @Override 419 public KeymetaAdmin getKeymetaAdmin() { 420 return null; 421 } 422 423 @Override 424 public ManagedKeyDataCache getManagedKeyDataCache() { 425 return null; 426 } 427 428 @Override 429 public SystemKeyCache getSystemKeyCache() { 430 return null; 431 } 432 433 protected final void shutdownChore(ScheduledChore chore) { 434 if (chore != null) { 435 chore.shutdown(); 436 } 437 } 438 439 protected final void initializeMemStoreChunkCreator(HeapMemoryManager hMemManager) { 440 if (MemStoreLAB.isEnabled(conf)) { 441 // MSLAB is enabled. So initialize MemStoreChunkPool 442 // By this time, the MemstoreFlusher is already initialized. We can get the global limits from 443 // it. 444 Pair<Long, MemoryType> pair = MemorySizeUtil.getGlobalMemStoreSize(conf); 445 long globalMemStoreSize = pair.getFirst(); 446 boolean offheap = pair.getSecond() == MemoryType.NON_HEAP; 447 // When off heap memstore in use, take full area for chunk pool. 448 float poolSizePercentage = offheap 449 ? 1.0F 450 : conf.getFloat(MemStoreLAB.CHUNK_POOL_MAXSIZE_KEY, MemStoreLAB.POOL_MAX_SIZE_DEFAULT); 451 float initialCountPercentage = conf.getFloat(MemStoreLAB.CHUNK_POOL_INITIALSIZE_KEY, 452 MemStoreLAB.POOL_INITIAL_SIZE_DEFAULT); 453 int chunkSize = conf.getInt(MemStoreLAB.CHUNK_SIZE_KEY, MemStoreLAB.CHUNK_SIZE_DEFAULT); 454 float indexChunkSizePercent = conf.getFloat(MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_KEY, 455 MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT); 456 // init the chunkCreator 457 ChunkCreator.initialize(chunkSize, offheap, globalMemStoreSize, poolSizePercentage, 458 initialCountPercentage, hMemManager, indexChunkSizePercent); 459 } 460 } 461 462 protected abstract void stopChores(); 463 464 protected final void stopChoreService() { 465 // clean up the scheduled chores 466 if (choreService != null) { 467 LOG.info("Shutdown chores and chore service"); 468 stopChores(); 469 // cancel the remaining scheduled chores (in case we missed out any) 470 // TODO: cancel will not cleanup the chores, so we need make sure we do not miss any 471 choreService.shutdown(); 472 } 473 } 474 475 protected final void stopExecutorService() { 476 if (executorService != null) { 477 LOG.info("Shutdown executor service"); 478 executorService.shutdown(); 479 } 480 } 481 482 protected final void closeClusterConnection() { 483 if (asyncClusterConnection != null) { 484 LOG.info("Close async cluster connection"); 485 try { 486 this.asyncClusterConnection.close(); 487 } catch (IOException e) { 488 // Although the {@link Closeable} interface throws an {@link 489 // IOException}, in reality, the implementation would never do that. 490 LOG.warn("Attempt to close server's AsyncClusterConnection failed.", e); 491 } 492 } 493 } 494 495 protected final void stopInfoServer() { 496 if (this.infoServer != null) { 497 LOG.info("Stop info server"); 498 try { 499 this.infoServer.stop(); 500 } catch (Exception e) { 501 LOG.error("Failed to stop infoServer", e); 502 } 503 } 504 } 505 506 protected final void closeZooKeeper() { 507 if (this.zooKeeper != null) { 508 LOG.info("Close zookeeper"); 509 this.zooKeeper.close(); 510 } 511 } 512 513 protected final void closeTableDescriptors() { 514 if (this.tableDescriptors != null) { 515 LOG.info("Close table descriptors"); 516 try { 517 this.tableDescriptors.close(); 518 } catch (IOException e) { 519 LOG.debug("Failed to close table descriptors gracefully", e); 520 } 521 } 522 } 523 524 /** 525 * In order to register ShutdownHook, this method is called when HMaster and HRegionServer are 526 * started. For details, please refer to HBASE-26951 527 */ 528 protected final void installShutdownHook() { 529 ShutdownHook.install(conf, dataFs, this, Thread.currentThread()); 530 isShutdownHookInstalled = true; 531 } 532 533 @RestrictedApi(explanation = "Should only be called in tests", link = "", 534 allowedOnPath = ".*/src/test/.*") 535 public boolean isShutdownHookInstalled() { 536 return isShutdownHookInstalled; 537 } 538 539 @Override 540 public ServerName getServerName() { 541 return serverName; 542 } 543 544 @Override 545 public ChoreService getChoreService() { 546 return choreService; 547 } 548 549 /** Returns Return table descriptors implementation. */ 550 public TableDescriptors getTableDescriptors() { 551 return this.tableDescriptors; 552 } 553 554 public ExecutorService getExecutorService() { 555 return executorService; 556 } 557 558 public AccessChecker getAccessChecker() { 559 return rpcServices.getAccessChecker(); 560 } 561 562 public ZKPermissionWatcher getZKPermissionWatcher() { 563 return rpcServices.getZkPermissionWatcher(); 564 } 565 566 @Override 567 public CoordinatedStateManager getCoordinatedStateManager() { 568 return csm; 569 } 570 571 @Override 572 public Connection createConnection(Configuration conf) throws IOException { 573 User user = UserProvider.instantiate(conf).getCurrent(); 574 return ConnectionFactory.createConnection(conf, null, user); 575 } 576 577 /** Returns Return the rootDir. */ 578 public Path getDataRootDir() { 579 return dataRootDir; 580 } 581 582 @Override 583 public FileSystem getFileSystem() { 584 return dataFs; 585 } 586 587 /** Returns Return the walRootDir. */ 588 public Path getWALRootDir() { 589 return walRootDir; 590 } 591 592 /** Returns Return the walFs. */ 593 public FileSystem getWALFileSystem() { 594 return walFs; 595 } 596 597 /** Returns True if the cluster is up. */ 598 public boolean isClusterUp() { 599 return !clusterMode() || this.clusterStatusTracker.isClusterUp(); 600 } 601 602 /** Returns time stamp in millis of when this server was started */ 603 public long getStartcode() { 604 return this.startcode; 605 } 606 607 public InfoServer getInfoServer() { 608 return infoServer; 609 } 610 611 public int getMsgInterval() { 612 return msgInterval; 613 } 614 615 /** 616 * get NamedQueue Provider to add different logs to ringbuffer 617 */ 618 public NamedQueueRecorder getNamedQueueRecorder() { 619 return this.namedQueueRecorder; 620 } 621 622 public RpcServerInterface getRpcServer() { 623 return rpcServices.getRpcServer(); 624 } 625 626 public NettyEventLoopGroupConfig getEventLoopGroupConfig() { 627 return eventLoopGroupConfig; 628 } 629 630 public R getRpcServices() { 631 return rpcServices; 632 } 633 634 @RestrictedApi(explanation = "Should only be called in tests", link = "", 635 allowedOnPath = ".*/src/test/.*") 636 public MetaRegionLocationCache getMetaRegionLocationCache() { 637 return this.metaRegionLocationCache; 638 } 639 640 @RestrictedApi(explanation = "Should only be called in tests", link = "", 641 allowedOnPath = ".*/src/test/.*") 642 public ConfigurationManager getConfigurationManager() { 643 return configurationManager; 644 } 645 646 /** 647 * Reload the configuration from disk. 648 */ 649 public void updateConfiguration() throws IOException { 650 LOG.info("Reloading the configuration from disk."); 651 // Reload the configuration from disk. 652 preUpdateConfiguration(); 653 this.readOnlyTransitionBlocked.set(false); 654 this.blockingActiveClusterId.set(null); 655 conf.reloadConfiguration(); 656 configurationManager.notifyAllObservers(conf); 657 this.checkForBlockedReadOnlyTransition(); 658 postUpdateConfiguration(); 659 } 660 661 protected Configuration blockReadOnlyTransition(Configuration updatedConf, 662 String activeClusterId) { 663 this.blockingActiveClusterId.set(activeClusterId); 664 LOG.error( 665 "Cannot disable read-only mode. The {} file contains a different cluster ID ({}), which means " 666 + "that cluster is already the active cluster. Reverting {} to true", 667 HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME, this.blockingActiveClusterId.get(), 668 HConstants.HBASE_GLOBAL_READONLY_ENABLED_KEY); 669 this.readOnlyTransitionBlocked.set(true); 670 return ConfigurationUtil.copyWithReadOnlyModeEnabled(updatedConf); 671 } 672 673 protected void checkForBlockedReadOnlyTransition() throws ReadOnlyTransitionException { 674 if (this.readOnlyTransitionBlocked.get()) { 675 throw new ReadOnlyTransitionException( 676 "Cannot disable read-only mode because another active cluster already exists on this " 677 + "storage location. The read-only coprocessors have not been removed.", 678 this.blockingActiveClusterId.get()); 679 } 680 } 681 682 @Override 683 public KeyManagementService getKeyManagementService() { 684 return this; 685 } 686 687 private void preUpdateConfiguration() throws IOException { 688 CoprocessorHost<?, ?> coprocessorHost = getCoprocessorHost(); 689 if (coprocessorHost instanceof RegionServerCoprocessorHost) { 690 ((RegionServerCoprocessorHost) coprocessorHost).preUpdateConfiguration(conf); 691 } else if (coprocessorHost instanceof MasterCoprocessorHost) { 692 ((MasterCoprocessorHost) coprocessorHost).preUpdateConfiguration(conf); 693 } 694 } 695 696 private void postUpdateConfiguration() throws IOException { 697 CoprocessorHost<?, ?> coprocessorHost = getCoprocessorHost(); 698 if (coprocessorHost instanceof RegionServerCoprocessorHost) { 699 ((RegionServerCoprocessorHost) coprocessorHost).postUpdateConfiguration(conf); 700 } else if (coprocessorHost instanceof MasterCoprocessorHost) { 701 ((MasterCoprocessorHost) coprocessorHost).postUpdateConfiguration(conf); 702 } 703 } 704 705 @Override 706 public String toString() { 707 return getServerName().toString(); 708 } 709 710 protected abstract CoprocessorHost<?, ?> getCoprocessorHost(); 711 712 protected abstract boolean canCreateBaseZNode(); 713 714 protected abstract String getProcessName(); 715 716 protected abstract R createRpcServices() throws IOException; 717 718 protected abstract String getUseThisHostnameInstead(Configuration conf) throws IOException; 719 720 protected abstract void login(UserProvider user, String host) throws IOException; 721 722 protected abstract DNS.ServerType getDNSServerType(); 723 724 private String resolveHostName(Configuration conf, String useThisHostnameInstead) 725 throws IOException { 726 if (!StringUtils.isBlank(useThisHostnameInstead)) { 727 return useThisHostnameInstead; 728 } 729 // if use-ip is enabled, we will use ip to expose Master/RS service for client, 730 // see HBASE-27304 for details. 731 boolean useIp = conf.getBoolean(HConstants.HBASE_SERVER_USEIP_ENABLED_KEY, 732 HConstants.HBASE_SERVER_USEIP_ENABLED_DEFAULT); 733 InetAddress addr = InetAddress.getByName(DNS.getHostname(conf, getDNSServerType())); 734 return useIp ? addr.getHostAddress() : addr.getHostName(); 735 } 736 737 protected abstract NamedQueueRecorder createNamedQueueRecord(); 738 739 protected abstract void configureInfoServer(InfoServer infoServer); 740 741 protected abstract Class<? extends HttpServlet> getDumpServlet(); 742 743 protected abstract boolean canUpdateTableDescriptor(); 744 745 protected abstract boolean cacheTableDescriptor(); 746 747 protected abstract boolean clusterMode(); 748}