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