1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.io.hfile;
21
22 import java.io.DataInputStream;
23 import java.io.DataOutput;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.nio.ByteBuffer;
27
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.util.Bytes;
30
31
32
33
34
35 @InterfaceAudience.Private
36 public enum BlockType {
37
38
39
40
41 DATA("DATABLK*", BlockCategory.DATA),
42
43
44 ENCODED_DATA("DATABLKE", BlockCategory.DATA) {
45 @Override
46 public int getId() {
47 return DATA.ordinal();
48 }
49 },
50
51
52 LEAF_INDEX("IDXLEAF2", BlockCategory.INDEX),
53
54
55 BLOOM_CHUNK("BLMFBLK2", BlockCategory.BLOOM),
56
57
58
59
60 META("METABLKc", BlockCategory.META),
61
62
63 INTERMEDIATE_INDEX("IDXINTE2", BlockCategory.INDEX),
64
65
66
67
68 ROOT_INDEX("IDXROOT2", BlockCategory.INDEX),
69
70
71 FILE_INFO("FILEINF2", BlockCategory.META),
72
73
74 GENERAL_BLOOM_META("BLMFMET2", BlockCategory.BLOOM),
75
76
77 DELETE_FAMILY_BLOOM_META("DFBLMET2", BlockCategory.BLOOM),
78
79
80
81
82 TRAILER("TRABLK\"$", BlockCategory.META),
83
84
85
86
87 INDEX_V1("IDXBLK)+", BlockCategory.INDEX);
88
89 public enum BlockCategory {
90 DATA, META, INDEX, BLOOM, ALL_CATEGORIES, UNKNOWN;
91
92
93
94
95
96 public void expectSpecific() {
97 if (this == ALL_CATEGORIES) {
98 throw new IllegalArgumentException("Expected a specific block " +
99 "category but got " + this);
100 }
101 }
102 }
103
104 public static final int MAGIC_LENGTH = 8;
105
106 private final byte[] magic;
107 private final BlockCategory metricCat;
108
109 private BlockType(String magicStr, BlockCategory metricCat) {
110 magic = Bytes.toBytes(magicStr);
111 this.metricCat = metricCat;
112 assert magic.length == MAGIC_LENGTH;
113 }
114
115
116
117
118
119
120
121 public int getId() {
122
123 return ordinal();
124 }
125
126 public void writeToStream(OutputStream out) throws IOException {
127 out.write(magic);
128 }
129
130 public void write(DataOutput out) throws IOException {
131 out.write(magic);
132 }
133
134 public void write(ByteBuffer buf) {
135 buf.put(magic);
136 }
137
138 public BlockCategory getCategory() {
139 return metricCat;
140 }
141
142 public static BlockType parse(byte[] buf, int offset, int length)
143 throws IOException {
144 if (length != MAGIC_LENGTH) {
145 throw new IOException("Magic record of invalid length: "
146 + Bytes.toStringBinary(buf, offset, length));
147 }
148
149 for (BlockType blockType : values())
150 if (Bytes.compareTo(blockType.magic, 0, MAGIC_LENGTH, buf, offset,
151 MAGIC_LENGTH) == 0)
152 return blockType;
153
154 throw new IOException("Invalid HFile block magic: "
155 + Bytes.toStringBinary(buf, offset, MAGIC_LENGTH));
156 }
157
158 public static BlockType read(DataInputStream in) throws IOException {
159 byte[] buf = new byte[MAGIC_LENGTH];
160 in.readFully(buf);
161 return parse(buf, 0, buf.length);
162 }
163
164 public static BlockType read(ByteBuffer buf) throws IOException {
165 byte[] magicBuf = new byte[Math.min(buf.limit() - buf.position(), MAGIC_LENGTH)];
166 buf.get(magicBuf);
167 BlockType blockType = parse(magicBuf, 0, magicBuf.length);
168
169 return blockType;
170 }
171
172
173
174
175
176
177
178
179 public int put(byte[] bytes, int offset) {
180 System.arraycopy(magic, 0, bytes, offset, MAGIC_LENGTH);
181 return offset + MAGIC_LENGTH;
182 }
183
184
185
186
187
188 public void readAndCheck(DataInputStream in) throws IOException {
189 byte[] buf = new byte[MAGIC_LENGTH];
190 in.readFully(buf);
191 if (Bytes.compareTo(buf, magic) != 0) {
192 throw new IOException("Invalid magic: expected "
193 + Bytes.toStringBinary(magic) + ", got " + Bytes.toStringBinary(buf));
194 }
195 }
196
197
198
199
200
201 public void readAndCheck(ByteBuffer in) throws IOException {
202 byte[] buf = new byte[MAGIC_LENGTH];
203 in.get(buf);
204 if (Bytes.compareTo(buf, magic) != 0) {
205 throw new IOException("Invalid magic: expected "
206 + Bytes.toStringBinary(magic) + ", got " + Bytes.toStringBinary(buf));
207 }
208 }
209
210
211
212
213 public final boolean isData() {
214 return this == DATA || this == ENCODED_DATA;
215 }
216
217 }