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