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