001/*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.client;
020
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.hbase.HConstants;
023import org.apache.hadoop.hbase.TableName;
024import org.apache.hadoop.hbase.client.RegionInfo;
025import org.apache.hadoop.hbase.client.RegionInfoBuilder;
026import org.apache.hadoop.hbase.master.RegionState;
027import org.apache.hadoop.hbase.util.Bytes;
028import org.apache.yetus.audience.InterfaceAudience;
029
030import java.io.IOException;
031
032/**
033 * Utility used composing RegionInfo for 'display'; e.g. on the web UI
034 */
035@InterfaceAudience.Private
036public class RegionInfoDisplay {
037  public final static String DISPLAY_KEYS_KEY = "hbase.display.keys";
038  public final static byte[] HIDDEN_END_KEY = Bytes.toBytes("hidden-end-key");
039  public final static byte[] HIDDEN_START_KEY = Bytes.toBytes("hidden-start-key");
040
041  /**
042   * Get the descriptive name as {@link RegionState} does it but with hidden
043   * startkey optionally
044   * @return descriptive string
045   */
046  public static String getDescriptiveNameFromRegionStateForDisplay(RegionState state,
047                                                                   Configuration conf) {
048    if (conf.getBoolean(DISPLAY_KEYS_KEY, true)) return state.toDescriptiveString();
049    String descriptiveStringFromState = state.toDescriptiveString();
050    int idx = descriptiveStringFromState.lastIndexOf(" state=");
051    String regionName = getRegionNameAsStringForDisplay(
052    RegionInfoBuilder.newBuilder(state.getRegion()).build(), conf);
053    return regionName + descriptiveStringFromState.substring(idx);
054  }
055
056  /**
057   * Get the end key for display. Optionally hide the real end key.
058   * @return the endkey
059   */
060  public static byte[] getEndKeyForDisplay(RegionInfo ri, Configuration conf) {
061    boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
062    if (displayKey) return ri.getEndKey();
063    return HIDDEN_END_KEY;
064  }
065
066  /**
067   * Get the start key for display. Optionally hide the real start key.
068   * @param ri
069   * @param conf
070   * @return the startkey
071   */
072  public static byte[] getStartKeyForDisplay(RegionInfo ri, Configuration conf) {
073    boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
074    if (displayKey) return ri.getStartKey();
075    return HIDDEN_START_KEY;
076  }
077
078  /**
079   * Get the region name for display. Optionally hide the start key.
080   * @param ri
081   * @param conf
082   * @return region name as String
083   */
084  public static String getRegionNameAsStringForDisplay(RegionInfo ri, Configuration conf) {
085    return Bytes.toStringBinary(getRegionNameForDisplay(ri, conf));
086  }
087
088  /**
089   * Get the region name for display. Optionally hide the start key.
090   * @param ri
091   * @param conf
092   * @return region name bytes
093   */
094  public static byte[] getRegionNameForDisplay(RegionInfo ri, Configuration conf) {
095    boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
096    if (displayKey || ri.getTable().equals(TableName.META_TABLE_NAME)) {
097      return ri.getRegionName();
098    } else {
099      // create a modified regionname with the startkey replaced but preserving
100      // the other parts including the encodedname.
101      try {
102        byte[][]regionNameParts = RegionInfo.parseRegionName(ri.getRegionName());
103        regionNameParts[1] = HIDDEN_START_KEY; //replace the real startkey
104        int len = 0;
105        // get the total length
106        for (byte[] b : regionNameParts) {
107          len += b.length;
108        }
109        byte[] encodedRegionName =
110        Bytes.toBytes(RegionInfo.encodeRegionName(ri.getRegionName()));
111        len += encodedRegionName.length;
112        //allocate some extra bytes for the delimiters and the last '.'
113        byte[] modifiedName = new byte[len + regionNameParts.length + 1];
114        int lengthSoFar = 0;
115        int loopCount = 0;
116        for (byte[] b : regionNameParts) {
117          System.arraycopy(b, 0, modifiedName, lengthSoFar, b.length);
118          lengthSoFar += b.length;
119          if (loopCount++ == 2) modifiedName[lengthSoFar++] = RegionInfo.REPLICA_ID_DELIMITER;
120          else  modifiedName[lengthSoFar++] = HConstants.DELIMITER;
121        }
122        // replace the last comma with '.'
123        modifiedName[lengthSoFar - 1] = RegionInfo.ENC_SEPARATOR;
124        System.arraycopy(encodedRegionName, 0, modifiedName, lengthSoFar,
125        encodedRegionName.length);
126        lengthSoFar += encodedRegionName.length;
127        modifiedName[lengthSoFar] = RegionInfo.ENC_SEPARATOR;
128        return modifiedName;
129      } catch (IOException e) {
130        //LOG.warn("Encountered exception " + e);
131        throw new RuntimeException(e);
132      }
133    }
134  }
135}