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