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.util;
019
020import java.io.IOException;
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.fs.FileSystem;
023import org.apache.hadoop.fs.Path;
024import org.apache.hadoop.hbase.TableName;
025import org.apache.hadoop.hbase.client.Admin;
026import org.apache.hadoop.hbase.client.RegionInfo;
027import org.apache.hadoop.hbase.client.RegionReplicaUtil;
028import org.apache.hadoop.hbase.io.HFileLink;
029import org.apache.hadoop.hbase.io.Reference;
030import org.apache.hadoop.hbase.regionserver.HRegion;
031import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
032import org.apache.yetus.audience.InterfaceAudience;
033
034/**
035 * Similar to {@link RegionReplicaUtil} but for the server side
036 */
037@InterfaceAudience.Private
038public class ServerRegionReplicaUtil extends RegionReplicaUtil {
039
040  /**
041   * Whether asynchronous WAL replication to the secondary region replicas is enabled or not. If
042   * this is enabled, a replication peer named "region_replica_replication" will be created which
043   * will tail the logs and replicate the mutatations to region replicas for tables that have region
044   * replication > 1. If this is enabled once, disabling this replication also requires disabling
045   * the replication peer using shell or {@link Admin} java class. Replication to secondary region
046   * replicas works over standard inter-cluster replication.ยท
047   */
048  public static final String REGION_REPLICA_REPLICATION_CONF_KEY =
049    "hbase.region.replica.replication.enabled";
050  private static final boolean DEFAULT_REGION_REPLICA_REPLICATION = false;
051
052  /**
053   * @deprecated Since 3.0.0, leave here only for implementing compatibility code.
054   */
055  @Deprecated
056  public static final String REGION_REPLICA_REPLICATION_PEER = "region_replica_replication";
057
058  /**
059   * Same as for {@link #REGION_REPLICA_REPLICATION_CONF_KEY} but for catalog replication.
060   */
061  public static final String REGION_REPLICA_REPLICATION_CATALOG_CONF_KEY =
062    "hbase.region.replica.replication.catalog.enabled";
063  private static final boolean DEFAULT_REGION_REPLICA_REPLICATION_CATALOG = false;
064
065  /**
066   * Enables or disables refreshing store files of secondary region replicas when the memory is
067   * above the global memstore lower limit. Refreshing the store files means that we will do a file
068   * list of the primary regions store files, and pick up new files. Also depending on the store
069   * files, we can drop some memstore contents which will free up memory.
070   */
071  public static final String REGION_REPLICA_STORE_FILE_REFRESH =
072    "hbase.region.replica.storefile.refresh";
073  private static final boolean DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH = true;
074
075  /**
076   * The multiplier to use when we want to refresh a secondary region instead of flushing a primary
077   * region. Default value assumes that for doing the file refresh, the biggest secondary should be
078   * 4 times bigger than the biggest primary.
079   */
080  public static final String REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER =
081    "hbase.region.replica.storefile.refresh.memstore.multiplier";
082  private static final double DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER = 4;
083
084  /**
085   * Returns the regionInfo object to use for interacting with the file system.
086   * @return An RegionInfo object to interact with the filesystem
087   */
088  public static RegionInfo getRegionInfoForFs(RegionInfo regionInfo) {
089    if (regionInfo == null) {
090      return null;
091    }
092    return RegionReplicaUtil.getRegionInfoForDefaultReplica(regionInfo);
093  }
094
095  /**
096   * Returns whether this region replica can accept writes.
097   * @param region the HRegion object
098   * @return whether the replica is read only
099   */
100  public static boolean isReadOnly(HRegion region) {
101    return region.getTableDescriptor().isReadOnly() || !isDefaultReplica(region.getRegionInfo());
102  }
103
104  /**
105   * Returns whether to replay the recovered edits to flush the results. Currently secondary region
106   * replicas do not replay the edits, since it would cause flushes which might affect the primary
107   * region. Primary regions even opened in read only mode should replay the edits.
108   * @param region the HRegion object
109   * @return whether recovered edits should be replayed.
110   */
111  public static boolean shouldReplayRecoveredEdits(HRegion region) {
112    return isDefaultReplica(region.getRegionInfo());
113  }
114
115  /**
116   * Returns a StoreFileInfo from the given FileStatus. Secondary replicas refer to the files of the
117   * primary region, so an HFileLink is used to construct the StoreFileInfo. This way ensures that
118   * the secondary will be able to continue reading the store files even if they are moved to
119   * archive after compaction
120   */
121  public static StoreFileInfo getStoreFileInfo(Configuration conf, FileSystem fs,
122    RegionInfo regionInfo, RegionInfo regionInfoForFs, String familyName, Path path)
123    throws IOException {
124
125    // if this is a primary region, just return the StoreFileInfo constructed from path
126    if (RegionInfo.COMPARATOR.compare(regionInfo, regionInfoForFs) == 0) {
127      return new StoreFileInfo(conf, fs, path, true);
128    }
129
130    // else create a store file link. The link file does not exists on filesystem though.
131    if (HFileLink.isHFileLink(path) || StoreFileInfo.isHFile(path)) {
132      HFileLink link = HFileLink.build(conf, regionInfoForFs.getTable(),
133        regionInfoForFs.getEncodedName(), familyName, path.getName());
134      return new StoreFileInfo(conf, fs, link.getFileStatus(fs), link);
135    } else if (StoreFileInfo.isReference(path)) {
136      Reference reference = Reference.read(fs, path);
137      Path referencePath = StoreFileInfo.getReferredToFile(path);
138      if (HFileLink.isHFileLink(referencePath)) {
139        // HFileLink Reference
140        HFileLink link = HFileLink.buildFromHFileLinkPattern(conf, referencePath);
141        return new StoreFileInfo(conf, fs, link.getFileStatus(fs), reference, link);
142      } else {
143        // Reference
144        HFileLink link = HFileLink.build(conf, regionInfoForFs.getTable(),
145          regionInfoForFs.getEncodedName(), familyName, path.getName());
146        return new StoreFileInfo(conf, fs, link.getFileStatus(fs), reference);
147      }
148    } else {
149      throw new IOException("path=" + path + " doesn't look like a valid StoreFile");
150    }
151  }
152
153  /**
154   * @return True if Region Read Replica is enabled for <code>tn</code> (whether hbase:meta or
155   *         user-space tables).
156   */
157  public static boolean isRegionReplicaReplicationEnabled(Configuration conf, TableName tn) {
158    return isMetaRegionReplicaReplicationEnabled(conf, tn)
159      || isRegionReplicaReplicationEnabled(conf);
160  }
161
162  /**
163   * @return True if Region Read Replica is enabled for user-space tables.
164   */
165  private static boolean isRegionReplicaReplicationEnabled(Configuration conf) {
166    return conf.getBoolean(REGION_REPLICA_REPLICATION_CONF_KEY, DEFAULT_REGION_REPLICA_REPLICATION);
167  }
168
169  /**
170   * @return True if hbase:meta Region Read Replica is enabled.
171   */
172  public static boolean isMetaRegionReplicaReplicationEnabled(Configuration conf, TableName tn) {
173    return TableName.isMetaTableName(tn) && conf.getBoolean(
174      REGION_REPLICA_REPLICATION_CATALOG_CONF_KEY, DEFAULT_REGION_REPLICA_REPLICATION_CATALOG);
175  }
176
177  /**
178   * @return True if wait for primary to flush is enabled for user-space tables.
179   */
180  public static boolean isRegionReplicaWaitForPrimaryFlushEnabled(Configuration conf) {
181    return conf.getBoolean(REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH_CONF_KEY,
182      DEFAULT_REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH);
183  }
184
185  /**
186   * @return True if we are to refresh user-space hfiles in Region Read Replicas.
187   */
188  public static boolean isRegionReplicaStoreFileRefreshEnabled(Configuration conf) {
189    return conf.getBoolean(REGION_REPLICA_STORE_FILE_REFRESH,
190      DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH);
191  }
192
193  public static double getRegionReplicaStoreFileRefreshMultiplier(Configuration conf) {
194    return conf.getDouble(REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER,
195      DEFAULT_REGION_REPLICA_STORE_FILE_REFRESH_MEMSTORE_MULTIPLIER);
196  }
197
198}