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