View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase;
20  
21  import java.io.Serializable;
22  import java.util.Comparator;
23  
24  import org.apache.hadoop.classification.InterfaceAudience;
25  import org.apache.hadoop.classification.InterfaceStability;
26  import org.apache.hadoop.hbase.util.Bytes;
27  
28  import com.google.common.primitives.Longs;
29  
30  /**
31   * Compare two HBase cells.  Do not use this method comparing <code>-ROOT-</code> or
32   * <code>.META.</code> cells.  Cells from these tables need a specialized comparator, one that
33   * takes account of the special formatting of the row where we have commas to delimit table from
34   * regionname, from row.  See KeyValue for how it has a special comparator to do .META. cells
35   * and yet another for -ROOT-.
36   */
37  @edu.umd.cs.findbugs.annotations.SuppressWarnings(
38      value="UNKNOWN",
39      justification="Findbugs doesn't like the way we are negating the result of a compare in below")
40  @InterfaceAudience.Private
41  @InterfaceStability.Evolving
42  public class CellComparator implements Comparator<Cell>, Serializable{
43    private static final long serialVersionUID = -8760041766259623329L;
44  
45    @Override
46    public int compare(Cell a, Cell b) {
47      return compareStatic(a, b);
48    }
49  
50  
51    public static int compareStatic(Cell a, Cell b) {
52      //row
53      int c = Bytes.compareTo(
54          a.getRowArray(), a.getRowOffset(), a.getRowLength(),
55          b.getRowArray(), b.getRowOffset(), b.getRowLength());
56      if (c != 0) return c;
57  
58      //family
59      c = Bytes.compareTo(
60        a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(),
61        b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength());
62      if (c != 0) return c;
63  
64      //qualifier
65      c = Bytes.compareTo(
66          a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(),
67          b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength());
68      if (c != 0) return c;
69  
70      //timestamp: later sorts first
71      c = -Longs.compare(a.getTimestamp(), b.getTimestamp());
72      if (c != 0) return c;
73  
74      //type
75      c = (0xff & a.getTypeByte()) - (0xff & b.getTypeByte());
76      if (c != 0) return c;
77  
78      //mvccVersion: later sorts first
79      return -Longs.compare(a.getMvccVersion(), b.getMvccVersion());
80    }
81  
82  
83    /**************** equals ****************************/
84  
85    public static boolean equals(Cell a, Cell b){
86      return equalsRow(a, b)
87          && equalsFamily(a, b)
88          && equalsQualifier(a, b)
89          && equalsTimestamp(a, b)
90          && equalsType(a, b);
91    }
92  
93    public static boolean equalsRow(Cell a, Cell b){
94      return Bytes.equals(
95        a.getRowArray(), a.getRowOffset(), a.getRowLength(),
96        b.getRowArray(), b.getRowOffset(), b.getRowLength());
97    }
98  
99    public static boolean equalsFamily(Cell a, Cell b){
100     return Bytes.equals(
101       a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(),
102       b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength());
103   }
104 
105   public static boolean equalsQualifier(Cell a, Cell b){
106     return Bytes.equals(
107       a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(),
108       b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength());
109   }
110 
111   public static boolean equalsTimestamp(Cell a, Cell b){
112     return a.getTimestamp() == b.getTimestamp();
113   }
114 
115   public static boolean equalsType(Cell a, Cell b){
116     return a.getTypeByte() == b.getTypeByte();
117   }
118 
119 
120   /********************* hashCode ************************/
121 
122   /**
123    * Returns a hash code that is always the same for two Cells having a matching equals(..) result.
124    * Currently does not guard against nulls, but it could if necessary.
125    */
126   public static int hashCode(Cell cell){
127     if (cell == null) {// return 0 for empty Cell
128       return 0;
129     }
130 
131     //pre-calculate the 3 hashes made of byte ranges
132     int rowHash = Bytes.hashCode(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
133     int familyHash =
134       Bytes.hashCode(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
135     int qualifierHash = Bytes.hashCode(cell.getQualifierArray(), cell.getQualifierOffset(),
136       cell.getQualifierLength());
137 
138     //combine the 6 sub-hashes
139     int hash = 31 * rowHash + familyHash;
140     hash = 31 * hash + qualifierHash;
141     hash = 31 * hash + (int)cell.getTimestamp();
142     hash = 31 * hash + cell.getTypeByte();
143     hash = 31 * hash + (int)cell.getMvccVersion();
144     return hash;
145   }
146 
147 
148   /******************** lengths *************************/
149 
150   public static boolean areKeyLengthsEqual(Cell a, Cell b) {
151     return a.getRowLength() == b.getRowLength()
152         && a.getFamilyLength() == b.getFamilyLength()
153         && a.getQualifierLength() == b.getQualifierLength();
154   }
155 
156   public static boolean areRowLengthsEqual(Cell a, Cell b) {
157     return a.getRowLength() == b.getRowLength();
158   }
159 
160 
161   /***************** special cases ****************************/
162 
163   /**
164    * special case for KeyValue.equals
165    */
166   private static int compareStaticIgnoreMvccVersion(Cell a, Cell b) {
167     //row
168     int c = Bytes.compareTo(
169         a.getRowArray(), a.getRowOffset(), a.getRowLength(),
170         b.getRowArray(), b.getRowOffset(), b.getRowLength());
171     if (c != 0) return c;
172 
173     //family
174     c = Bytes.compareTo(
175       a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(),
176       b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength());
177     if (c != 0) return c;
178 
179     //qualifier
180     c = Bytes.compareTo(
181         a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(),
182         b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength());
183     if (c != 0) return c;
184 
185     //timestamp: later sorts first
186     c = -Longs.compare(a.getTimestamp(), b.getTimestamp());
187     if (c != 0) return c;
188 
189     //type
190     c = (0xff & a.getTypeByte()) - (0xff & b.getTypeByte());
191     return c;
192   }
193 
194   /**
195    * special case for KeyValue.equals
196    */
197   public static boolean equalsIgnoreMvccVersion(Cell a, Cell b){
198     return 0 == compareStaticIgnoreMvccVersion(a, b);
199   }
200 
201 }