1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  package org.apache.hadoop.hbase.io.encoding;
18  
19  import java.io.IOException;
20  import java.io.OutputStream;
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.classification.InterfaceStability;
26  import org.apache.hadoop.hbase.util.Bytes;
27  
28  
29  
30  
31  
32  
33  
34  @InterfaceAudience.Public
35  @InterfaceStability.Evolving
36  public enum DataBlockEncoding {
37  
38    
39    NONE(0, null),
40    
41    PREFIX(2, "org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder"),
42    DIFF(3, "org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder"),
43    FAST_DIFF(4, "org.apache.hadoop.hbase.io.encoding.FastDiffDeltaEncoder"),
44    
45    
46    PREFIX_TREE(6, "org.apache.hadoop.hbase.codec.prefixtree.PrefixTreeCodec");
47  
48    private final short id;
49    private final byte[] idInBytes;
50    private DataBlockEncoder encoder;
51    private final String encoderCls;
52  
53    public static final int ID_SIZE = Bytes.SIZEOF_SHORT;
54  
55    
56    private static Map<Short, DataBlockEncoding> idToEncoding =
57        new HashMap<Short, DataBlockEncoding>();
58  
59    static {
60      for (DataBlockEncoding algo : values()) {
61        if (idToEncoding.containsKey(algo.id)) {
62          throw new RuntimeException(String.format(
63              "Two data block encoder algorithms '%s' and '%s' have " +
64              "the same id %d",
65              idToEncoding.get(algo.id).toString(), algo.toString(),
66              (int) algo.id));
67        }
68        idToEncoding.put(algo.id, algo);
69      }
70    }
71  
72    private DataBlockEncoding(int id, String encoderClsName) {
73      if (id < Short.MIN_VALUE || id > Short.MAX_VALUE) {
74        throw new AssertionError(
75            "Data block encoding algorithm id is out of range: " + id);
76      }
77      this.id = (short) id;
78      this.idInBytes = Bytes.toBytes(this.id);
79      if (idInBytes.length != ID_SIZE) {
80        
81        
82        throw new RuntimeException("Unexpected length of encoder ID byte " +
83            "representation: " + Bytes.toStringBinary(idInBytes));
84      }
85      this.encoderCls = encoderClsName;
86    }
87  
88    
89  
90  
91    public byte[] getNameInBytes() {
92      return Bytes.toBytes(toString());
93    }
94  
95    
96  
97  
98    public short getId() {
99      return id;
100   }
101 
102   
103 
104 
105 
106   public void writeIdInBytes(OutputStream stream) throws IOException {
107     stream.write(idInBytes);
108   }
109 
110 
111   
112 
113 
114 
115 
116 
117 
118   public void writeIdInBytes(byte[] dest, int offset) throws IOException {
119     System.arraycopy(idInBytes, 0, dest, offset, ID_SIZE);
120   }
121 
122   
123 
124 
125 
126 
127   public DataBlockEncoder getEncoder() {
128     if (encoder == null && id != 0) {
129       
130       encoder = createEncoder(encoderCls);
131     }
132     return encoder;
133   }
134 
135   
136 
137 
138 
139 
140   public static DataBlockEncoder getDataBlockEncoderById(short encoderId) {
141     if (!idToEncoding.containsKey(encoderId)) {
142       throw new IllegalArgumentException(String.format(
143           "There is no data block encoder for given id '%d'",
144           (int) encoderId));
145     }
146 
147     return idToEncoding.get(encoderId).getEncoder();
148   }
149 
150   
151 
152 
153 
154 
155   public static String getNameFromId(short encoderId) {
156     return idToEncoding.get(encoderId).toString();
157   }
158 
159   
160 
161 
162 
163 
164 
165 
166 
167   public static boolean isCorrectEncoder(DataBlockEncoder encoder,
168       short encoderId) {
169     if (!idToEncoding.containsKey(encoderId)) {
170       throw new IllegalArgumentException(String.format(
171           "There is no data block encoder for given id '%d'",
172           (int) encoderId));
173     }
174 
175     DataBlockEncoding algorithm = idToEncoding.get(encoderId);
176     String encoderCls = encoder.getClass().getName();
177     return encoderCls.equals(algorithm.encoderCls);
178   }
179 
180   public static DataBlockEncoding getEncodingById(short dataBlockEncodingId) {
181     return idToEncoding.get(dataBlockEncodingId);
182   }
183 
184   protected static DataBlockEncoder createEncoder(String fullyQualifiedClassName){
185       try {
186         return (DataBlockEncoder)Class.forName(fullyQualifiedClassName).newInstance();
187       } catch (InstantiationException e) {
188         throw new RuntimeException(e);
189       } catch (IllegalAccessException e) {
190         throw new RuntimeException(e);
191       } catch (ClassNotFoundException e) {
192         throw new IllegalArgumentException(e);
193       }
194   }
195 
196 }