1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.hadoop.hbase.io.hfile;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21
22 import org.apache.hadoop.hbase.classification.InterfaceAudience;
23 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoder;
24 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
25 import org.apache.hadoop.hbase.io.encoding.HFileBlockDecodingContext;
26 import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultDecodingContext;
27 import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultEncodingContext;
28 import org.apache.hadoop.hbase.io.encoding.HFileBlockEncodingContext;
29 import org.apache.hadoop.hbase.io.hfile.HFile.FileInfo;
30 import org.apache.hadoop.hbase.util.Bytes;
31
32
33
34
35
36 @InterfaceAudience.Private
37 public class HFileDataBlockEncoderImpl implements HFileDataBlockEncoder {
38 private final DataBlockEncoding encoding;
39
40
41
42
43
44 public HFileDataBlockEncoderImpl(DataBlockEncoding encoding) {
45 this.encoding = encoding != null ? encoding : DataBlockEncoding.NONE;
46 }
47
48 public static HFileDataBlockEncoder createFromFileInfo(
49 FileInfo fileInfo) throws IOException {
50 DataBlockEncoding encoding = DataBlockEncoding.NONE;
51 byte[] dataBlockEncodingType = fileInfo.get(DATA_BLOCK_ENCODING);
52 if (dataBlockEncodingType != null) {
53 String dataBlockEncodingStr = Bytes.toString(dataBlockEncodingType);
54 try {
55 encoding = DataBlockEncoding.valueOf(dataBlockEncodingStr);
56 } catch (IllegalArgumentException ex) {
57 throw new IOException("Invalid data block encoding type in file info: "
58 + dataBlockEncodingStr, ex);
59 }
60 }
61
62 if (encoding == DataBlockEncoding.NONE) {
63 return NoOpDataBlockEncoder.INSTANCE;
64 }
65 return new HFileDataBlockEncoderImpl(encoding);
66 }
67
68 @Override
69 public void saveMetadata(HFile.Writer writer) throws IOException {
70 writer.appendFileInfo(DATA_BLOCK_ENCODING, encoding.getNameInBytes());
71 }
72
73 @Override
74 public DataBlockEncoding getDataBlockEncoding() {
75 return encoding;
76 }
77
78
79
80
81
82
83
84
85 @Override
86 public void beforeWriteToDisk(ByteBuffer in,
87 HFileBlockEncodingContext encodeCtx,
88 BlockType blockType) throws IOException {
89 if (encoding == DataBlockEncoding.NONE) {
90
91 ((HFileBlockDefaultEncodingContext) encodeCtx).compressAfterEncodingWithBlockType(
92 in.array(), blockType);
93 return;
94 }
95 encodeBufferToHFileBlockBuffer(in, encoding, encodeCtx);
96 }
97
98 @Override
99 public boolean useEncodedScanner() {
100 return encoding != DataBlockEncoding.NONE;
101 }
102
103
104
105
106
107
108
109
110 private void encodeBufferToHFileBlockBuffer(ByteBuffer in, DataBlockEncoding algo,
111 HFileBlockEncodingContext encodeCtx) {
112 DataBlockEncoder encoder = algo.getEncoder();
113 try {
114 encoder.encodeKeyValues(in, encodeCtx);
115 } catch (IOException e) {
116 throw new RuntimeException(String.format(
117 "Bug in data block encoder "
118 + "'%s', it probably requested too much data, " +
119 "exception message: %s.",
120 algo.toString(), e.getMessage()), e);
121 }
122 }
123
124 @Override
125 public String toString() {
126 return getClass().getSimpleName() + "(encoding=" + encoding + ")";
127 }
128
129 @Override
130 public HFileBlockEncodingContext newDataBlockEncodingContext(
131 byte[] dummyHeader, HFileContext fileContext) {
132 DataBlockEncoder encoder = encoding.getEncoder();
133 if (encoder != null) {
134 return encoder.newDataBlockEncodingContext(encoding, dummyHeader, fileContext);
135 }
136 return new HFileBlockDefaultEncodingContext(null, dummyHeader, fileContext);
137 }
138
139 @Override
140 public HFileBlockDecodingContext newDataBlockDecodingContext(HFileContext fileContext) {
141 DataBlockEncoder encoder = encoding.getEncoder();
142 if (encoder != null) {
143 return encoder.newDataBlockDecodingContext(fileContext);
144 }
145 return new HFileBlockDefaultDecodingContext(fileContext);
146 }
147 }