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