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