1   /**
2    * Copyright 2009 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.io.hfile;
21  
22  import java.io.IOException;
23  
24  import org.apache.hadoop.fs.FSDataOutputStream;
25  import org.apache.hadoop.fs.Path;
26  import org.apache.hadoop.hbase.HBaseTestCase;
27  import org.apache.hadoop.hbase.KeyValue;
28  import org.apache.hadoop.hbase.util.Bytes;
29  
30  /**
31   * Test {@link HFileScanner#seekTo(byte[])} and its variants.
32   */
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 =
49        HFile.getWriterFactory(conf).createWriter(fout,
50          blocksize, "none", null);
51      // 4 bytes * 3 * 2 for each key/value +
52      // 3 for keys, 15 for values = 42 (woot)
53      writer.append(toKV("c"));
54      writer.append(toKV("e"));
55      writer.append(toKV("g"));
56      // block transition
57      writer.append(toKV("i"));
58      writer.append(toKV("k"));
59      writer.close();
60      fout.close();
61      return ncTFile;
62    }
63  
64    public void testSeekBefore() throws Exception {
65      Path p = makeNewFile();
66      HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
67      reader.loadFileInfo();
68      HFileScanner scanner = reader.getScanner(false, true);
69      assertEquals(false, scanner.seekBefore(toKV("a").getKey()));
70  
71      assertEquals(false, scanner.seekBefore(toKV("c").getKey()));
72  
73      assertEquals(true, scanner.seekBefore(toKV("d").getKey()));
74      assertEquals("c", toRowStr(scanner.getKeyValue()));
75  
76      assertEquals(true, scanner.seekBefore(toKV("e").getKey()));
77      assertEquals("c", toRowStr(scanner.getKeyValue()));
78  
79      assertEquals(true, scanner.seekBefore(toKV("f").getKey()));
80      assertEquals("e", toRowStr(scanner.getKeyValue()));
81  
82      assertEquals(true, scanner.seekBefore(toKV("g").getKey()));
83      assertEquals("e", toRowStr(scanner.getKeyValue()));
84  
85      assertEquals(true, scanner.seekBefore(toKV("h").getKey()));
86      assertEquals("g", toRowStr(scanner.getKeyValue()));
87      assertEquals(true, scanner.seekBefore(toKV("i").getKey()));
88      assertEquals("g", toRowStr(scanner.getKeyValue()));
89      assertEquals(true, scanner.seekBefore(toKV("j").getKey()));
90      assertEquals("i", toRowStr(scanner.getKeyValue()));
91      assertEquals(true, scanner.seekBefore(toKV("k").getKey()));
92      assertEquals("i", toRowStr(scanner.getKeyValue()));
93      assertEquals(true, scanner.seekBefore(toKV("l").getKey()));
94      assertEquals("k", toRowStr(scanner.getKeyValue()));
95    }
96  
97    public void testSeekTo() throws Exception {
98      Path p = makeNewFile();
99      HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
100     reader.loadFileInfo();
101     assertEquals(2, reader.getDataBlockIndexReader().getRootBlockCount());
102     HFileScanner scanner = reader.getScanner(false, true);
103     // lies before the start of the file.
104     assertEquals(-1, scanner.seekTo(toKV("a").getKey()));
105 
106     assertEquals(1, scanner.seekTo(toKV("d").getKey()));
107     assertEquals("c", toRowStr(scanner.getKeyValue()));
108 
109     // Across a block boundary now.
110     assertEquals(1, scanner.seekTo(toKV("h").getKey()));
111     assertEquals("g", toRowStr(scanner.getKeyValue()));
112 
113     assertEquals(1, scanner.seekTo(toKV("l").getKey()));
114     assertEquals("k", toRowStr(scanner.getKeyValue()));
115   }
116 
117   public void testBlockContainingKey() throws Exception {
118     Path p = makeNewFile();
119     HFile.Reader reader = HFile.createReader(fs, p, new CacheConfig(conf));
120     reader.loadFileInfo();
121     HFileBlockIndex.BlockIndexReader blockIndexReader = 
122       reader.getDataBlockIndexReader();
123     System.out.println(blockIndexReader.toString());
124     int klen = toKV("a").getKey().length;
125     // falls before the start of the file.
126     assertEquals(-1, blockIndexReader.rootBlockContainingKey(
127         toKV("a").getKey(), 0, klen));
128     assertEquals(0, blockIndexReader.rootBlockContainingKey(
129         toKV("c").getKey(), 0, klen));
130     assertEquals(0, blockIndexReader.rootBlockContainingKey(
131         toKV("d").getKey(), 0, klen));
132     assertEquals(0, blockIndexReader.rootBlockContainingKey(
133         toKV("e").getKey(), 0, klen));
134     assertEquals(0, blockIndexReader.rootBlockContainingKey(
135         toKV("g").getKey(), 0, klen));
136     assertEquals(0, blockIndexReader.rootBlockContainingKey(
137         toKV("h").getKey(), 0, klen));
138     assertEquals(1, blockIndexReader.rootBlockContainingKey(
139         toKV("i").getKey(), 0, klen));
140     assertEquals(1, blockIndexReader.rootBlockContainingKey(
141         toKV("j").getKey(), 0, klen));
142     assertEquals(1, blockIndexReader.rootBlockContainingKey(
143         toKV("k").getKey(), 0, klen));
144     assertEquals(1, blockIndexReader.rootBlockContainingKey(
145         toKV("l").getKey(), 0, klen));
146  }
147 }