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