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