View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.filter;
21  
22  import java.io.IOException;
23  
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.classification.InterfaceStability;
26  import org.apache.hadoop.hbase.Cell;
27  import org.apache.hadoop.hbase.exceptions.DeserializationException;
28  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
29  import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
30  
31  import com.google.protobuf.InvalidProtocolBufferException;
32  
33  /**
34   * A wrapper filter that filters an entire row if any of the Cell checks do
35   * not pass.
36   * <p>
37   * For example, if all columns in a row represent weights of different things,
38   * with the values being the actual weights, and we want to filter out the
39   * entire row if any of its weights are zero.  In this case, we want to prevent
40   * rows from being emitted if a single key is filtered.  Combine this filter
41   * with a {@link ValueFilter}:
42   * </p>
43   * <p>
44   * <code>
45   * scan.setFilter(new SkipFilter(new ValueFilter(CompareOp.NOT_EQUAL,
46   *     new BinaryComparator(Bytes.toBytes(0))));
47   * </code>
48   * Any row which contained a column whose value was 0 will be filtered out
49   * (since ValueFilter will not pass that Cell).
50   * Without this filter, the other non-zero valued columns in the row would still
51   * be emitted.
52   * </p>
53   */
54  @InterfaceAudience.Public
55  @InterfaceStability.Stable
56  public class SkipFilter extends FilterBase {
57    private boolean filterRow = false;
58    private Filter filter;
59  
60    public SkipFilter(Filter filter) {
61      this.filter = filter;
62    }
63  
64    public Filter getFilter() {
65      return filter;
66    }
67  
68    @Override
69    public void reset() throws IOException {
70      filter.reset();
71      filterRow = false;
72    }
73  
74    private void changeFR(boolean value) {
75      filterRow = filterRow || value;
76    }
77  
78    @Override
79    public ReturnCode filterKeyValue(Cell v) throws IOException {
80      ReturnCode c = filter.filterKeyValue(v);
81      changeFR(c != ReturnCode.INCLUDE);
82      return c;
83    }
84  
85    @Override
86    public Cell transformCell(Cell v) throws IOException {
87      return filter.transformCell(v);
88    }
89  
90    public boolean filterRow() {
91      return filterRow;
92    }
93      
94    public boolean hasFilterRow() {
95      return true;
96    }
97  
98    /**
99     * @return The filter serialized using pb
100    */
101   public byte[] toByteArray() throws IOException {
102     FilterProtos.SkipFilter.Builder builder =
103       FilterProtos.SkipFilter.newBuilder();
104     builder.setFilter(ProtobufUtil.toFilter(this.filter));
105     return builder.build().toByteArray();
106   }
107 
108   /**
109    * @param pbBytes A pb serialized {@link SkipFilter} instance
110    * @return An instance of {@link SkipFilter} made from <code>bytes</code>
111    * @throws DeserializationException
112    * @see #toByteArray
113    */
114   public static SkipFilter parseFrom(final byte [] pbBytes)
115   throws DeserializationException {
116     FilterProtos.SkipFilter proto;
117     try {
118       proto = FilterProtos.SkipFilter.parseFrom(pbBytes);
119     } catch (InvalidProtocolBufferException e) {
120       throw new DeserializationException(e);
121     }
122     try {
123       return new SkipFilter(ProtobufUtil.toFilter(proto.getFilter()));
124     } catch (IOException ioe) {
125       throw new DeserializationException(ioe);
126     }
127   }
128 
129   /**
130    * @param other
131    * @return true if and only if the fields of the filter that are serialized
132    * are equal to the corresponding fields in other.  Used for testing.
133    */
134   boolean areSerializedFieldsEqual(Filter o) {
135     if (o == this) return true;
136     if (!(o instanceof SkipFilter)) return false;
137 
138     SkipFilter other = (SkipFilter)o;
139     return getFilter().areSerializedFieldsEqual(other.getFilter());
140   }
141 
142   public boolean isFamilyEssential(byte[] name) throws IOException {
143     return filter.isFamilyEssential(name);
144   }
145 
146   @Override
147   public String toString() {
148     return this.getClass().getSimpleName() + " " + this.filter.toString();
149   }
150 }