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.client;
019
020import java.io.IOException;
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.hbase.HConstants;
023import org.apache.hadoop.hbase.TableName;
024import org.apache.hadoop.hbase.master.RegionState;
025import org.apache.hadoop.hbase.util.Bytes;
026import org.apache.yetus.audience.InterfaceAudience;
027
028/**
029 * Utility used composing RegionInfo for 'display'; e.g. on the web UI
030 */
031@InterfaceAudience.Private
032public class RegionInfoDisplay {
033  public final static String DISPLAY_KEYS_KEY = "hbase.display.keys";
034  public final static byte[] HIDDEN_END_KEY = Bytes.toBytes("hidden-end-key");
035  public final static byte[] HIDDEN_START_KEY = Bytes.toBytes("hidden-start-key");
036
037  /**
038   * Get the descriptive name as {@link RegionState} does it but with hidden startkey optionally
039   * @return descriptive string
040   */
041  public static String getDescriptiveNameFromRegionStateForDisplay(RegionState state,
042    Configuration conf) {
043    if (conf.getBoolean(DISPLAY_KEYS_KEY, true)) return state.toDescriptiveString();
044    String descriptiveStringFromState = state.toDescriptiveString();
045    int idx = descriptiveStringFromState.lastIndexOf(" state=");
046    String regionName = getRegionNameAsStringForDisplay(
047      RegionInfoBuilder.newBuilder(state.getRegion()).build(), conf);
048    return regionName + descriptiveStringFromState.substring(idx);
049  }
050
051  /**
052   * Get the end key for display. Optionally hide the real end key.
053   * @return the endkey
054   */
055  public static byte[] getEndKeyForDisplay(RegionInfo ri, Configuration conf) {
056    boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
057    if (displayKey) return ri.getEndKey();
058    return HIDDEN_END_KEY;
059  }
060
061  /**
062   * Get the start key for display. Optionally hide the real start key.
063   * @return the startkey
064   */
065  public static byte[] getStartKeyForDisplay(RegionInfo ri, Configuration conf) {
066    boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
067    if (displayKey) return ri.getStartKey();
068    return HIDDEN_START_KEY;
069  }
070
071  /**
072   * Get the region name for display. Optionally hide the start key.
073   * @return region name as String
074   */
075  public static String getRegionNameAsStringForDisplay(RegionInfo ri, Configuration conf) {
076    return Bytes.toStringBinary(getRegionNameForDisplay(ri, conf));
077  }
078
079  /**
080   * Get the region name for display. Optionally hide the start key.
081   * @return region name bytes
082   */
083  public static byte[] getRegionNameForDisplay(RegionInfo ri, Configuration conf) {
084    boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
085    if (displayKey || ri.getTable().equals(TableName.META_TABLE_NAME)) {
086      return ri.getRegionName();
087    } else {
088      // create a modified regionname with the startkey replaced but preserving
089      // the other parts including the encodedname.
090      try {
091        byte[][] regionNameParts = RegionInfo.parseRegionName(ri.getRegionName());
092        regionNameParts[1] = HIDDEN_START_KEY; // replace the real startkey
093        int len = 0;
094        // get the total length
095        for (byte[] b : regionNameParts) {
096          len += b.length;
097        }
098        byte[] encodedRegionName = Bytes.toBytes(RegionInfo.encodeRegionName(ri.getRegionName()));
099        len += encodedRegionName.length;
100        // allocate some extra bytes for the delimiters and the last '.'
101        byte[] modifiedName = new byte[len + regionNameParts.length + 1];
102        int lengthSoFar = 0;
103        int loopCount = 0;
104        for (byte[] b : regionNameParts) {
105          System.arraycopy(b, 0, modifiedName, lengthSoFar, b.length);
106          lengthSoFar += b.length;
107          if (loopCount++ == 2) modifiedName[lengthSoFar++] = RegionInfo.REPLICA_ID_DELIMITER;
108          else modifiedName[lengthSoFar++] = HConstants.DELIMITER;
109        }
110        // replace the last comma with '.'
111        modifiedName[lengthSoFar - 1] = RegionInfo.ENC_SEPARATOR;
112        System.arraycopy(encodedRegionName, 0, modifiedName, lengthSoFar, encodedRegionName.length);
113        lengthSoFar += encodedRegionName.length;
114        modifiedName[lengthSoFar] = RegionInfo.ENC_SEPARATOR;
115        return modifiedName;
116      } catch (IOException e) {
117        // LOG.warn("Encountered exception " + e);
118        throw new RuntimeException(e);
119      }
120    }
121  }
122}