001/* 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.filter; 020 021import java.io.IOException; 022import java.nio.ByteBuffer; 023import java.util.ArrayList; 024import java.util.Collections; 025import java.util.Iterator; 026import java.util.Objects; 027import java.util.Optional; 028 029import org.apache.hadoop.hbase.ByteBufferExtendedCell; 030import org.apache.hadoop.hbase.Cell; 031import org.apache.hadoop.hbase.HConstants; 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; 040import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 041 042/** 043 * A filter that will only return the key component of each KV (the value will 044 * be rewritten as empty). 045 * <p> 046 * This filter can be used to grab all of the keys without having to also grab 047 * the values. 048 */ 049@InterfaceAudience.Public 050public class KeyOnlyFilter extends FilterBase { 051 052 boolean lenAsVal; 053 public KeyOnlyFilter() { this(false); } 054 public KeyOnlyFilter(boolean lenAsVal) { this.lenAsVal = lenAsVal; } 055 056 @Override 057 public boolean filterRowKey(Cell cell) throws IOException { 058 // Impl in FilterBase might do unnecessary copy for Off heap backed Cells. 059 return false; 060 } 061 062 @Override 063 public Cell transformCell(Cell cell) { 064 return createKeyOnlyCell(cell); 065 } 066 067 private Cell createKeyOnlyCell(Cell c) { 068 if (c instanceof ByteBufferExtendedCell) { 069 return new KeyOnlyByteBufferExtendedCell((ByteBufferExtendedCell) c, lenAsVal); 070 } else { 071 return new KeyOnlyCell(c, lenAsVal); 072 } 073 } 074 075 @Deprecated 076 @Override 077 public ReturnCode filterKeyValue(final Cell ignored) throws IOException { 078 return filterCell(ignored); 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 = 102 FilterProtos.KeyOnlyFilter.newBuilder(); 103 builder.setLenAsVal(this.lenAsVal); 104 return builder.build().toByteArray(); 105 } 106 107 /** 108 * @param pbBytes A pb serialized {@link KeyOnlyFilter} instance 109 * @return An instance of {@link KeyOnlyFilter} made from <code>bytes</code> 110 * @throws DeserializationException 111 * @see #toByteArray 112 */ 113 public static KeyOnlyFilter parseFrom(final byte [] pbBytes) 114 throws DeserializationException { 115 FilterProtos.KeyOnlyFilter proto; 116 try { 117 proto = FilterProtos.KeyOnlyFilter.parseFrom(pbBytes); 118 } catch (InvalidProtocolBufferException e) { 119 throw new DeserializationException(e); 120 } 121 return new KeyOnlyFilter(proto.getLenAsVal()); 122 } 123 124 /** 125 * @param o the other filter to compare with 126 * @return true if and only if the fields of the filter that are serialized 127 * are equal to the corresponding fields in other. Used for testing. 128 */ 129 @Override 130 boolean areSerializedFieldsEqual(Filter o) { 131 if (o == this) return true; 132 if (!(o instanceof KeyOnlyFilter)) return false; 133 134 KeyOnlyFilter other = (KeyOnlyFilter)o; 135 return this.lenAsVal == other.lenAsVal; 136 } 137 138 @Override 139 public boolean equals(Object obj) { 140 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 141 } 142 143 @Override 144 public int hashCode() { 145 return Objects.hash(this.lenAsVal); 146 } 147 148 static class KeyOnlyCell implements Cell { 149 private Cell cell; 150 private boolean lenAsVal; 151 152 public KeyOnlyCell(Cell c, boolean lenAsVal) { 153 this.cell = c; 154 this.lenAsVal = lenAsVal; 155 } 156 157 @Override 158 public byte[] getRowArray() { 159 return cell.getRowArray(); 160 } 161 162 @Override 163 public int getRowOffset() { 164 return cell.getRowOffset(); 165 } 166 167 @Override 168 public short getRowLength() { 169 return cell.getRowLength(); 170 } 171 172 @Override 173 public byte[] getFamilyArray() { 174 return cell.getFamilyArray(); 175 } 176 177 @Override 178 public int getFamilyOffset() { 179 return cell.getFamilyOffset(); 180 } 181 182 @Override 183 public byte getFamilyLength() { 184 return cell.getFamilyLength(); 185 } 186 187 @Override 188 public byte[] getQualifierArray() { 189 return cell.getQualifierArray(); 190 } 191 192 @Override 193 public int getQualifierOffset() { 194 return cell.getQualifierOffset(); 195 } 196 197 @Override 198 public int getQualifierLength() { 199 return cell.getQualifierLength(); 200 } 201 202 @Override 203 public long getTimestamp() { 204 return cell.getTimestamp(); 205 } 206 207 @Override 208 public byte getTypeByte() { 209 return cell.getTypeByte(); 210 } 211 212 @Override 213 public Type getType() { 214 return cell.getType(); 215 } 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 byte[] getTagsArray() { 248 return HConstants.EMPTY_BYTE_ARRAY; 249 } 250 251 @Override 252 public int getTagsOffset() { 253 return 0; 254 } 255 256 @Override 257 public int getTagsLength() { 258 return 0; 259 } 260 } 261 262 static class KeyOnlyByteBufferExtendedCell extends ByteBufferExtendedCell { 263 public static final int FIXED_OVERHEAD = ClassSize.OBJECT + ClassSize.REFERENCE 264 + Bytes.SIZEOF_BOOLEAN; 265 private ByteBufferExtendedCell cell; 266 private boolean lenAsVal; 267 268 public KeyOnlyByteBufferExtendedCell(ByteBufferExtendedCell c, boolean lenAsVal) { 269 this.cell = c; 270 this.lenAsVal = lenAsVal; 271 } 272 273 @Override 274 public byte[] getRowArray() { 275 return cell.getRowArray(); 276 } 277 278 @Override 279 public int getRowOffset() { 280 return cell.getRowOffset(); 281 } 282 283 @Override 284 public short getRowLength() { 285 return cell.getRowLength(); 286 } 287 288 @Override 289 public byte[] getFamilyArray() { 290 return cell.getFamilyArray(); 291 } 292 293 @Override 294 public int getFamilyOffset() { 295 return cell.getFamilyOffset(); 296 } 297 298 @Override 299 public byte getFamilyLength() { 300 return cell.getFamilyLength(); 301 } 302 303 @Override 304 public byte[] getQualifierArray() { 305 return cell.getQualifierArray(); 306 } 307 308 @Override 309 public int getQualifierOffset() { 310 return cell.getQualifierOffset(); 311 } 312 313 @Override 314 public int getQualifierLength() { 315 return cell.getQualifierLength(); 316 } 317 318 @Override 319 public long getTimestamp() { 320 return cell.getTimestamp(); 321 } 322 323 @Override 324 public byte getTypeByte() { 325 return cell.getTypeByte(); 326 } 327 328 @Override 329 public void setSequenceId(long seqId) throws IOException { 330 cell.setSequenceId(seqId); 331 } 332 333 @Override 334 public void setTimestamp(long ts) throws IOException { 335 cell.setTimestamp(ts); 336 } 337 338 @Override 339 public void setTimestamp(byte[] ts) throws IOException { 340 cell.setTimestamp(ts); 341 } 342 343 @Override 344 public long getSequenceId() { 345 return 0; 346 } 347 348 @Override 349 public Type getType() { 350 return cell.getType(); 351 } 352 353 @Override 354 public byte[] getValueArray() { 355 if (lenAsVal) { 356 return Bytes.toBytes(cell.getValueLength()); 357 } else { 358 return HConstants.EMPTY_BYTE_ARRAY; 359 } 360 } 361 362 @Override 363 public int getValueOffset() { 364 return 0; 365 } 366 367 @Override 368 public int getValueLength() { 369 if (lenAsVal) { 370 return Bytes.SIZEOF_INT; 371 } else { 372 return 0; 373 } 374 } 375 376 @Override 377 public byte[] getTagsArray() { 378 return HConstants.EMPTY_BYTE_ARRAY; 379 } 380 381 @Override 382 public int getTagsOffset() { 383 return 0; 384 } 385 386 @Override 387 public int getTagsLength() { 388 return 0; 389 } 390 391 @Override 392 public ByteBuffer getRowByteBuffer() { 393 return cell.getRowByteBuffer(); 394 } 395 396 @Override 397 public int getRowPosition() { 398 return cell.getRowPosition(); 399 } 400 401 @Override 402 public ByteBuffer getFamilyByteBuffer() { 403 return cell.getFamilyByteBuffer(); 404 } 405 406 @Override 407 public int getFamilyPosition() { 408 return cell.getFamilyPosition(); 409 } 410 411 @Override 412 public ByteBuffer getQualifierByteBuffer() { 413 return cell.getQualifierByteBuffer(); 414 } 415 416 @Override 417 public int getQualifierPosition() { 418 return cell.getQualifierPosition(); 419 } 420 421 @Override 422 public ByteBuffer getValueByteBuffer() { 423 if (lenAsVal) { 424 return ByteBuffer.wrap(Bytes.toBytes(cell.getValueLength())); 425 } else { 426 return HConstants.EMPTY_BYTE_BUFFER; 427 } 428 } 429 430 @Override 431 public int getValuePosition() { 432 return 0; 433 } 434 435 @Override 436 public ByteBuffer getTagsByteBuffer() { 437 return HConstants.EMPTY_BYTE_BUFFER; 438 } 439 440 @Override 441 public int getTagsPosition() { 442 return 0; 443 } 444 445 @Override 446 public Iterator<Tag> getTags() { 447 return Collections.emptyIterator(); 448 } 449 450 @Override 451 public Optional<Tag> getTag(byte type) { 452 return Optional.empty(); 453 } 454 455 @Override 456 public long heapSize() { 457 return ClassSize.align(FIXED_OVERHEAD + cell.heapSize()); 458 } 459 } 460 461}