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  
20  package org.apache.hadoop.hbase.filter;
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.hadoop.hbase.Cell;
26  import org.apache.hadoop.hbase.HBaseTestingUtility;
27  import org.apache.hadoop.hbase.HColumnDescriptor;
28  import org.apache.hadoop.hbase.HRegionInfo;
29  import org.apache.hadoop.hbase.HTableDescriptor;
30  import org.apache.hadoop.hbase.KeyValue;
31  import org.apache.hadoop.hbase.TableName;
32  import org.apache.hadoop.hbase.client.Get;
33  import org.apache.hadoop.hbase.client.Put;
34  import org.apache.hadoop.hbase.client.Scan;
35  import org.apache.hadoop.hbase.regionserver.HRegion;
36  import org.apache.hadoop.hbase.regionserver.InternalScanner;
37  import org.apache.hadoop.hbase.regionserver.wal.HLog;
38  import org.apache.hadoop.hbase.testclassification.SmallTests;
39  import org.apache.hadoop.hbase.util.Bytes;
40  import org.junit.After;
41  import org.junit.Assert;
42  import org.junit.Before;
43  import org.junit.Test;
44  import org.junit.experimental.categories.Category;
45  
46  /**
47   * Test the invocation logic of the filters. A filter must be invoked only for
48   * the columns that are requested for.
49   */
50  @Category(SmallTests.class)
51  public class TestInvocationRecordFilter {
52  
53    private static final byte[] TABLE_NAME_BYTES = Bytes
54        .toBytes("invocationrecord");
55    private static final byte[] FAMILY_NAME_BYTES = Bytes.toBytes("mycf");
56  
57    private static final byte[] ROW_BYTES = Bytes.toBytes("row");
58    private static final String QUALIFIER_PREFIX = "qualifier";
59    private static final String VALUE_PREFIX = "value";
60  
61    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
62    private HRegion region;
63  
64    @Before
65    public void setUp() throws Exception {
66      HTableDescriptor htd = new HTableDescriptor(
67          TableName.valueOf(TABLE_NAME_BYTES));
68      htd.addFamily(new HColumnDescriptor(FAMILY_NAME_BYTES));
69      HRegionInfo info = new HRegionInfo(htd.getTableName(), null, null, false);
70      this.region = HRegion.createHRegion(info, TEST_UTIL.getDataTestDir(),
71          TEST_UTIL.getConfiguration(), htd);
72  
73      Put put = new Put(ROW_BYTES);
74      for (int i = 0; i < 10; i += 2) {
75        // puts 0, 2, 4, 6 and 8
76        put.add(FAMILY_NAME_BYTES, Bytes.toBytes(QUALIFIER_PREFIX + i), i,
77            Bytes.toBytes(VALUE_PREFIX + i));
78      }
79      this.region.put(put);
80      this.region.flushcache();
81    }
82  
83    @Test
84    public void testFilterInvocation() throws Exception {
85      List<Integer> selectQualifiers = new ArrayList<Integer>();
86      List<Integer> expectedQualifiers = new ArrayList<Integer>();
87  
88      selectQualifiers.add(-1);
89      verifyInvocationResults(selectQualifiers.toArray(new Integer[selectQualifiers.size()]),
90          expectedQualifiers.toArray(new Integer[expectedQualifiers.size()]));
91  
92      selectQualifiers.clear();
93  
94      selectQualifiers.add(0);
95      expectedQualifiers.add(0);
96      verifyInvocationResults(selectQualifiers.toArray(new Integer[selectQualifiers.size()]),
97          expectedQualifiers.toArray(new Integer[expectedQualifiers.size()]));
98  
99      selectQualifiers.add(3);
100     verifyInvocationResults(selectQualifiers.toArray(new Integer[selectQualifiers.size()]),
101         expectedQualifiers.toArray(new Integer[expectedQualifiers.size()]));
102 
103     selectQualifiers.add(4);
104     expectedQualifiers.add(4);
105     verifyInvocationResults(selectQualifiers.toArray(new Integer[selectQualifiers.size()]),
106         expectedQualifiers.toArray(new Integer[expectedQualifiers.size()]));
107 
108     selectQualifiers.add(5);
109     verifyInvocationResults(selectQualifiers.toArray(new Integer[selectQualifiers.size()]),
110         expectedQualifiers.toArray(new Integer[expectedQualifiers.size()]));
111 
112     selectQualifiers.add(8);
113     expectedQualifiers.add(8);
114     verifyInvocationResults(selectQualifiers.toArray(new Integer[selectQualifiers.size()]),
115         expectedQualifiers.toArray(new Integer[expectedQualifiers.size()]));
116   }
117 
118   public void verifyInvocationResults(Integer[] selectQualifiers,
119       Integer[] expectedQualifiers) throws Exception {
120     Get get = new Get(ROW_BYTES);
121     for (int i = 0; i < selectQualifiers.length; i++) {
122       get.addColumn(FAMILY_NAME_BYTES,
123           Bytes.toBytes(QUALIFIER_PREFIX + selectQualifiers[i]));
124     }
125 
126     get.setFilter(new InvocationRecordFilter());
127 
128     List<KeyValue> expectedValues = new ArrayList<KeyValue>();
129     for (int i = 0; i < expectedQualifiers.length; i++) {
130       expectedValues.add(new KeyValue(ROW_BYTES, FAMILY_NAME_BYTES, Bytes
131           .toBytes(QUALIFIER_PREFIX + expectedQualifiers[i]),
132           expectedQualifiers[i], Bytes.toBytes(VALUE_PREFIX
133               + expectedQualifiers[i])));
134     }
135 
136     Scan scan = new Scan(get);
137     List<Cell> actualValues = new ArrayList<Cell>();
138     List<Cell> temp = new ArrayList<Cell>();
139     InternalScanner scanner = this.region.getScanner(scan);
140     while (scanner.next(temp)) {
141       actualValues.addAll(temp);
142       temp.clear();
143     }
144     actualValues.addAll(temp);
145     Assert.assertTrue("Actual values " + actualValues
146         + " differ from the expected values:" + expectedValues,
147         expectedValues.equals(actualValues));
148   }
149 
150   @After
151   public void tearDown() throws Exception {
152     HLog hlog = region.getLog();
153     region.close();
154     hlog.closeAndDelete();
155   }
156 
157   /**
158    * Filter which gives the list of keyvalues for which the filter is invoked.
159    */
160   private static class InvocationRecordFilter extends FilterBase {
161 
162     private List<Cell> visitedKeyValues = new ArrayList<Cell>();
163 
164     public void reset() {
165       visitedKeyValues.clear();
166     }
167 
168     public ReturnCode filterKeyValue(Cell ignored) {
169       visitedKeyValues.add(ignored);
170       return ReturnCode.INCLUDE;
171     }
172 
173     public void filterRowCells(List<Cell> kvs) {
174       kvs.clear();
175       kvs.addAll(visitedKeyValues);
176     }
177 
178     public boolean hasFilterRow() {
179       return true;
180     }
181   }
182 }