1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.io;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.hadoop.fs.FSDataInputStream;
28 import org.apache.hadoop.fs.FileSystem;
29 import org.apache.hadoop.fs.Path;
30 import org.apache.hadoop.hbase.KeyValue;
31 import org.apache.hadoop.hbase.client.Scan;
32 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
33 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
34 import org.apache.hadoop.hbase.io.hfile.HFileScanner;
35 import org.apache.hadoop.hbase.regionserver.StoreFile;
36 import org.apache.hadoop.hbase.util.Bytes;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 @InterfaceAudience.Private
52 public class HalfStoreFileReader extends StoreFile.Reader {
53 final Log LOG = LogFactory.getLog(HalfStoreFileReader.class);
54 final boolean top;
55
56
57 protected final byte [] splitkey;
58
59 private byte[] firstKey = null;
60
61 private boolean firstKeySeeked = false;
62
63
64
65
66
67
68
69
70
71
72 public HalfStoreFileReader(final FileSystem fs, final Path p,
73 final CacheConfig cacheConf, final Reference r,
74 DataBlockEncoding preferredEncodingInCache) throws IOException {
75 super(fs, p, cacheConf, preferredEncodingInCache);
76
77
78
79
80
81 this.splitkey = r.getSplitKey();
82
83 this.top = Reference.isTopFileRegion(r.getFileRegion());
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97 public HalfStoreFileReader(final FileSystem fs, final Path p, final FSDataInputStreamWrapper in,
98 long size, final CacheConfig cacheConf, final Reference r,
99 final DataBlockEncoding preferredEncodingInCache) throws IOException {
100 super(fs, p, in, size, cacheConf, preferredEncodingInCache);
101
102
103
104
105
106 this.splitkey = r.getSplitKey();
107
108 this.top = Reference.isTopFileRegion(r.getFileRegion());
109 }
110
111 protected boolean isTop() {
112 return this.top;
113 }
114
115 @Override
116 public HFileScanner getScanner(final boolean cacheBlocks,
117 final boolean pread, final boolean isCompaction) {
118 final HFileScanner s = super.getScanner(cacheBlocks, pread, isCompaction);
119 return new HFileScanner() {
120 final HFileScanner delegate = s;
121 public boolean atEnd = false;
122
123 public ByteBuffer getKey() {
124 if (atEnd) return null;
125 return delegate.getKey();
126 }
127
128 public String getKeyString() {
129 if (atEnd) return null;
130
131 return delegate.getKeyString();
132 }
133
134 public ByteBuffer getValue() {
135 if (atEnd) return null;
136
137 return delegate.getValue();
138 }
139
140 public String getValueString() {
141 if (atEnd) return null;
142
143 return delegate.getValueString();
144 }
145
146 public KeyValue getKeyValue() {
147 if (atEnd) return null;
148
149 return delegate.getKeyValue();
150 }
151
152 public boolean next() throws IOException {
153 if (atEnd) return false;
154
155 boolean b = delegate.next();
156 if (!b) {
157 return b;
158 }
159
160 if (!top) {
161 ByteBuffer bb = getKey();
162 if (getComparator().compare(bb.array(), bb.arrayOffset(), bb.limit(),
163 splitkey, 0, splitkey.length) >= 0) {
164 atEnd = true;
165 return false;
166 }
167 }
168 return true;
169 }
170
171 public boolean seekBefore(byte[] key) throws IOException {
172 return seekBefore(key, 0, key.length);
173 }
174
175 public boolean seekBefore(byte [] key, int offset, int length)
176 throws IOException {
177 if (top) {
178 byte[] fk = getFirstKey();
179
180 if (fk == null) return false;
181 if (getComparator().compare(key, offset, length, fk, 0,
182 fk.length) <= 0) {
183 return false;
184 }
185 } else {
186
187 if (getComparator().compare(key, offset, length, splitkey, 0,
188 splitkey.length) >= 0) {
189 return this.delegate.seekBefore(splitkey, 0, splitkey.length);
190 }
191 }
192 return this.delegate.seekBefore(key, offset, length);
193 }
194
195 public boolean seekTo() throws IOException {
196 if (top) {
197 int r = this.delegate.seekTo(splitkey);
198 if (r < 0) {
199
200 return this.delegate.seekTo();
201 }
202 if (r > 0) {
203 return this.delegate.next();
204 }
205 return true;
206 }
207
208 boolean b = delegate.seekTo();
209 if (!b) {
210 return b;
211 }
212
213 ByteBuffer k = this.delegate.getKey();
214 return this.delegate.getReader().getComparator().
215 compare(k.array(), k.arrayOffset(), k.limit(),
216 splitkey, 0, splitkey.length) < 0;
217 }
218
219 public int seekTo(byte[] key) throws IOException {
220 return seekTo(key, 0, key.length);
221 }
222
223 public int seekTo(byte[] key, int offset, int length) throws IOException {
224 if (top) {
225 if (getComparator().compare(key, offset, length, splitkey, 0,
226 splitkey.length) < 0) {
227 return -1;
228 }
229 } else {
230 if (getComparator().compare(key, offset, length, splitkey, 0,
231 splitkey.length) >= 0) {
232
233
234 boolean res = delegate.seekBefore(splitkey, 0, splitkey.length);
235 if (!res) {
236 throw new IOException("Seeking for a key in bottom of file, but key exists in top of file, failed on seekBefore(midkey)");
237 }
238 return 1;
239 }
240 }
241 return delegate.seekTo(key, offset, length);
242 }
243
244 @Override
245 public int reseekTo(byte[] key) throws IOException {
246 return reseekTo(key, 0, key.length);
247 }
248
249 @Override
250 public int reseekTo(byte[] key, int offset, int length)
251 throws IOException {
252
253
254 if (top) {
255 if (getComparator().compare(key, offset, length, splitkey, 0,
256 splitkey.length) < 0) {
257 return -1;
258 }
259 } else {
260 if (getComparator().compare(key, offset, length, splitkey, 0,
261 splitkey.length) >= 0) {
262
263
264 boolean res = delegate.seekBefore(splitkey, 0, splitkey.length);
265 if (!res) {
266 throw new IOException("Seeking for a key in bottom of file, but" +
267 " key exists in top of file, failed on seekBefore(midkey)");
268 }
269 return 1;
270 }
271 }
272 if (atEnd) {
273
274 return 1;
275 }
276 return delegate.reseekTo(key, offset, length);
277 }
278
279 public org.apache.hadoop.hbase.io.hfile.HFile.Reader getReader() {
280 return this.delegate.getReader();
281 }
282
283 public boolean isSeeked() {
284 return this.delegate.isSeeked();
285 }
286 };
287 }
288
289 @Override
290 public boolean passesKeyRangeFilter(Scan scan) {
291 return true;
292 }
293
294 @Override
295 public byte[] getLastKey() {
296 if (top) {
297 return super.getLastKey();
298 }
299
300 HFileScanner scanner = getScanner(true, true);
301 try {
302 if (scanner.seekBefore(this.splitkey)) {
303 return Bytes.toBytes(scanner.getKey());
304 }
305 } catch (IOException e) {
306 LOG.warn("Failed seekBefore " + Bytes.toStringBinary(this.splitkey), e);
307 }
308 return null;
309 }
310
311 @Override
312 public byte[] midkey() throws IOException {
313
314 return null;
315 }
316
317 @Override
318 public byte[] getFirstKey() {
319 if (!firstKeySeeked) {
320 HFileScanner scanner = getScanner(true, true, false);
321 try {
322 if (scanner.seekTo()) {
323 this.firstKey = Bytes.toBytes(scanner.getKey());
324 }
325 firstKeySeeked = true;
326 } catch (IOException e) {
327 LOG.warn("Failed seekTo first KV in the file", e);
328 }
329 }
330 return this.firstKey;
331 }
332 }