001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import org.apache.hadoop.hbase.Cell; 021import org.apache.hadoop.hbase.KeyValue; 022import org.apache.hadoop.hbase.PrivateCellUtil; 023import org.apache.yetus.audience.InterfaceAudience; 024 025/** 026 * A hash key for ROWCOL bloom. This assumes the cells to be serialized in the Keyvalue 027 * serialization format with Empty column family. Note that the byte representing the family length 028 * is considered to be 0 029 */ 030@InterfaceAudience.Private 031public class RowColBloomHashKey extends CellHashKey { 032 private final int rowLength; 033 private final int qualLength; 034 private final int totalLength; 035 036 public RowColBloomHashKey(Cell cell) { 037 super(cell); 038 rowLength = cell.getRowLength(); 039 // We don't consider the family length for ROWCOL bloom. So subtract the famLen from the 040 // length calculation. Timestamp and type are of no relevance here 041 qualLength = cell.getQualifierLength(); 042 // ROWCOL Bloom byte layout: 043 // <2B RK length> <RK> <1B CF length> <CQ> <8B TS> <1B TYPE> 044 totalLength = KeyValue.ROW_LENGTH_SIZE + rowLength + KeyValue.FAMILY_LENGTH_SIZE + qualLength 045 + KeyValue.TIMESTAMP_TYPE_SIZE; 046 } 047 048 @Override 049 public byte get(int offset) { 050 return (byte) assembleCrossingLE(offset, Bytes.SIZEOF_BYTE); 051 } 052 053 @Override 054 public int length() { 055 return totalLength; 056 } 057 058 @Override 059 public int getIntLE(int offset) { 060 // Handle fast path that can return the row key as int directly 061 // Compute rowkey section range. 062 final int rowEnd = KeyValue.ROW_LENGTH_SIZE + rowLength; 063 if (offset >= KeyValue.ROW_LENGTH_SIZE && offset + Bytes.SIZEOF_INT <= rowEnd) { 064 return LittleEndianBytes.getRowAsInt(t, offset - KeyValue.ROW_LENGTH_SIZE); 065 } 066 067 // Compute qualifier section range. 068 final int qualStart = rowEnd + KeyValue.FAMILY_LENGTH_SIZE; 069 final int qualEnd = qualStart + qualLength; 070 if (offset >= qualStart && offset + Bytes.SIZEOF_INT <= qualEnd) { 071 return LittleEndianBytes.getQualifierAsInt(t, offset - qualStart); 072 } 073 074 // Compute timestamp section range. 075 final int tsEnd = qualEnd + KeyValue.TIMESTAMP_SIZE; 076 if (offset >= qualEnd && offset + Bytes.SIZEOF_INT <= tsEnd) { 077 return LittleEndianBytes.toInt(LATEST_TS, offset - qualEnd); 078 } 079 080 return (int) assembleCrossingLE(offset, Bytes.SIZEOF_INT); 081 } 082 083 private long assembleCrossingLE(int offset, int wordBytes) { 084 final int rowEnd = KeyValue.ROW_LENGTH_SIZE + rowLength; 085 final int qualStart = rowEnd + KeyValue.FAMILY_LENGTH_SIZE; 086 final int qualEnd = qualStart + qualLength; 087 final int tsEnd = qualEnd + KeyValue.TIMESTAMP_SIZE; 088 089 long result = 0L; 090 int pos = offset; 091 int remaining = wordBytes; 092 093 while (remaining > 0) { 094 // 1) row length field [0,2) 095 if (pos < KeyValue.ROW_LENGTH_SIZE) { 096 if (pos == 0 && remaining >= KeyValue.ROW_LENGTH_SIZE) { 097 result |= (rowLength >>> 8) & 0xFF; 098 result |= (rowLength & 0xFF) << 8; 099 pos += 2; 100 remaining -= 2; 101 } else if (pos == 0) { 102 result |= (rowLength >>> 8) & 0xFF; 103 pos += 1; 104 remaining -= 1; 105 } else { 106 result |= rowLength & 0xFF; 107 pos += 1; 108 remaining -= 1; 109 } 110 continue; 111 } 112 113 // 2) row bytes [2, rowEnd) 114 if (pos < rowEnd) { 115 final int take = Math.min(rowEnd - pos, remaining); 116 final int rOffset = pos - KeyValue.ROW_LENGTH_SIZE; 117 for (int i = 0; i < take; i++) { 118 final int shift = (wordBytes - remaining) * 8; 119 final byte b = PrivateCellUtil.getRowByte(t, rOffset + i); 120 result |= ((long) b & 0xFF) << shift; 121 remaining -= 1; 122 } 123 pos += take; 124 continue; 125 } 126 127 // 3) family length byte (always 0) 128 if (pos == rowEnd) { 129 pos += 1; 130 remaining -= 1; 131 continue; 132 } 133 134 // 4) qualifier bytes [qualStart, qualEnd) 135 if (pos < qualEnd) { 136 final int take = Math.min(qualEnd - pos, remaining); 137 final int qOffset = pos - qualStart; 138 for (int i = 0; i < take; i++) { 139 final int shift = (wordBytes - remaining) * 8; 140 final int b = PrivateCellUtil.getQualifierByte(t, qOffset + i) & 0xFF; 141 result |= ((long) b) << shift; 142 remaining -= 1; 143 } 144 pos += take; 145 continue; 146 } 147 148 // 5) timestamp bytes [qualEnd, tsEnd) -> LATEST_TS 149 if (pos < tsEnd) { 150 final int take = Math.min(tsEnd - pos, remaining); 151 final int tsOff = pos - qualEnd; 152 for (int i = 0; i < take; i++) { 153 final int shift = (wordBytes - remaining) * 8; 154 final int b = LATEST_TS[tsOff + i] & 0xFF; 155 result |= ((long) b) << shift; 156 remaining -= 1; 157 } 158 pos += take; 159 continue; 160 } 161 162 // 6) type byte at typePos -> MAX_TYPE 163 final int shift = (wordBytes - remaining) * 8; 164 result |= ((long) MAX_TYPE & 0xFF) << shift; 165 pos += 1; 166 remaining -= 1; 167 } 168 169 return result; 170 } 171}