View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.client;
20  
21  import java.util.Collection;
22  import java.util.Iterator;
23  
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.HRegionInfo;
26  import org.apache.hadoop.hbase.util.Bytes;
27  
28  /**
29   * Utility methods which contain the logic for regions and replicas.
30   */
31  @InterfaceAudience.Private
32  public class RegionReplicaUtil {
33  
34    /**
35     * Whether or not the secondary region will wait for observing a flush / region open event
36     * from the primary region via async wal replication before enabling read requests. Since replayed
37     * edits from async wal replication from primary is not persisted in WAL, the memstore of the
38     * secondary region might be non-empty at the time of close or crash. For ensuring seqId's not
39     * "going back in time" in the secondary region replica, this should be enabled. However, in some
40     * cases the above semantics might be ok for some application classes.
41     * See HBASE-11580 for more context.
42     */
43    public static final String REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH_CONF_KEY
44      = "hbase.region.replica.wait.for.primary.flush";
45    protected static final boolean DEFAULT_REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH = true;
46  
47    /**
48     * The default replicaId for the region
49     */
50    static final int DEFAULT_REPLICA_ID = 0;
51  
52    /**
53     * Returns the HRegionInfo for the given replicaId. HRegionInfo's correspond to
54     * a range of a table, but more than one "instance" of the same range can be
55     * deployed which are differentiated by the replicaId.
56     * @param replicaId the replicaId to use
57     * @return an HRegionInfo object corresponding to the same range (table, start and
58     * end key), but for the given replicaId.
59     */
60    public static HRegionInfo getRegionInfoForReplica(HRegionInfo regionInfo, int replicaId) {
61      if (regionInfo.getReplicaId() == replicaId) {
62        return regionInfo;
63      }
64      HRegionInfo replicaInfo;
65      if (regionInfo.isMetaRegion()) {
66        replicaInfo = new HRegionInfo(regionInfo.getRegionId(), regionInfo.getTable(), replicaId);
67      } else {
68        replicaInfo = new HRegionInfo(regionInfo.getTable(), regionInfo.getStartKey(),
69          regionInfo.getEndKey(), regionInfo.isSplit(), regionInfo.getRegionId(), replicaId);
70      }
71      replicaInfo.setOffline(regionInfo.isOffline());
72      return replicaInfo;
73    }
74  
75    /**
76     * Returns the HRegionInfo for the default replicaId (0). HRegionInfo's correspond to
77     * a range of a table, but more than one "instance" of the same range can be
78     * deployed which are differentiated by the replicaId.
79     * @return an HRegionInfo object corresponding to the same range (table, start and
80     * end key), but for the default replicaId.
81     */
82    public static HRegionInfo getRegionInfoForDefaultReplica(HRegionInfo regionInfo) {
83      return getRegionInfoForReplica(regionInfo, DEFAULT_REPLICA_ID);
84    }
85  
86    /** @return true if this replicaId corresponds to default replica for the region */
87    public static boolean isDefaultReplica(int replicaId) {
88      return DEFAULT_REPLICA_ID == replicaId;
89    }
90  
91    /** @return true if this region is a default replica for the region */
92    public static boolean isDefaultReplica(HRegionInfo hri) {
93      return  hri.getReplicaId() == DEFAULT_REPLICA_ID;
94    }
95  
96    /**
97     * Removes the non-default replicas from the passed regions collection
98     * @param regions
99     */
100   public static void removeNonDefaultRegions(Collection<HRegionInfo> regions) {
101     Iterator<HRegionInfo> iterator = regions.iterator();
102     while (iterator.hasNext()) {
103       HRegionInfo hri = iterator.next();
104       if (!RegionReplicaUtil.isDefaultReplica(hri)) {
105         iterator.remove();
106       }
107     }
108   }
109 
110   public static boolean isReplicasForSameRegion(HRegionInfo regionInfoA, HRegionInfo regionInfoB) {
111     return compareRegionInfosWithoutReplicaId(regionInfoA, regionInfoB) == 0;
112   }
113 
114   private static int compareRegionInfosWithoutReplicaId(HRegionInfo regionInfoA,
115       HRegionInfo regionInfoB) {
116     int result = regionInfoA.getTable().compareTo(regionInfoB.getTable());
117     if (result != 0) {
118       return result;
119     }
120 
121     // Compare start keys.
122     result = Bytes.compareTo(regionInfoA.getStartKey(), regionInfoB.getStartKey());
123     if (result != 0) {
124       return result;
125     }
126 
127     // Compare end keys.
128     result = Bytes.compareTo(regionInfoA.getEndKey(), regionInfoB.getEndKey());
129 
130     if (result != 0) {
131       if (regionInfoA.getStartKey().length != 0
132               && regionInfoA.getEndKey().length == 0) {
133           return 1; // this is last region
134       }
135       if (regionInfoB.getStartKey().length != 0
136               && regionInfoB.getEndKey().length == 0) {
137           return -1; // o is the last region
138       }
139       return result;
140     }
141 
142     // regionId is usually milli timestamp -- this defines older stamps
143     // to be "smaller" than newer stamps in sort order.
144     if (regionInfoA.getRegionId() > regionInfoB.getRegionId()) {
145       return 1;
146     } else if (regionInfoA.getRegionId() < regionInfoB.getRegionId()) {
147       return -1;
148     }
149     return 0;
150   }
151 }