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