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.regionserver.querymatcher;
21  
22  import static org.junit.Assert.assertEquals;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.List;
28  import java.util.TreeSet;
29  
30  import org.apache.hadoop.hbase.KeyValue;
31  import org.apache.hadoop.hbase.regionserver.querymatcher.ScanQueryMatcher.MatchCode;
32  import org.apache.hadoop.hbase.testclassification.SmallTests;
33  import org.apache.hadoop.hbase.util.Bytes;
34  import org.junit.Test;
35  import org.junit.experimental.categories.Category;
36  
37  @Category(SmallTests.class)
38  public class TestExplicitColumnTracker {
39  
40    private final byte[] col1 = Bytes.toBytes("col1");
41    private final byte[] col2 = Bytes.toBytes("col2");
42    private final byte[] col3 = Bytes.toBytes("col3");
43    private final byte[] col4 = Bytes.toBytes("col4");
44    private final byte[] col5 = Bytes.toBytes("col5");
45  
46    private void runTest(int maxVersions, TreeSet<byte[]> trackColumns, List<byte[]> scannerColumns,
47        List<MatchCode> expected) throws IOException {
48      ColumnTracker exp = new ExplicitColumnTracker(trackColumns, 0, maxVersions, Long.MIN_VALUE);
49  
50      // Initialize result
51      List<ScanQueryMatcher.MatchCode> result = new ArrayList<ScanQueryMatcher.MatchCode>();
52  
53      long timestamp = 0;
54      // "Match"
55      for (byte[] col : scannerColumns) {
56        result.add(ScanQueryMatcher.checkColumn(exp, col, 0, col.length, ++timestamp,
57          KeyValue.Type.Put.getCode(), false));
58      }
59  
60      assertEquals(expected.size(), result.size());
61      for (int i = 0; i < expected.size(); i++) {
62        assertEquals(expected.get(i), result.get(i));
63      }
64    }
65  
66    @Test
67    public void testGetSingleVersion() throws IOException {
68      // Create tracker
69      TreeSet<byte[]> columns = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
70      // Looking for every other
71      columns.add(col2);
72      columns.add(col4);
73      List<MatchCode> expected = new ArrayList<ScanQueryMatcher.MatchCode>();
74      expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL); // col1
75      expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL); // col2
76      expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL); // col3
77      expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW); // col4
78      expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW); // col5
79      int maxVersions = 1;
80  
81      // Create "Scanner"
82      List<byte[]> scanner = new ArrayList<byte[]>();
83      scanner.add(col1);
84      scanner.add(col2);
85      scanner.add(col3);
86      scanner.add(col4);
87      scanner.add(col5);
88  
89      runTest(maxVersions, columns, scanner, expected);
90    }
91  
92    @Test
93    public void testGetMultiVersion() throws IOException {
94      // Create tracker
95      TreeSet<byte[]> columns = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
96      // Looking for every other
97      columns.add(col2);
98      columns.add(col4);
99  
100     List<ScanQueryMatcher.MatchCode> expected = new ArrayList<ScanQueryMatcher.MatchCode>();
101     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
102     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
103     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
104 
105     expected.add(ScanQueryMatcher.MatchCode.INCLUDE); // col2; 1st version
106     expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL); // col2; 2nd version
107     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
108 
109     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
110     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
111     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
112 
113     expected.add(ScanQueryMatcher.MatchCode.INCLUDE); // col4; 1st version
114     expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW); // col4; 2nd version
115     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW);
116 
117     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW);
118     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW);
119     expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW);
120     int maxVersions = 2;
121 
122     // Create "Scanner"
123     List<byte[]> scanner = new ArrayList<byte[]>();
124     scanner.add(col1);
125     scanner.add(col1);
126     scanner.add(col1);
127     scanner.add(col2);
128     scanner.add(col2);
129     scanner.add(col2);
130     scanner.add(col3);
131     scanner.add(col3);
132     scanner.add(col3);
133     scanner.add(col4);
134     scanner.add(col4);
135     scanner.add(col4);
136     scanner.add(col5);
137     scanner.add(col5);
138     scanner.add(col5);
139 
140     // Initialize result
141     runTest(maxVersions, columns, scanner, expected);
142   }
143 
144   /**
145    * hbase-2259
146    */
147   @Test
148   public void testStackOverflow() throws IOException {
149     int maxVersions = 1;
150     TreeSet<byte[]> columns = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
151     for (int i = 0; i < 100000; i++) {
152       columns.add(Bytes.toBytes("col" + i));
153     }
154 
155     ColumnTracker explicit = new ExplicitColumnTracker(columns, 0, maxVersions, Long.MIN_VALUE);
156     for (int i = 0; i < 100000; i += 2) {
157       byte[] col = Bytes.toBytes("col" + i);
158       ScanQueryMatcher.checkColumn(explicit, col, 0, col.length, 1, KeyValue.Type.Put.getCode(),
159         false);
160     }
161     explicit.reset();
162 
163     for (int i = 1; i < 100000; i += 2) {
164       byte[] col = Bytes.toBytes("col" + i);
165       ScanQueryMatcher.checkColumn(explicit, col, 0, col.length, 1, KeyValue.Type.Put.getCode(),
166         false);
167     }
168   }
169 
170   /**
171    * Regression test for HBASE-2545
172    */
173   @Test
174   public void testInfiniteLoop() throws IOException {
175     TreeSet<byte[]> columns = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
176     columns.addAll(Arrays.asList(new byte[][] { col2, col3, col5 }));
177     List<byte[]> scanner = Arrays.<byte[]> asList(new byte[][] { col1, col4 });
178     List<ScanQueryMatcher.MatchCode> expected =
179         Arrays.<ScanQueryMatcher.MatchCode> asList(new ScanQueryMatcher.MatchCode[] {
180             ScanQueryMatcher.MatchCode.SEEK_NEXT_COL, ScanQueryMatcher.MatchCode.SEEK_NEXT_COL });
181     runTest(1, columns, scanner, expected);
182   }
183 
184 }