View Javadoc

1   /*
2    * Copyright 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.regionserver;
21  
22  import static junit.framework.Assert.assertEquals;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import org.apache.hadoop.hbase.HBaseTestingUtility;
30  import org.apache.hadoop.hbase.HColumnDescriptor;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  import org.apache.hadoop.hbase.testclassification.MediumTests;
33  import org.apache.hadoop.hbase.TableExistsException;
34  import org.apache.hadoop.hbase.TableName;
35  import org.apache.hadoop.hbase.TableNotFoundException;
36  import org.apache.hadoop.hbase.client.Admin;
37  import org.apache.hadoop.hbase.client.Durability;
38  import org.apache.hadoop.hbase.client.HTable;
39  import org.apache.hadoop.hbase.client.Put;
40  import org.apache.hadoop.hbase.client.Result;
41  import org.apache.hadoop.hbase.client.ResultScanner;
42  import org.apache.hadoop.hbase.client.Scan;
43  import org.apache.hadoop.hbase.client.Table;
44  import org.apache.hadoop.hbase.filter.BinaryComparator;
45  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
46  import org.apache.hadoop.hbase.filter.Filter;
47  import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
48  import org.apache.hadoop.hbase.io.compress.Compression.Algorithm;
49  import org.apache.hadoop.hbase.util.Bytes;
50  import org.junit.AfterClass;
51  import org.junit.BeforeClass;
52  import org.junit.Test;
53  import org.junit.experimental.categories.Category;
54  
55  @Category(MediumTests.class)
56  /*
57   * This test verifies that the scenarios illustrated by HBASE-10850 work
58   * w.r.t. essential column family optimization
59   */
60  public class TestSCVFWithMiniCluster {
61    private static final TableName HBASE_TABLE_NAME = TableName.valueOf("TestSCVFWithMiniCluster");
62  
63    private static final byte[] FAMILY_A = Bytes.toBytes("a");
64    private static final byte[] FAMILY_B = Bytes.toBytes("b");
65  
66    private static final byte[] QUALIFIER_FOO = Bytes.toBytes("foo");
67    private static final byte[] QUALIFIER_BAR = Bytes.toBytes("bar");
68  
69    private static Table htable;
70  
71    private static Filter scanFilter;
72  
73    private int expected = 1;
74  
75    @BeforeClass
76    public static void setUp() throws Exception {
77      HBaseTestingUtility util = new HBaseTestingUtility();
78  
79      util.startMiniCluster(1);
80  
81      Admin admin = util.getHBaseAdmin();
82      destroy(admin, HBASE_TABLE_NAME);
83      create(admin, HBASE_TABLE_NAME, FAMILY_A, FAMILY_B);
84      admin.close();
85      htable = new HTable(util.getConfiguration(), HBASE_TABLE_NAME);
86  
87      /* Add some values */
88      List<Put> puts = new ArrayList<Put>();
89  
90      /* Add a row with 'a:foo' = false */
91      Put put = new Put(Bytes.toBytes("1"));
92      put.setDurability(Durability.SKIP_WAL);
93      put.add(FAMILY_A, QUALIFIER_FOO, Bytes.toBytes("false"));
94      put.add(FAMILY_A, QUALIFIER_BAR, Bytes.toBytes("_flag_"));
95      put.add(FAMILY_B, QUALIFIER_FOO, Bytes.toBytes("_flag_"));
96      put.add(FAMILY_B, QUALIFIER_BAR, Bytes.toBytes("_flag_"));
97      puts.add(put);
98  
99      /* Add a row with 'a:foo' = true */
100     put = new Put(Bytes.toBytes("2"));
101     put.setDurability(Durability.SKIP_WAL);
102     put.add(FAMILY_A, QUALIFIER_FOO, Bytes.toBytes("true"));
103     put.add(FAMILY_A, QUALIFIER_BAR, Bytes.toBytes("_flag_"));
104     put.add(FAMILY_B, QUALIFIER_FOO, Bytes.toBytes("_flag_"));
105     put.add(FAMILY_B, QUALIFIER_BAR, Bytes.toBytes("_flag_"));
106     puts.add(put);
107 
108     /* Add a row with 'a:foo' qualifier not set */
109     put = new Put(Bytes.toBytes("3"));
110     put.setDurability(Durability.SKIP_WAL);
111     put.add(FAMILY_A, QUALIFIER_BAR, Bytes.toBytes("_flag_"));
112     put.add(FAMILY_B, QUALIFIER_FOO, Bytes.toBytes("_flag_"));
113     put.add(FAMILY_B, QUALIFIER_BAR, Bytes.toBytes("_flag_"));
114     puts.add(put);
115 
116     htable.put(puts);
117     /*
118      * We want to filter out from the scan all rows that do not have the column 'a:foo' with value
119      * 'false'. Only row with key '1' should be returned in the scan.
120      */
121     scanFilter = new SingleColumnValueFilter(FAMILY_A, QUALIFIER_FOO, CompareOp.EQUAL,
122       new BinaryComparator(Bytes.toBytes("false")));
123     ((SingleColumnValueFilter) scanFilter).setFilterIfMissing(true);
124   }
125   
126   @AfterClass
127   public static void tearDown() throws Exception {
128     htable.close();
129   }
130 
131   private void verify(Scan scan) throws IOException {
132     ResultScanner scanner = htable.getScanner(scan);
133     Iterator<Result> it = scanner.iterator();
134 
135     /* Then */
136     int count = 0;
137     try {
138       while (it.hasNext()) {
139         it.next();
140         count++;
141       }
142     } finally {
143       scanner.close();
144     }
145     assertEquals(expected, count);
146   }
147   /**
148    * Test the filter by adding all columns of family A in the scan. (OK)
149    */
150   @Test
151   public void scanWithAllQualifiersOfFamiliyA() throws IOException {
152     /* Given */
153     Scan scan = new Scan();
154     scan.addFamily(FAMILY_A);
155     scan.setFilter(scanFilter);
156 
157     verify(scan);
158   }
159 
160   /**
161    * Test the filter by adding all columns of family A and B in the scan. (KO: row '3' without
162    * 'a:foo' qualifier is returned)
163    */
164   @Test
165   public void scanWithAllQualifiersOfBothFamilies() throws IOException {
166     /* When */
167     Scan scan = new Scan();
168     scan.setFilter(scanFilter);
169 
170     verify(scan);
171   }
172 
173   /**
174    * Test the filter by adding 2 columns of family A and 1 column of family B in the scan. (KO: row
175    * '3' without 'a:foo' qualifier is returned)
176    */
177   @Test
178   public void scanWithSpecificQualifiers1() throws IOException {
179     /* When */
180     Scan scan = new Scan();
181     scan.addColumn(FAMILY_A, QUALIFIER_FOO);
182     scan.addColumn(FAMILY_A, QUALIFIER_BAR);
183     scan.addColumn(FAMILY_B, QUALIFIER_BAR);
184     scan.addColumn(FAMILY_B, QUALIFIER_FOO);
185     scan.setFilter(scanFilter);
186 
187     verify(scan);
188   }
189 
190   /**
191    * Test the filter by adding 1 column of family A (the one used in the filter) and 1 column of
192    * family B in the scan. (OK)
193    */
194   @Test
195   public void scanWithSpecificQualifiers2() throws IOException {
196     /* When */
197     Scan scan = new Scan();
198     scan.addColumn(FAMILY_A, QUALIFIER_FOO);
199     scan.addColumn(FAMILY_B, QUALIFIER_BAR);
200     scan.setFilter(scanFilter);
201 
202     verify(scan);
203   }
204 
205   /**
206    * Test the filter by adding 2 columns of family A in the scan. (OK)
207    */
208   @Test
209   public void scanWithSpecificQualifiers3() throws IOException {
210     /* When */
211     Scan scan = new Scan();
212     scan.addColumn(FAMILY_A, QUALIFIER_FOO);
213     scan.addColumn(FAMILY_A, QUALIFIER_BAR);
214     scan.setFilter(scanFilter);
215 
216     verify(scan);
217   }
218 
219   private static void create(Admin admin, TableName tableName, byte[]... families)
220       throws IOException {
221     HTableDescriptor desc = new HTableDescriptor(tableName);
222     for (byte[] family : families) {
223       HColumnDescriptor colDesc = new HColumnDescriptor(family);
224       colDesc.setMaxVersions(1);
225       colDesc.setCompressionType(Algorithm.GZ);
226       desc.addFamily(colDesc);
227     }
228     try {
229       admin.createTable(desc);
230     } catch (TableExistsException tee) {
231       /* Ignore */
232     }
233   }
234 
235   private static void destroy(Admin admin, TableName tableName) throws IOException {
236     try {
237       admin.disableTable(tableName);
238       admin.deleteTable(tableName);
239     } catch (TableNotFoundException tnfe) {
240       /* Ignore */
241     }
242   }
243 }