1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.codec.prefixtree;
20
21 import java.io.DataInputStream;
22 import java.io.DataOutputStream;
23 import java.io.IOException;
24 import java.nio.ByteBuffer;
25
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.hadoop.hbase.KeyValue;
28 import org.apache.hadoop.hbase.KeyValue.KeyComparator;
29 import org.apache.hadoop.hbase.KeyValue.MetaKeyComparator;
30 import org.apache.hadoop.hbase.KeyValueUtil;
31 import org.apache.hadoop.hbase.codec.prefixtree.decode.DecoderFactory;
32 import org.apache.hadoop.hbase.codec.prefixtree.decode.PrefixTreeArraySearcher;
33 import org.apache.hadoop.hbase.codec.prefixtree.encode.EncoderFactory;
34 import org.apache.hadoop.hbase.codec.prefixtree.encode.PrefixTreeEncoder;
35 import org.apache.hadoop.hbase.codec.prefixtree.scanner.CellSearcher;
36 import org.apache.hadoop.hbase.io.compress.Compression.Algorithm;
37 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoder;
38 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
39 import org.apache.hadoop.hbase.io.encoding.HFileBlockDecodingContext;
40 import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultDecodingContext;
41 import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultEncodingContext;
42 import org.apache.hadoop.hbase.io.encoding.HFileBlockEncodingContext;
43 import org.apache.hadoop.hbase.io.hfile.BlockType;
44 import org.apache.hadoop.hbase.util.ByteBufferUtils;
45 import org.apache.hadoop.io.RawComparator;
46
47
48
49
50
51
52
53
54
55
56
57 @InterfaceAudience.Private
58 public class PrefixTreeCodec implements DataBlockEncoder{
59
60
61
62
63 public PrefixTreeCodec() {
64 }
65
66
67
68
69
70 @Override
71 public void encodeKeyValues(ByteBuffer in, boolean includesMvccVersion,
72 HFileBlockEncodingContext blkEncodingCtx) throws IOException {
73 if (blkEncodingCtx.getClass() != HFileBlockDefaultEncodingContext.class) {
74 throw new IOException(this.getClass().getName() + " only accepts "
75 + HFileBlockDefaultEncodingContext.class.getName() + " as the " + "encoding context.");
76 }
77
78 HFileBlockDefaultEncodingContext encodingCtx
79 = (HFileBlockDefaultEncodingContext) blkEncodingCtx;
80 encodingCtx.prepareEncoding();
81 DataOutputStream dataOut = encodingCtx.getOutputStreamForEncoder();
82 internalEncodeKeyValues(dataOut, in, includesMvccVersion);
83
84
85 if (encodingCtx.getDataBlockEncoding() != DataBlockEncoding.NONE) {
86 encodingCtx.postEncoding(BlockType.ENCODED_DATA);
87 } else {
88 encodingCtx.postEncoding(BlockType.DATA);
89 }
90 }
91
92 private void internalEncodeKeyValues(DataOutputStream encodedOutputStream,
93 ByteBuffer rawKeyValues, boolean includesMvccVersion) throws IOException {
94 rawKeyValues.rewind();
95 PrefixTreeEncoder builder = EncoderFactory.checkOut(encodedOutputStream, includesMvccVersion);
96
97 try{
98 KeyValue kv;
99 while ((kv = KeyValueUtil.nextShallowCopy(rawKeyValues, includesMvccVersion)) != null) {
100 builder.write(kv);
101 }
102 builder.flush();
103 }finally{
104 EncoderFactory.checkIn(builder);
105 }
106 }
107
108
109 @Override
110 public ByteBuffer decodeKeyValues(DataInputStream source, boolean includesMvccVersion)
111 throws IOException {
112 return decodeKeyValues(source, 0, 0, includesMvccVersion);
113 }
114
115
116
117
118
119
120 @Override
121 public ByteBuffer decodeKeyValues(DataInputStream source, int allocateHeaderLength,
122 int skipLastBytes, boolean includesMvccVersion) throws IOException {
123 ByteBuffer sourceAsBuffer = ByteBufferUtils.drainInputStreamToBuffer(source);
124 sourceAsBuffer.mark();
125 PrefixTreeBlockMeta blockMeta = new PrefixTreeBlockMeta(sourceAsBuffer);
126 sourceAsBuffer.rewind();
127 int numV1BytesWithHeader = allocateHeaderLength + blockMeta.getNumKeyValueBytes();
128 byte[] keyValueBytesWithHeader = new byte[numV1BytesWithHeader];
129 ByteBuffer result = ByteBuffer.wrap(keyValueBytesWithHeader);
130 result.rewind();
131 CellSearcher searcher = null;
132 try {
133 searcher = DecoderFactory.checkOut(sourceAsBuffer, includesMvccVersion);
134 while (searcher.advance()) {
135 KeyValue currentCell = KeyValueUtil.copyToNewKeyValue(searcher.current());
136
137
138 int offset = result.arrayOffset() + result.position();
139 KeyValueUtil.appendToByteArray(currentCell, result.array(), offset);
140 int keyValueLength = KeyValueUtil.length(currentCell);
141 ByteBufferUtils.skip(result, keyValueLength);
142 offset += keyValueLength;
143 if (includesMvccVersion) {
144 ByteBufferUtils.writeVLong(result, currentCell.getMvccVersion());
145 }
146 }
147 result.position(result.limit());
148 return result;
149 } finally {
150 DecoderFactory.checkIn(searcher);
151 }
152 }
153
154
155 @Override
156 public ByteBuffer getFirstKeyInBlock(ByteBuffer block) {
157 block.rewind();
158 PrefixTreeArraySearcher searcher = null;
159 try {
160
161 searcher = DecoderFactory.checkOut(block, true);
162 if (!searcher.positionAtFirstCell()) {
163 return null;
164 }
165 return KeyValueUtil.copyKeyToNewByteBuffer(searcher.current());
166 } finally {
167 DecoderFactory.checkIn(searcher);
168 }
169 }
170
171 @Override
172 public HFileBlockEncodingContext newDataBlockEncodingContext(Algorithm compressionAlgorithm,
173 DataBlockEncoding encoding, byte[] header) {
174 if(DataBlockEncoding.PREFIX_TREE != encoding){
175
176
177 throw new IllegalArgumentException("only DataBlockEncoding.PREFIX_TREE supported");
178 }
179 return new HFileBlockDefaultEncodingContext(compressionAlgorithm, encoding, header);
180 }
181
182 @Override
183 public HFileBlockDecodingContext newDataBlockDecodingContext(Algorithm compressionAlgorithm) {
184 return new HFileBlockDefaultDecodingContext(compressionAlgorithm);
185 }
186
187
188
189
190
191 @Override
192 public EncodedSeeker createSeeker(RawComparator<byte[]> comparator, boolean includesMvccVersion) {
193 if(! (comparator instanceof KeyComparator)){
194 throw new IllegalArgumentException("comparator must be KeyValue.KeyComparator");
195 }
196 if(comparator instanceof MetaKeyComparator){
197 throw new IllegalArgumentException("DataBlockEncoding.PREFIX_TREE not compatible with META "
198 +"table");
199 }
200
201 return new PrefixTreeSeeker(includesMvccVersion);
202 }
203
204 }