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.filter; 019 020import java.io.IOException; 021import java.nio.ByteBuffer; 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.Iterator; 025import java.util.Objects; 026import java.util.Optional; 027import org.apache.hadoop.hbase.ByteBufferExtendedCell; 028import org.apache.hadoop.hbase.Cell; 029import org.apache.hadoop.hbase.HConstants; 030import org.apache.hadoop.hbase.KeyValue; 031import org.apache.hadoop.hbase.KeyValueUtil; 032import org.apache.hadoop.hbase.Tag; 033import org.apache.hadoop.hbase.exceptions.DeserializationException; 034import org.apache.hadoop.hbase.util.Bytes; 035import org.apache.hadoop.hbase.util.ClassSize; 036import org.apache.yetus.audience.InterfaceAudience; 037 038import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 039import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException; 040 041import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 042 043/** 044 * A filter that will only return the key component of each KV (the value will be rewritten as 045 * empty). 046 * <p> 047 * This filter can be used to grab all of the keys without having to also grab the values. 048 */ 049@InterfaceAudience.Public 050public class KeyOnlyFilter extends FilterBase { 051 052 boolean lenAsVal; 053 054 public KeyOnlyFilter() { 055 this(false); 056 } 057 058 public KeyOnlyFilter(boolean lenAsVal) { 059 this.lenAsVal = lenAsVal; 060 } 061 062 @Override 063 public boolean filterRowKey(Cell cell) throws IOException { 064 // Impl in FilterBase might do unnecessary copy for Off heap backed Cells. 065 return false; 066 } 067 068 @Override 069 public Cell transformCell(Cell cell) { 070 return createKeyOnlyCell(cell); 071 } 072 073 private Cell createKeyOnlyCell(Cell c) { 074 if (c instanceof ByteBufferExtendedCell) { 075 return new KeyOnlyByteBufferExtendedCell((ByteBufferExtendedCell) c, lenAsVal); 076 } else { 077 return new KeyOnlyCell(c, lenAsVal); 078 } 079 } 080 081 @Override 082 public ReturnCode filterCell(final Cell ignored) throws IOException { 083 return ReturnCode.INCLUDE; 084 } 085 086 public static Filter createFilterFromArguments(ArrayList<byte[]> filterArguments) { 087 Preconditions.checkArgument((filterArguments.isEmpty() || filterArguments.size() == 1), 088 "Expected: 0 or 1 but got: %s", filterArguments.size()); 089 KeyOnlyFilter filter = new KeyOnlyFilter(); 090 if (filterArguments.size() == 1) { 091 filter.lenAsVal = ParseFilter.convertByteArrayToBoolean(filterArguments.get(0)); 092 } 093 return filter; 094 } 095 096 /** Returns The filter serialized using pb */ 097 @Override 098 public byte[] toByteArray() { 099 FilterProtos.KeyOnlyFilter.Builder builder = FilterProtos.KeyOnlyFilter.newBuilder(); 100 builder.setLenAsVal(this.lenAsVal); 101 return builder.build().toByteArray(); 102 } 103 104 /** 105 * Parse a serialized representation of {@link KeyOnlyFilter} 106 * @param pbBytes A pb serialized {@link KeyOnlyFilter} instance 107 * @return An instance of {@link KeyOnlyFilter} made from <code>bytes</code> 108 * @throws DeserializationException if an error occurred 109 * @see #toByteArray 110 */ 111 public static KeyOnlyFilter parseFrom(final byte[] pbBytes) throws DeserializationException { 112 FilterProtos.KeyOnlyFilter proto; 113 try { 114 proto = FilterProtos.KeyOnlyFilter.parseFrom(pbBytes); 115 } catch (InvalidProtocolBufferException e) { 116 throw new DeserializationException(e); 117 } 118 return new KeyOnlyFilter(proto.getLenAsVal()); 119 } 120 121 /** 122 * Returns true if and only if the fields of the filter that are serialized are equal to the 123 * corresponding fields in other. Used for testing. 124 */ 125 @Override 126 boolean areSerializedFieldsEqual(Filter o) { 127 if (o == this) { 128 return true; 129 } 130 if (!(o instanceof KeyOnlyFilter)) { 131 return false; 132 } 133 KeyOnlyFilter other = (KeyOnlyFilter) o; 134 return this.lenAsVal == other.lenAsVal; 135 } 136 137 @Override 138 public boolean equals(Object obj) { 139 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 140 } 141 142 @Override 143 public int hashCode() { 144 return Objects.hash(this.lenAsVal); 145 } 146 147 static class KeyOnlyCell implements Cell { 148 private Cell cell; 149 private int keyLen; 150 private boolean lenAsVal; 151 152 public KeyOnlyCell(Cell c, boolean lenAsVal) { 153 this.cell = c; 154 this.lenAsVal = lenAsVal; 155 this.keyLen = KeyValueUtil.keyLength(c); 156 } 157 158 @Override 159 public byte[] getRowArray() { 160 return cell.getRowArray(); 161 } 162 163 @Override 164 public int getRowOffset() { 165 return cell.getRowOffset(); 166 } 167 168 @Override 169 public short getRowLength() { 170 return cell.getRowLength(); 171 } 172 173 @Override 174 public byte[] getFamilyArray() { 175 return cell.getFamilyArray(); 176 } 177 178 @Override 179 public int getFamilyOffset() { 180 return cell.getFamilyOffset(); 181 } 182 183 @Override 184 public byte getFamilyLength() { 185 return cell.getFamilyLength(); 186 } 187 188 @Override 189 public byte[] getQualifierArray() { 190 return cell.getQualifierArray(); 191 } 192 193 @Override 194 public int getQualifierOffset() { 195 return cell.getQualifierOffset(); 196 } 197 198 @Override 199 public int getQualifierLength() { 200 return cell.getQualifierLength(); 201 } 202 203 @Override 204 public long getTimestamp() { 205 return cell.getTimestamp(); 206 } 207 208 @Override 209 public byte getTypeByte() { 210 return cell.getTypeByte(); 211 } 212 213 @Override 214 public Type getType() { 215 return cell.getType(); 216 } 217 218 @Override 219 public long getSequenceId() { 220 return 0; 221 } 222 223 @Override 224 public byte[] getValueArray() { 225 if (lenAsVal) { 226 return Bytes.toBytes(cell.getValueLength()); 227 } else { 228 return HConstants.EMPTY_BYTE_ARRAY; 229 } 230 } 231 232 @Override 233 public int getValueOffset() { 234 return 0; 235 } 236 237 @Override 238 public int getValueLength() { 239 if (lenAsVal) { 240 return Bytes.SIZEOF_INT; 241 } else { 242 return 0; 243 } 244 } 245 246 @Override 247 public int getSerializedSize() { 248 return KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE + keyLen + getValueLength(); 249 } 250 251 @Override 252 public byte[] getTagsArray() { 253 return HConstants.EMPTY_BYTE_ARRAY; 254 } 255 256 @Override 257 public int getTagsOffset() { 258 return 0; 259 } 260 261 @Override 262 public int getTagsLength() { 263 return 0; 264 } 265 266 @Override 267 public long heapSize() { 268 return cell.heapSize(); 269 } 270 } 271 272 static class KeyOnlyByteBufferExtendedCell extends ByteBufferExtendedCell { 273 public static final int FIXED_OVERHEAD = 274 ClassSize.OBJECT + ClassSize.REFERENCE + Bytes.SIZEOF_BOOLEAN; 275 private ByteBufferExtendedCell cell; 276 private boolean lenAsVal; 277 278 public KeyOnlyByteBufferExtendedCell(ByteBufferExtendedCell c, boolean lenAsVal) { 279 this.cell = c; 280 this.lenAsVal = lenAsVal; 281 } 282 283 @Override 284 public byte[] getRowArray() { 285 return cell.getRowArray(); 286 } 287 288 @Override 289 public int getRowOffset() { 290 return cell.getRowOffset(); 291 } 292 293 @Override 294 public short getRowLength() { 295 return cell.getRowLength(); 296 } 297 298 @Override 299 public byte[] getFamilyArray() { 300 return cell.getFamilyArray(); 301 } 302 303 @Override 304 public int getFamilyOffset() { 305 return cell.getFamilyOffset(); 306 } 307 308 @Override 309 public byte getFamilyLength() { 310 return cell.getFamilyLength(); 311 } 312 313 @Override 314 public byte[] getQualifierArray() { 315 return cell.getQualifierArray(); 316 } 317 318 @Override 319 public int getQualifierOffset() { 320 return cell.getQualifierOffset(); 321 } 322 323 @Override 324 public int getQualifierLength() { 325 return cell.getQualifierLength(); 326 } 327 328 @Override 329 public long getTimestamp() { 330 return cell.getTimestamp(); 331 } 332 333 @Override 334 public byte getTypeByte() { 335 return cell.getTypeByte(); 336 } 337 338 @Override 339 public void setSequenceId(long seqId) throws IOException { 340 cell.setSequenceId(seqId); 341 } 342 343 @Override 344 public void setTimestamp(long ts) throws IOException { 345 cell.setTimestamp(ts); 346 } 347 348 @Override 349 public void setTimestamp(byte[] ts) throws IOException { 350 cell.setTimestamp(ts); 351 } 352 353 @Override 354 public long getSequenceId() { 355 return 0; 356 } 357 358 @Override 359 public Type getType() { 360 return cell.getType(); 361 } 362 363 @Override 364 public byte[] getValueArray() { 365 if (lenAsVal) { 366 return Bytes.toBytes(cell.getValueLength()); 367 } else { 368 return HConstants.EMPTY_BYTE_ARRAY; 369 } 370 } 371 372 @Override 373 public int getValueOffset() { 374 return 0; 375 } 376 377 @Override 378 public int getValueLength() { 379 if (lenAsVal) { 380 return Bytes.SIZEOF_INT; 381 } else { 382 return 0; 383 } 384 } 385 386 @Override 387 public byte[] getTagsArray() { 388 return HConstants.EMPTY_BYTE_ARRAY; 389 } 390 391 @Override 392 public int getTagsOffset() { 393 return 0; 394 } 395 396 @Override 397 public int getTagsLength() { 398 return 0; 399 } 400 401 @Override 402 public ByteBuffer getRowByteBuffer() { 403 return cell.getRowByteBuffer(); 404 } 405 406 @Override 407 public int getRowPosition() { 408 return cell.getRowPosition(); 409 } 410 411 @Override 412 public ByteBuffer getFamilyByteBuffer() { 413 return cell.getFamilyByteBuffer(); 414 } 415 416 @Override 417 public int getFamilyPosition() { 418 return cell.getFamilyPosition(); 419 } 420 421 @Override 422 public ByteBuffer getQualifierByteBuffer() { 423 return cell.getQualifierByteBuffer(); 424 } 425 426 @Override 427 public int getQualifierPosition() { 428 return cell.getQualifierPosition(); 429 } 430 431 @Override 432 public ByteBuffer getValueByteBuffer() { 433 if (lenAsVal) { 434 return ByteBuffer.wrap(Bytes.toBytes(cell.getValueLength())); 435 } else { 436 return HConstants.EMPTY_BYTE_BUFFER; 437 } 438 } 439 440 @Override 441 public int getValuePosition() { 442 return 0; 443 } 444 445 @Override 446 public ByteBuffer getTagsByteBuffer() { 447 return HConstants.EMPTY_BYTE_BUFFER; 448 } 449 450 @Override 451 public int getTagsPosition() { 452 return 0; 453 } 454 455 @Override 456 public Iterator<Tag> getTags() { 457 return Collections.emptyIterator(); 458 } 459 460 @Override 461 public Optional<Tag> getTag(byte type) { 462 return Optional.empty(); 463 } 464 465 @Override 466 public long heapSize() { 467 return ClassSize.align(FIXED_OVERHEAD + cell.heapSize()); 468 } 469 } 470 471}