View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.io.encoding;
19  
20  import static org.junit.Assert.assertEquals;
21  
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.List;
25  
26  import org.apache.hadoop.fs.Path;
27  import org.apache.hadoop.hbase.Cell;
28  import org.apache.hadoop.hbase.HBaseTestingUtility;
29  import org.apache.hadoop.hbase.HColumnDescriptor;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.HRegionInfo;
32  import org.apache.hadoop.hbase.HTableDescriptor;
33  import org.apache.hadoop.hbase.TableName;
34  import org.apache.hadoop.hbase.client.Put;
35  import org.apache.hadoop.hbase.client.Scan;
36  import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
37  import org.apache.hadoop.hbase.regionserver.Region;
38  import org.apache.hadoop.hbase.regionserver.RegionScanner;
39  import org.apache.hadoop.hbase.testclassification.SmallTests;
40  import org.apache.hadoop.hbase.util.Bytes;
41  import org.junit.After;
42  import org.junit.Before;
43  import org.junit.Test;
44  import org.junit.experimental.categories.Category;
45  
46  @Category({ SmallTests.class })
47  public class TestSeekBeforeWithReverseScan {
48    private final HBaseTestingUtility testUtil = new HBaseTestingUtility();
49  
50    private Region region;
51  
52    private byte[] cfName = Bytes.toBytes("a");
53    private byte[] cqName = Bytes.toBytes("b");
54  
55    @Before
56    public void setUp() throws Exception {
57      TableName tableName = TableName.valueOf(getClass().getSimpleName());
58      HTableDescriptor htd = new HTableDescriptor(tableName);
59      htd.addFamily(new HColumnDescriptor(cfName).setDataBlockEncoding(DataBlockEncoding.FAST_DIFF));
60      HRegionInfo info = new HRegionInfo(tableName, null, null, false);
61      Path path = testUtil.getDataTestDir(getClass().getSimpleName());
62      region = HBaseTestingUtility.createRegionAndWAL(info, path, path, testUtil.getConfiguration(), htd);
63    }
64  
65    @After
66    public void tearDown() throws Exception {
67      HBaseTestingUtility.closeRegionAndWAL(region);
68      testUtil.cleanupTestDir();
69    }
70  
71    @Test
72    public void testReverseScanWithoutPadding() throws Exception {
73      byte[] row1 = Bytes.toBytes("a");
74      byte[] row2 = Bytes.toBytes("ab");
75      byte[] row3 = Bytes.toBytes("b");
76  
77      Put put1 = new Put(row1);
78      put1.addColumn(cfName, cqName, HConstants.EMPTY_BYTE_ARRAY);
79      Put put2 = new Put(row2);
80      put2.addColumn(cfName, cqName, HConstants.EMPTY_BYTE_ARRAY);
81      Put put3 = new Put(row3);
82      put3.addColumn(cfName, cqName, HConstants.EMPTY_BYTE_ARRAY);
83  
84      region.put(put1);
85      region.put(put2);
86      region.put(put3);
87      region.flush(true);
88      Scan scan = new Scan();
89      scan.setCacheBlocks(false);
90      scan.setReversed(true);
91      scan.setFilter(new FirstKeyOnlyFilter());
92      scan.addFamily(cfName);
93      RegionScanner scanner = region.getScanner(scan);
94      List<Cell> res = new ArrayList<Cell>();
95      int count = 1;
96      while (scanner.next(res)) {
97        count++;
98      }
99      assertEquals(Bytes.toString(res.get(0).getRowArray(), res.get(0).getRowOffset(), res.get(0)
100         .getRowLength()), "b");
101     assertEquals(Bytes.toString(res.get(1).getRowArray(), res.get(1).getRowOffset(), res.get(1)
102         .getRowLength()), "ab");
103     assertEquals(Bytes.toString(res.get(2).getRowArray(), res.get(2).getRowOffset(), res.get(2)
104         .getRowLength()), "a");
105     assertEquals(3, count);
106   }
107 
108   @Test
109   public void testReverseScanWithPadding() throws Exception {
110     byte[] terminator = new byte[] { -1 };
111     byte[] row1 = Bytes.add(invert(Bytes.toBytes("a")), terminator);
112     byte[] row2 = Bytes.add(invert(Bytes.toBytes("ab")), terminator);
113     byte[] row3 = Bytes.add(invert(Bytes.toBytes("b")), terminator);
114 
115     Put put1 = new Put(row1);
116     put1.addColumn(cfName, cqName, HConstants.EMPTY_BYTE_ARRAY);
117     Put put2 = new Put(row2);
118     put2.addColumn(cfName, cqName, HConstants.EMPTY_BYTE_ARRAY);
119     Put put3 = new Put(row3);
120     put3.addColumn(cfName, cqName, HConstants.EMPTY_BYTE_ARRAY);
121 
122     region.put(put1);
123     region.put(put2);
124     region.put(put3);
125     region.flush(true);
126     Scan scan = new Scan();
127     scan.setCacheBlocks(false);
128     scan.setReversed(true);
129     scan.setFilter(new FirstKeyOnlyFilter());
130     scan.addFamily(cfName);
131     RegionScanner scanner = region.getScanner(scan);
132     List<Cell> res = new ArrayList<Cell>();
133     int count = 1;
134     while (scanner.next(res)) {
135       count++;
136     }
137     assertEquals(3, count);
138   }
139 
140   private byte[] invert(byte[] bytes) {
141     byte[] newBytes = Arrays.copyOf(bytes, bytes.length);
142     for (int i = 0; i < newBytes.length; i++) {
143       newBytes[i] = (byte) (newBytes[i] ^ 0xFF);
144     }
145     return newBytes;
146   }
147 }