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.hbase.cell;
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  import org.apache.hbase.Cell;
28  
29  import com.google.common.primitives.Longs;
30  
31  /**
32   * Compare two traditional HBase cells.
33   *
34   * Note: This comparator is not valid for -ROOT- and .META. tables.
35   */
36  @InterfaceAudience.Private
37  @InterfaceStability.Evolving
38  public class CellComparator implements Comparator<Cell>, Serializable{
39    private static final long serialVersionUID = -8760041766259623329L;
40  
41    @Override
42    public int compare(Cell a, Cell b) {
43      return compareStatic(a, b);
44    }
45  
46  
47    public static int compareStatic(Cell a, Cell b) {
48      //row
49      int c = Bytes.compareTo(
50          a.getRowArray(), a.getRowOffset(), a.getRowLength(),
51          b.getRowArray(), b.getRowOffset(), b.getRowLength());
52      if (c != 0) return c;
53  
54      //family
55      c = Bytes.compareTo(
56        a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(),
57        b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength());
58      if (c != 0) return c;
59  
60      //qualifier
61      c = Bytes.compareTo(
62          a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(),
63          b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength());
64      if (c != 0) return c;
65  
66      //timestamp: later sorts first
67      c = -Longs.compare(a.getTimestamp(), b.getTimestamp());
68      if (c != 0) return c;
69  
70      //type
71      c = (0xff & a.getTypeByte()) - (0xff & b.getTypeByte());
72      if (c != 0) return c;
73  
74      //mvccVersion: later sorts first
75      return -Longs.compare(a.getMvccVersion(), b.getMvccVersion());
76    }
77  
78  
79    /**************** equals ****************************/
80  
81    public static boolean equals(Cell a, Cell b){
82      if (!areKeyLengthsEqual(a, b)) {
83        return false;
84      }
85      //TODO compare byte[]'s in reverse since later bytes more likely to differ
86      return 0 == compareStatic(a, b);
87    }
88  
89    public static boolean equalsRow(Cell a, Cell b){
90      if(!areRowLengthsEqual(a, b)){
91        return false;
92      }
93      return 0 == Bytes.compareTo(
94        a.getRowArray(), a.getRowOffset(), a.getRowLength(),
95        b.getRowArray(), b.getRowOffset(), b.getRowLength());
96    }
97  
98  
99    /********************* hashCode ************************/
100 
101   /**
102    * Returns a hash code that is always the same for two Cells having a matching equals(..) result.
103    * Currently does not guard against nulls, but it could if necessary.
104    */
105   public static int hashCode(Cell cell){
106     if (cell == null) {// return 0 for empty Cell
107       return 0;
108     }
109 
110     //pre-calculate the 3 hashes made of byte ranges
111     int rowHash = Bytes.hashCode(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
112     int familyHash = Bytes.hashCode(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
113     int qualifierHash = Bytes.hashCode(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
114 
115     //combine the 6 sub-hashes
116     int hash = 31 * rowHash + familyHash;
117     hash = 31 * hash + qualifierHash;
118     hash = 31 * hash + (int)cell.getTimestamp();
119     hash = 31 * hash + cell.getTypeByte();
120     hash = 31 * hash + (int)cell.getMvccVersion();
121     return hash;
122   }
123 
124 
125   /******************** lengths *************************/
126 
127   public static boolean areKeyLengthsEqual(Cell a, Cell b) {
128     return a.getRowLength() == b.getRowLength()
129         && a.getFamilyLength() == b.getFamilyLength()
130         && a.getQualifierLength() == b.getQualifierLength();
131   }
132 
133   public static boolean areRowLengthsEqual(Cell a, Cell b) {
134     return a.getRowLength() == b.getRowLength();
135   }
136 
137 
138   /***************** special cases ****************************/
139 
140   /**
141    * special case for KeyValue.equals
142    */
143   private static int compareStaticIgnoreMvccVersion(Cell a, Cell b) {
144     //row
145     int c = Bytes.compareTo(
146         a.getRowArray(), a.getRowOffset(), a.getRowLength(),
147         b.getRowArray(), b.getRowOffset(), b.getRowLength());
148     if (c != 0) return c;
149 
150     //family
151     c = Bytes.compareTo(
152       a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(),
153       b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength());
154     if (c != 0) return c;
155 
156     //qualifier
157     c = Bytes.compareTo(
158         a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(),
159         b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength());
160     if (c != 0) return c;
161 
162     //timestamp: later sorts first
163     c = -Longs.compare(a.getTimestamp(), b.getTimestamp());
164     if (c != 0) return c;
165 
166     //type
167     c = (0xff & a.getTypeByte()) - (0xff & b.getTypeByte());
168     return c;
169   }
170 
171   /**
172    * special case for KeyValue.equals
173    */
174   public static boolean equalsIgnoreMvccVersion(Cell a, Cell b){
175     return 0 == compareStaticIgnoreMvccVersion(a, b);
176   }
177 
178 }