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.apache.hadoop.io.RawComparator;
28  import org.junit.experimental.categories.Category;
29  
30  /**
31   * Test {@link HFileScanner#seekTo(byte[])} and its variants.
32   */
33  @Category(SmallTests.class)
34  public class TestSeekTo extends HBaseTestCase {
35  
36    static KeyValue toKV(String row) {
37      return new KeyValue(Bytes.toBytes(row), Bytes.toBytes("family"), Bytes
38          .toBytes("qualifier"), Bytes.toBytes("value"));
39    }
40  
41    static String toRowStr(KeyValue kv) {
42      return Bytes.toString(kv.getRow());
43    }
44  
45    Path makeNewFile() throws IOException {
46      Path ncTFile = new Path(this.testDir, "basic.hfile");
47      FSDataOutputStream fout = this.fs.create(ncTFile);
48      int blocksize = toKV("a").getLength() * 3;
49      HFile.Writer writer = HFile.getWriterFactoryNoCache(conf)
50          .withOutputStream(fout)
51          .withBlockSize(blocksize)
52          // NOTE: This test is dependent on this deprecated nonstandard comparator
53          .withComparator(KeyValue.RAW_COMPARATOR)
54          .create();
55      // 4 bytes * 3 * 2 for each key/value +
56      // 3 for keys, 15 for values = 42 (woot)
57      writer.append(toKV("c"));
58      writer.append(toKV("e"));
59      writer.append(toKV("g"));
60      // block transition
61      writer.append(toKV("i"));
62      writer.append(toKV("k"));
63      writer.close();
64      fout.close();
65      return ncTFile;
66    }
67  
68    public void testSeekBefore() throws Exception {
69      Path p = makeNewFile();
70      HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
71      reader.loadFileInfo();
72      HFileScanner scanner = reader.getScanner(false, true);
73      assertEquals(false, scanner.seekBefore(toKV("a").getKey()));
74  
75      assertEquals(false, scanner.seekBefore(toKV("c").getKey()));
76  
77      assertEquals(true, scanner.seekBefore(toKV("d").getKey()));
78      assertEquals("c", toRowStr(scanner.getKeyValue()));
79  
80      assertEquals(true, scanner.seekBefore(toKV("e").getKey()));
81      assertEquals("c", toRowStr(scanner.getKeyValue()));
82  
83      assertEquals(true, scanner.seekBefore(toKV("f").getKey()));
84      assertEquals("e", toRowStr(scanner.getKeyValue()));
85  
86      assertEquals(true, scanner.seekBefore(toKV("g").getKey()));
87      assertEquals("e", toRowStr(scanner.getKeyValue()));
88  
89      assertEquals(true, scanner.seekBefore(toKV("h").getKey()));
90      assertEquals("g", toRowStr(scanner.getKeyValue()));
91      assertEquals(true, scanner.seekBefore(toKV("i").getKey()));
92      assertEquals("g", toRowStr(scanner.getKeyValue()));
93      assertEquals(true, scanner.seekBefore(toKV("j").getKey()));
94      assertEquals("i", toRowStr(scanner.getKeyValue()));
95      assertEquals(true, scanner.seekBefore(toKV("k").getKey()));
96      assertEquals("i", toRowStr(scanner.getKeyValue()));
97      assertEquals(true, scanner.seekBefore(toKV("l").getKey()));
98      assertEquals("k", toRowStr(scanner.getKeyValue()));
99  
100     reader.close();
101   }
102 
103   public void testSeekBeforeWithReSeekTo() throws Exception {
104     Path p = makeNewFile();
105     HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
106     reader.loadFileInfo();
107     HFileScanner scanner = reader.getScanner(false, true);
108     assertEquals(false, scanner.seekBefore(toKV("a").getKey()));
109     assertEquals(false, scanner.seekBefore(toKV("b").getKey()));
110     assertEquals(false, scanner.seekBefore(toKV("c").getKey()));
111 
112     // seekBefore d, so the scanner points to c
113     assertEquals(true, scanner.seekBefore(toKV("d").getKey()));
114     assertEquals("c", toRowStr(scanner.getKeyValue()));
115     // reseekTo e and g
116     assertEquals(0, scanner.reseekTo(toKV("c").getKey()));
117     assertEquals("c", toRowStr(scanner.getKeyValue()));
118     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
119     assertEquals("g", toRowStr(scanner.getKeyValue()));
120 
121     // seekBefore e, so the scanner points to c
122     assertEquals(true, scanner.seekBefore(toKV("e").getKey()));
123     assertEquals("c", toRowStr(scanner.getKeyValue()));
124     // reseekTo e and g
125     assertEquals(0, scanner.reseekTo(toKV("e").getKey()));
126     assertEquals("e", toRowStr(scanner.getKeyValue()));
127     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
128     assertEquals("g", toRowStr(scanner.getKeyValue()));
129 
130     // seekBefore f, so the scanner points to e
131     assertEquals(true, scanner.seekBefore(toKV("f").getKey()));
132     assertEquals("e", toRowStr(scanner.getKeyValue()));
133     // reseekTo e and g
134     assertEquals(0, scanner.reseekTo(toKV("e").getKey()));
135     assertEquals("e", toRowStr(scanner.getKeyValue()));
136     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
137     assertEquals("g", toRowStr(scanner.getKeyValue()));
138 
139     // seekBefore g, so the scanner points to e
140     assertEquals(true, scanner.seekBefore(toKV("g").getKey()));
141     assertEquals("e", toRowStr(scanner.getKeyValue()));
142     // reseekTo e and g again
143     assertEquals(0, scanner.reseekTo(toKV("e").getKey()));
144     assertEquals("e", toRowStr(scanner.getKeyValue()));
145     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
146     assertEquals("g", toRowStr(scanner.getKeyValue()));
147 
148     // seekBefore h, so the scanner points to g
149     assertEquals(true, scanner.seekBefore(toKV("h").getKey()));
150     assertEquals("g", toRowStr(scanner.getKeyValue()));
151     // reseekTo g
152     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
153     assertEquals("g", toRowStr(scanner.getKeyValue()));
154 
155     // seekBefore i, so the scanner points to g
156     assertEquals(true, scanner.seekBefore(toKV("i").getKey()));
157     assertEquals("g", toRowStr(scanner.getKeyValue()));
158     // reseekTo g
159     assertEquals(0, scanner.reseekTo(toKV("g").getKey()));
160     assertEquals("g", toRowStr(scanner.getKeyValue()));
161 
162     // seekBefore j, so the scanner points to i
163     assertEquals(true, scanner.seekBefore(toKV("j").getKey()));
164     assertEquals("i", toRowStr(scanner.getKeyValue()));
165     // reseekTo i
166     assertEquals(0, scanner.reseekTo(toKV("i").getKey()));
167     assertEquals("i", toRowStr(scanner.getKeyValue()));
168 
169     // seekBefore k, so the scanner points to i
170     assertEquals(true, scanner.seekBefore(toKV("k").getKey()));
171     assertEquals("i", toRowStr(scanner.getKeyValue()));
172     // reseekTo i and k
173     assertEquals(0, scanner.reseekTo(toKV("i").getKey()));
174     assertEquals("i", toRowStr(scanner.getKeyValue()));
175     assertEquals(0, scanner.reseekTo(toKV("k").getKey()));
176     assertEquals("k", toRowStr(scanner.getKeyValue()));
177 
178     // seekBefore l, so the scanner points to k
179     assertEquals(true, scanner.seekBefore(toKV("l").getKey()));
180     assertEquals("k", toRowStr(scanner.getKeyValue()));
181     // reseekTo k
182     assertEquals(0, scanner.reseekTo(toKV("k").getKey()));
183     assertEquals("k", toRowStr(scanner.getKeyValue()));
184   }
185 
186   public void testSeekTo() throws Exception {
187     Path p = makeNewFile();
188     HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
189     reader.loadFileInfo();
190     assertEquals(2, reader.getDataBlockIndexReader().getRootBlockCount());
191     HFileScanner scanner = reader.getScanner(false, true);
192     // lies before the start of the file.
193     assertEquals(-1, scanner.seekTo(toKV("a").getKey()));
194 
195     assertEquals(1, scanner.seekTo(toKV("d").getKey()));
196     assertEquals("c", toRowStr(scanner.getKeyValue()));
197 
198     // Across a block boundary now.
199     assertEquals(1, scanner.seekTo(toKV("h").getKey()));
200     assertEquals("g", toRowStr(scanner.getKeyValue()));
201 
202     assertEquals(1, scanner.seekTo(toKV("l").getKey()));
203     assertEquals("k", toRowStr(scanner.getKeyValue()));
204 
205     reader.close();
206   }
207 
208   public void testBlockContainingKey() throws Exception {
209     Path p = makeNewFile();
210     HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
211     reader.loadFileInfo();
212     HFileBlockIndex.BlockIndexReader blockIndexReader = 
213       reader.getDataBlockIndexReader();
214     System.out.println(blockIndexReader.toString());
215     int klen = toKV("a").getKey().length;
216     // falls before the start of the file.
217     assertEquals(-1, blockIndexReader.rootBlockContainingKey(
218         toKV("a").getKey(), 0, klen));
219     assertEquals(0, blockIndexReader.rootBlockContainingKey(
220         toKV("c").getKey(), 0, klen));
221     assertEquals(0, blockIndexReader.rootBlockContainingKey(
222         toKV("d").getKey(), 0, klen));
223     assertEquals(0, blockIndexReader.rootBlockContainingKey(
224         toKV("e").getKey(), 0, klen));
225     assertEquals(0, blockIndexReader.rootBlockContainingKey(
226         toKV("g").getKey(), 0, klen));
227     assertEquals(0, blockIndexReader.rootBlockContainingKey(
228         toKV("h").getKey(), 0, klen));
229     assertEquals(1, blockIndexReader.rootBlockContainingKey(
230         toKV("i").getKey(), 0, klen));
231     assertEquals(1, blockIndexReader.rootBlockContainingKey(
232         toKV("j").getKey(), 0, klen));
233     assertEquals(1, blockIndexReader.rootBlockContainingKey(
234         toKV("k").getKey(), 0, klen));
235     assertEquals(1, blockIndexReader.rootBlockContainingKey(
236         toKV("l").getKey(), 0, klen));
237 
238     reader.close();
239  }
240 
241 }
242