View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.io.hfile;
20  
21  import java.io.IOException;
22  
23  import org.apache.hadoop.fs.FSDataOutputStream;
24  import org.apache.hadoop.fs.Path;
25  import org.apache.hadoop.hbase.*;
26  import org.apache.hadoop.hbase.util.Bytes;
27  import org.junit.experimental.categories.Category;
28  
29  /**
30   * Test {@link HFileScanner#seekTo(byte[])} and its variants.
31   */
32  @Category(SmallTests.class)
33  public class TestSeekTo extends HBaseTestCase {
34  
35    static KeyValue toKV(String row) {
36      return new KeyValue(Bytes.toBytes(row), Bytes.toBytes("family"), Bytes
37          .toBytes("qualifier"), Bytes.toBytes("value"));
38    }
39  
40    static String toRowStr(KeyValue kv) {
41      return Bytes.toString(kv.getRow());
42    }
43  
44    Path makeNewFile() throws IOException {
45      Path ncTFile = new Path(this.testDir, "basic.hfile");
46      FSDataOutputStream fout = this.fs.create(ncTFile);
47      int blocksize = toKV("a").getLength() * 3;
48      HFile.Writer writer = HFile.getWriterFactoryNoCache(conf)
49          .withOutputStream(fout)
50          .withBlockSize(blocksize)
51          .create();
52      // 4 bytes * 3 * 2 for each key/value +
53      // 3 for keys, 15 for values = 42 (woot)
54      writer.append(toKV("c"));
55      writer.append(toKV("e"));
56      writer.append(toKV("g"));
57      // block transition
58      writer.append(toKV("i"));
59      writer.append(toKV("k"));
60      writer.close();
61      fout.close();
62      return ncTFile;
63    }
64  
65    public void testSeekBefore() throws Exception {
66      Path p = makeNewFile();
67      HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
68      reader.loadFileInfo();
69      HFileScanner scanner = reader.getScanner(false, true);
70      assertEquals(false, scanner.seekBefore(toKV("a").getKey()));
71  
72      assertEquals(false, scanner.seekBefore(toKV("c").getKey()));
73  
74      assertEquals(true, scanner.seekBefore(toKV("d").getKey()));
75      assertEquals("c", toRowStr(scanner.getKeyValue()));
76  
77      assertEquals(true, scanner.seekBefore(toKV("e").getKey()));
78      assertEquals("c", toRowStr(scanner.getKeyValue()));
79  
80      assertEquals(true, scanner.seekBefore(toKV("f").getKey()));
81      assertEquals("e", toRowStr(scanner.getKeyValue()));
82  
83      assertEquals(true, scanner.seekBefore(toKV("g").getKey()));
84      assertEquals("e", toRowStr(scanner.getKeyValue()));
85  
86      assertEquals(true, scanner.seekBefore(toKV("h").getKey()));
87      assertEquals("g", toRowStr(scanner.getKeyValue()));
88      assertEquals(true, scanner.seekBefore(toKV("i").getKey()));
89      assertEquals("g", toRowStr(scanner.getKeyValue()));
90      assertEquals(true, scanner.seekBefore(toKV("j").getKey()));
91      assertEquals("i", toRowStr(scanner.getKeyValue()));
92      assertEquals(true, scanner.seekBefore(toKV("k").getKey()));
93      assertEquals("i", toRowStr(scanner.getKeyValue()));
94      assertEquals(true, scanner.seekBefore(toKV("l").getKey()));
95      assertEquals("k", toRowStr(scanner.getKeyValue()));
96  
97      reader.close();
98    }
99  
100   public void testSeekBeforeWithReSeekTo() throws Exception {
101     Path p = makeNewFile();
102     HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
103     reader.loadFileInfo();
104     HFileScanner scanner = reader.getScanner(false, true);
105     assertEquals(false, scanner.seekBefore(toKV("a").getKey()));
106     assertEquals(false, scanner.seekBefore(toKV("b").getKey()));
107     assertEquals(false, scanner.seekBefore(toKV("c").getKey()));
108 
109     // seekBefore d, so the scanner points to c
110     assertEquals(true, scanner.seekBefore(toKV("d").getKey()));
111     assertEquals("c", toRowStr(scanner.getKeyValue()));
112     // reseekTo e and g
113     assertEquals(0, scanner.reseekTo(toKV("c").getKey()));
114     assertEquals("c", toRowStr(scanner.getKeyValue()));
115     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
116     assertEquals("g", toRowStr(scanner.getKeyValue()));
117 
118     // seekBefore e, so the scanner points to c
119     assertEquals(true, scanner.seekBefore(toKV("e").getKey()));
120     assertEquals("c", toRowStr(scanner.getKeyValue()));
121     // reseekTo e and g
122     assertEquals(0, scanner.reseekTo(toKV("e").getKey()));
123     assertEquals("e", toRowStr(scanner.getKeyValue()));
124     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
125     assertEquals("g", toRowStr(scanner.getKeyValue()));
126 
127     // seekBefore f, so the scanner points to e
128     assertEquals(true, scanner.seekBefore(toKV("f").getKey()));
129     assertEquals("e", toRowStr(scanner.getKeyValue()));
130     // reseekTo e and g
131     assertEquals(0, scanner.reseekTo(toKV("e").getKey()));
132     assertEquals("e", toRowStr(scanner.getKeyValue()));
133     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
134     assertEquals("g", toRowStr(scanner.getKeyValue()));
135 
136     // seekBefore g, so the scanner points to e
137     assertEquals(true, scanner.seekBefore(toKV("g").getKey()));
138     assertEquals("e", toRowStr(scanner.getKeyValue()));
139     // reseekTo e and g again
140     assertEquals(0, scanner.reseekTo(toKV("e").getKey()));
141     assertEquals("e", toRowStr(scanner.getKeyValue()));
142     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
143     assertEquals("g", toRowStr(scanner.getKeyValue()));
144 
145     // seekBefore h, so the scanner points to g
146     assertEquals(true, scanner.seekBefore(toKV("h").getKey()));
147     assertEquals("g", toRowStr(scanner.getKeyValue()));
148     // reseekTo g
149     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
150     assertEquals("g", toRowStr(scanner.getKeyValue()));
151 
152     // seekBefore i, so the scanner points to g
153     assertEquals(true, scanner.seekBefore(toKV("i").getKey()));
154     assertEquals("g", toRowStr(scanner.getKeyValue()));
155     // reseekTo g
156     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
157     assertEquals("g", toRowStr(scanner.getKeyValue()));
158 
159     // seekBefore j, so the scanner points to i
160     assertEquals(true, scanner.seekBefore(toKV("j").getKey()));
161     assertEquals("i", toRowStr(scanner.getKeyValue()));
162     // reseekTo i
163     assertEquals(0, scanner.reseekTo(toKV("i").getKey()));
164     assertEquals("i", toRowStr(scanner.getKeyValue()));
165 
166     // seekBefore k, so the scanner points to i
167     assertEquals(true, scanner.seekBefore(toKV("k").getKey()));
168     assertEquals("i", toRowStr(scanner.getKeyValue()));
169     // reseekTo i and k
170     assertEquals(0, scanner.reseekTo(toKV("i").getKey()));
171     assertEquals("i", toRowStr(scanner.getKeyValue()));
172     assertEquals(0, scanner.reseekTo(toKV("k").getKey()));
173     assertEquals("k", toRowStr(scanner.getKeyValue()));
174 
175     // seekBefore l, so the scanner points to k
176     assertEquals(true, scanner.seekBefore(toKV("l").getKey()));
177     assertEquals("k", toRowStr(scanner.getKeyValue()));
178     // reseekTo k
179     assertEquals(0, scanner.reseekTo(toKV("k").getKey()));
180     assertEquals("k", toRowStr(scanner.getKeyValue()));
181   }
182 
183   public void testSeekTo() throws Exception {
184     Path p = makeNewFile();
185     HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
186     reader.loadFileInfo();
187     assertEquals(2, reader.getDataBlockIndexReader().getRootBlockCount());
188     HFileScanner scanner = reader.getScanner(false, true);
189     // lies before the start of the file.
190     assertEquals(-1, scanner.seekTo(toKV("a").getKey()));
191 
192     assertEquals(1, scanner.seekTo(toKV("d").getKey()));
193     assertEquals("c", toRowStr(scanner.getKeyValue()));
194 
195     // Across a block boundary now.
196     assertEquals(1, scanner.seekTo(toKV("h").getKey()));
197     assertEquals("g", toRowStr(scanner.getKeyValue()));
198 
199     assertEquals(1, scanner.seekTo(toKV("l").getKey()));
200     assertEquals("k", toRowStr(scanner.getKeyValue()));
201 
202     reader.close();
203   }
204 
205   public void testBlockContainingKey() throws Exception {
206     Path p = makeNewFile();
207     HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
208     reader.loadFileInfo();
209     HFileBlockIndex.BlockIndexReader blockIndexReader = 
210       reader.getDataBlockIndexReader();
211     System.out.println(blockIndexReader.toString());
212     int klen = toKV("a").getKey().length;
213     // falls before the start of the file.
214     assertEquals(-1, blockIndexReader.rootBlockContainingKey(
215         toKV("a").getKey(), 0, klen));
216     assertEquals(0, blockIndexReader.rootBlockContainingKey(
217         toKV("c").getKey(), 0, klen));
218     assertEquals(0, blockIndexReader.rootBlockContainingKey(
219         toKV("d").getKey(), 0, klen));
220     assertEquals(0, blockIndexReader.rootBlockContainingKey(
221         toKV("e").getKey(), 0, klen));
222     assertEquals(0, blockIndexReader.rootBlockContainingKey(
223         toKV("g").getKey(), 0, klen));
224     assertEquals(0, blockIndexReader.rootBlockContainingKey(
225         toKV("h").getKey(), 0, klen));
226     assertEquals(1, blockIndexReader.rootBlockContainingKey(
227         toKV("i").getKey(), 0, klen));
228     assertEquals(1, blockIndexReader.rootBlockContainingKey(
229         toKV("j").getKey(), 0, klen));
230     assertEquals(1, blockIndexReader.rootBlockContainingKey(
231         toKV("k").getKey(), 0, klen));
232     assertEquals(1, blockIndexReader.rootBlockContainingKey(
233         toKV("l").getKey(), 0, klen));
234 
235     reader.close();
236  }
237 
238 }
239