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.io.encoding; 019 020import java.io.IOException; 021import java.io.OutputStream; 022import org.apache.hadoop.hbase.util.Bytes; 023import org.apache.yetus.audience.InterfaceAudience; 024 025/** 026 * Provide access to all index block encoding algorithms. All of the algorithms are required to have 027 * unique id which should <b>NEVER</b> be changed. If you want to add a new algorithm/version, 028 * assign it a new id. Announce the new id in the HBase mailing list to prevent collisions. 029 */ 030@InterfaceAudience.Public 031public enum IndexBlockEncoding { 032 033 /** Disable index block encoding. */ 034 NONE(0, null), 035 // id 1 is reserved for the PREFIX_TREE algorithm to be added later 036 PREFIX_TREE(1, null); 037 038 private final short id; 039 private final byte[] idInBytes; 040 private final String encoderCls; 041 042 public static final int ID_SIZE = Bytes.SIZEOF_SHORT; 043 044 /** Maps data block encoding ids to enum instances. */ 045 private static IndexBlockEncoding[] idArray = new IndexBlockEncoding[Byte.MAX_VALUE + 1]; 046 047 static { 048 for (IndexBlockEncoding algo : values()) { 049 if (idArray[algo.id] != null) { 050 throw new RuntimeException( 051 String.format("Two data block encoder algorithms '%s' and '%s' have " + "the same id %d", 052 idArray[algo.id].toString(), algo.toString(), (int) algo.id)); 053 } 054 idArray[algo.id] = algo; 055 } 056 } 057 058 private IndexBlockEncoding(int id, String encoderClsName) { 059 if (id < 0 || id > Byte.MAX_VALUE) { 060 throw new AssertionError("Data block encoding algorithm id is out of range: " + id); 061 } 062 this.id = (short) id; 063 this.idInBytes = Bytes.toBytes(this.id); 064 if (idInBytes.length != ID_SIZE) { 065 // White this may seem redundant, if we accidentally serialize 066 // the id as e.g. an int instead of a short, all encoders will break. 067 throw new RuntimeException("Unexpected length of encoder ID byte " + "representation: " 068 + Bytes.toStringBinary(idInBytes)); 069 } 070 this.encoderCls = encoderClsName; 071 } 072 073 /** Returns name converted to bytes. */ 074 public byte[] getNameInBytes() { 075 return Bytes.toBytes(toString()); 076 } 077 078 /** Returns The id of a data block encoder. */ 079 public short getId() { 080 return id; 081 } 082 083 /** 084 * Writes id in bytes. 085 * @param stream where the id should be written. 086 */ 087 public void writeIdInBytes(OutputStream stream) throws IOException { 088 stream.write(idInBytes); 089 } 090 091 /** 092 * Writes id bytes to the given array starting from offset. 093 * @param dest output array 094 * @param offset starting offset of the output array 095 */ 096 public void writeIdInBytes(byte[] dest, int offset) throws IOException { 097 System.arraycopy(idInBytes, 0, dest, offset, ID_SIZE); 098 } 099 100 /** 101 * Find and return the name of data block encoder for the given id. 102 * @param encoderId id of data block encoder 103 * @return name, same as used in options in column family 104 */ 105 public static String getNameFromId(short encoderId) { 106 return getEncodingById(encoderId).toString(); 107 } 108 109 public static IndexBlockEncoding getEncodingById(short indexBlockEncodingId) { 110 IndexBlockEncoding algorithm = null; 111 if (indexBlockEncodingId >= 0 && indexBlockEncodingId <= Byte.MAX_VALUE) { 112 algorithm = idArray[indexBlockEncodingId]; 113 } 114 if (algorithm == null) { 115 throw new IllegalArgumentException(String 116 .format("There is no index block encoder for given id '%d'", (int) indexBlockEncodingId)); 117 } 118 return algorithm; 119 } 120 121}