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