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