View Javadoc

1   /**
2    * Copyright 2010 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 org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.hbase.regionserver.ScanQueryMatcher.MatchCode;
26  import org.apache.hadoop.hbase.util.Bytes;
27  
28  /**
29   * Keeps track of the columns for a scan if they are not explicitly specified
30   */
31  public class ScanWildcardColumnTracker implements ColumnTracker {
32    private static final Log LOG =
33      LogFactory.getLog(ScanWildcardColumnTracker.class);
34    private byte [] columnBuffer = null;
35    private int columnOffset = 0;
36    private int columnLength = 0;
37    private int currentCount = 0;
38    private int maxVersions;
39  
40    /**
41     * Return maxVersions of every row.
42     * @param maxVersion
43     */
44    public ScanWildcardColumnTracker(int maxVersion) {
45      this.maxVersions = maxVersion;
46    }
47  
48    /**
49     * Can only return INCLUDE or SKIP, since returning "NEXT" or
50     * "DONE" would imply we have finished with this row, when
51     * this class can't figure that out.
52     *
53     * @param bytes
54     * @param offset
55     * @param length
56     * @return The match code instance.
57     */
58    @Override
59    public MatchCode checkColumn(byte[] bytes, int offset, int length) {
60      if (columnBuffer == null) {
61        // first iteration.
62        columnBuffer = bytes;
63        columnOffset = offset;
64        columnLength = length;
65        currentCount = 0;
66  
67        if (++currentCount > maxVersions)
68          return ScanQueryMatcher.MatchCode.SKIP;
69        return ScanQueryMatcher.MatchCode.INCLUDE;
70      }
71      int cmp = Bytes.compareTo(bytes, offset, length,
72          columnBuffer, columnOffset, columnLength);
73      if (cmp == 0) {
74        if (++currentCount > maxVersions)
75          return ScanQueryMatcher.MatchCode.SKIP; // skip to next col
76        return ScanQueryMatcher.MatchCode.INCLUDE;
77      }
78  
79      // new col > old col
80      if (cmp > 0) {
81        // switched columns, lets do something.x
82        columnBuffer = bytes;
83        columnOffset = offset;
84        columnLength = length;
85        currentCount = 0;
86        if (++currentCount > maxVersions)
87          return ScanQueryMatcher.MatchCode.SKIP;
88        return ScanQueryMatcher.MatchCode.INCLUDE;
89      }
90  
91      // new col < oldcol
92      // if (cmp < 0) {
93      // WARNING: This means that very likely an edit for some other family
94      // was incorrectly stored into the store for this one. Continue, but
95      // complain.
96      LOG.error("ScanWildcardColumnTracker.checkColumn ran " +
97    		"into a column actually smaller than the previous column: " +
98        Bytes.toStringBinary(bytes, offset, length));
99      // switched columns
100     columnBuffer = bytes;
101     columnOffset = offset;
102     columnLength = length;
103     currentCount = 0;
104     if (++currentCount > maxVersions)
105       return ScanQueryMatcher.MatchCode.SKIP;
106     return ScanQueryMatcher.MatchCode.INCLUDE;
107   }
108 
109   @Override
110   public void update() {
111     // no-op, shouldn't even be called
112     throw new UnsupportedOperationException(
113         "ScanWildcardColumnTracker.update should never be called!");
114   }
115 
116   @Override
117   public void reset() {
118     columnBuffer = null;
119   }
120 
121   /**
122    * Used by matcher and scan/get to get a hint of the next column
123    * to seek to after checkColumn() returns SKIP.  Returns the next interesting
124    * column we want, or NULL there is none (wildcard scanner).
125    *
126    * @return The column count.
127    */
128   public ColumnCount getColumnHint() {
129     return null;
130   }
131 
132 
133   /**
134    * We can never know a-priori if we are done, so always return false.
135    * @return false
136    */
137   @Override
138   public boolean done() {
139     return false;
140   }
141 }