blob: f9a99549362b5479a3038b57c71eed0d52310a1e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hbase;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.util.ByteArrayHashKey;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.HashKey;
import org.apache.hadoop.hbase.util.JenkinsHash;
/**
* A copy of utilities from {@link org.apache.hadoop.hbase.client.RegionInfo} to copy internal
* methods into HBCK2 for stability to avoid using Private methods.
*/
public final class HBCKRegionInfo {
/**
* Separator used to demarcate the encodedName in a region name in the new format. See description
* on new format above.
*/
static final int ENC_SEPARATOR = '.';
static final int MD5_HEX_LENGTH = 32;
static final int DEFAULT_REPLICA_ID = 0;
static final byte REPLICA_ID_DELIMITER = (byte) '_';
private HBCKRegionInfo() {
}
/**
* Does region name contain its encoded name?
* @param regionName region name
* @return boolean indicating if this a new format region name which contains its encoded name.
*/
public static boolean hasEncodedName(final byte[] regionName) {
// check if region name ends in ENC_SEPARATOR
return (regionName.length >= 1)
&& (regionName[regionName.length - 1] == RegionInfo.ENC_SEPARATOR);
}
/** Returns the encodedName */
public static String encodeRegionName(final byte[] regionName) {
String encodedName;
if (hasEncodedName(regionName)) {
// region is in new format:
// <tableName>,<startKey>,<regionIdTimeStamp>/encodedName/
encodedName =
Bytes.toString(regionName, regionName.length - MD5_HEX_LENGTH - 1, MD5_HEX_LENGTH);
} else {
// old format region name. First hbase:meta region also
// use this format.EncodedName is the JenkinsHash value.
HashKey<byte[]> key = new ByteArrayHashKey(regionName, 0, regionName.length);
int hashVal = Math.abs(JenkinsHash.getInstance().hash(key, 0));
encodedName = String.valueOf(hashVal);
}
return encodedName;
}
/**
* Separate elements of a regionName. Region name is of the format:
* <code>tablename,startkey,regionIdTimestamp[_replicaId][.encodedName.]</code>. Startkey can
* contain the delimiter (',') so we parse from the start and then parse from the end.
* @return Array of byte[] containing tableName, startKey and id OR null if not parseable as a
* region name.
*/
public static byte[][] parseRegionNameOrReturnNull(final byte[] regionName) {
int offset = -1;
for (int i = 0; i < regionName.length; i++) {
if (regionName[i] == HConstants.DELIMITER) {
offset = i;
break;
}
}
if (offset == -1) {
return null;
}
byte[] tableName = new byte[offset];
System.arraycopy(regionName, 0, tableName, 0, offset);
offset = -1;
int endOffset = regionName.length;
// check whether regionName contains encodedName
if (
regionName.length > MD5_HEX_LENGTH + 2 && regionName[regionName.length - 1] == ENC_SEPARATOR
&& regionName[regionName.length - MD5_HEX_LENGTH - 2] == ENC_SEPARATOR
) {
endOffset = endOffset - MD5_HEX_LENGTH - 2;
}
// parse from end
byte[] replicaId = null;
int idEndOffset = endOffset;
for (int i = endOffset - 1; i > 0; i--) {
if (regionName[i] == REPLICA_ID_DELIMITER) { // replicaId may or may not be present
replicaId = new byte[endOffset - i - 1];
System.arraycopy(regionName, i + 1, replicaId, 0, endOffset - i - 1);
idEndOffset = i;
// do not break, continue to search for id
}
if (regionName[i] == HConstants.DELIMITER) {
offset = i;
break;
}
}
if (offset == -1) {
return null;
}
byte[] startKey = HConstants.EMPTY_BYTE_ARRAY;
if (offset != tableName.length + 1) {
startKey = new byte[offset - tableName.length - 1];
System.arraycopy(regionName, tableName.length + 1, startKey, 0,
offset - tableName.length - 1);
}
byte[] id = new byte[idEndOffset - offset - 1];
System.arraycopy(regionName, offset + 1, id, 0, idEndOffset - offset - 1);
byte[][] elements = new byte[replicaId == null ? 3 : 4][];
elements[0] = tableName;
elements[1] = startKey;
elements[2] = id;
if (replicaId != null) {
elements[3] = replicaId;
}
return elements;
}
}