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 */
018
019package org.apache.hadoop.hbase.master;
020
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.hbase.ChoreService;
023import org.apache.hadoop.hbase.HConstants;
024import org.apache.hadoop.hbase.conf.ConfigurationObserver;
025import org.apache.yetus.audience.InterfaceAudience;
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029/**
030 * Config manager for RegionsRecovery Chore - Dynamically reload config and update chore
031 * accordingly
032 */
033@InterfaceAudience.Private
034public class RegionsRecoveryConfigManager implements ConfigurationObserver {
035
036  private static final Logger LOG = LoggerFactory.getLogger(RegionsRecoveryConfigManager.class);
037
038  private final HMaster hMaster;
039  private int prevMaxStoreFileRefCount;
040  private int prevRegionsRecoveryInterval;
041
042  RegionsRecoveryConfigManager(final HMaster hMaster) {
043    this.hMaster = hMaster;
044    Configuration conf = hMaster.getConfiguration();
045    this.prevMaxStoreFileRefCount = getMaxStoreFileRefCount(conf);
046    this.prevRegionsRecoveryInterval = getRegionsRecoveryChoreInterval(conf);
047  }
048
049  @Override
050  public void onConfigurationChange(Configuration conf) {
051    final int newMaxStoreFileRefCount = getMaxStoreFileRefCount(conf);
052    final int newRegionsRecoveryInterval = getRegionsRecoveryChoreInterval(conf);
053
054    if (prevMaxStoreFileRefCount == newMaxStoreFileRefCount
055        && prevRegionsRecoveryInterval == newRegionsRecoveryInterval) {
056      // no need to re-schedule the chore with updated config
057      // as there is no change in desired configs
058      return;
059    }
060
061    LOG.info("Config Reload for RegionsRecovery Chore. prevMaxStoreFileRefCount: {}," +
062        " newMaxStoreFileRefCount: {}, prevRegionsRecoveryInterval: {}, " +
063        "newRegionsRecoveryInterval: {}", prevMaxStoreFileRefCount, newMaxStoreFileRefCount,
064      prevRegionsRecoveryInterval, newRegionsRecoveryInterval);
065
066    RegionsRecoveryChore regionsRecoveryChore = new RegionsRecoveryChore(this.hMaster,
067      conf, this.hMaster);
068    ChoreService choreService = this.hMaster.getChoreService();
069
070    // Regions Reopen based on very high storeFileRefCount is considered enabled
071    // only if hbase.regions.recovery.store.file.ref.count has value > 0
072
073    synchronized (this) {
074      if (newMaxStoreFileRefCount > 0) {
075        // reschedule the chore
076        // provide mayInterruptIfRunning - false to take care of completion
077        // of in progress task if any
078        choreService.cancelChore(regionsRecoveryChore, false);
079        choreService.scheduleChore(regionsRecoveryChore);
080      } else {
081        choreService.cancelChore(regionsRecoveryChore, false);
082      }
083      this.prevMaxStoreFileRefCount = newMaxStoreFileRefCount;
084      this.prevRegionsRecoveryInterval = newRegionsRecoveryInterval;
085    }
086  }
087
088  private int getMaxStoreFileRefCount(Configuration configuration) {
089    return configuration.getInt(
090      HConstants.STORE_FILE_REF_COUNT_THRESHOLD,
091      HConstants.DEFAULT_STORE_FILE_REF_COUNT_THRESHOLD);
092  }
093
094  private int getRegionsRecoveryChoreInterval(Configuration configuration) {
095    return configuration.getInt(
096      HConstants.REGIONS_RECOVERY_INTERVAL,
097      HConstants.DEFAULT_REGIONS_RECOVERY_INTERVAL);
098  }
099
100}