View Javadoc

1   /*
2    * Copyright (c) 2010.  The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.hbql.filter;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HBaseConfiguration;
27  import org.apache.hadoop.hbase.KeyValue;
28  import org.apache.hadoop.hbase.filter.Filter;
29  import org.apache.hadoop.hbase.io.HbaseObjectWritable;
30  import org.apache.hadoop.io.Writable;
31  
32  import java.io.DataInput;
33  import java.io.DataOutput;
34  import java.io.IOException;
35  
36  /**
37   * Implementation of Filter interface that limits results to a specific page
38   * size. It terminates scanning once the number of filter-passed rows is >
39   * the given page size.
40   * <p/>
41   * Note that this filter cannot guarantee that the number of results returned
42   * to a client are <= page size. This is because the filter is applied
43   * separately on different region servers. It does however optimize the scan of
44   * individual HRegions by making sure that the page size is never exceeded
45   * locally.
46   */
47  public class PageFilter implements InstrumentedFilter {
48  
49      private static final Log LOG = LogFactory.getLog(PageFilter.class);
50  
51      private boolean verbose = false;
52      private long pageSize = Long.MAX_VALUE;
53      private int rowsAccepted = 0;
54      private Filter filter;
55  
56      /**
57       * Default constructor, filters nothing. Required though for RPC
58       * deserialization.
59       */
60      public PageFilter() {
61          super();
62      }
63  
64      /**
65       * Constructor that takes a maximum page size.
66       *
67       * @param pageSize Maximum result size.
68       */
69      public PageFilter(final long pageSize, final Filter filter) {
70          this.pageSize = pageSize;
71          this.filter = filter;
72      }
73  
74      private Filter getFilter() {
75          return this.filter;
76      }
77  
78      public void setVerbose(final boolean verbose) {
79          this.verbose = verbose;
80      }
81  
82      public boolean getVerbose() {
83          return this.verbose;
84      }
85  
86      public void reset() {
87          if (this.getFilter() != null)
88              this.getFilter().reset();
89      }
90  
91      public boolean filterAllRemaining() {
92          if (this.getVerbose())
93              LOG.debug("In PageFilter.filterAllRemaining() " + (this.rowsAccepted >= this.pageSize)
94                        + " " + this.rowsAccepted + " of " + this.pageSize);
95          return this.rowsAccepted >= this.pageSize;
96      }
97  
98      public boolean filterRowKey(byte[] rowKey, int offset, int length) {
99          if (this.getFilter() != null)
100             return this.getFilter().filterRowKey(rowKey, offset, length);
101         else
102             return false;
103     }
104 
105     public ReturnCode filterKeyValue(KeyValue v) {
106         if (this.getFilter() != null)
107             return this.getFilter().filterKeyValue(v);
108         else
109             return ReturnCode.INCLUDE;
110     }
111 
112     public boolean filterRow() {
113 
114         if (this.rowsAccepted > this.pageSize)
115             return true;
116 
117         if (this.getFilter() != null) {
118             if (this.getFilter().filterRow())
119                 return true;
120         }
121 
122         this.rowsAccepted++;
123         return this.rowsAccepted > this.pageSize;
124     }
125 
126     public void readFields(final DataInput in) throws IOException {
127         Configuration conf = new HBaseConfiguration();
128         this.pageSize = in.readLong();
129         this.verbose = in.readBoolean();
130         this.filter = (Filter)HbaseObjectWritable.readObject(in, conf);
131     }
132 
133     public void write(final DataOutput out) throws IOException {
134         Configuration conf = new HBaseConfiguration();
135         out.writeLong(this.pageSize);
136         out.writeBoolean(this.getVerbose());
137         HbaseObjectWritable.writeObject(out, this.getFilter(), Writable.class, conf);
138     }
139 }