View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.filter;
19  
20  import java.io.DataInput;
21  import java.io.DataOutput;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.TreeSet;
26  import java.util.ArrayList;
27  
28  import org.apache.hadoop.hbase.KeyValue;
29  import com.google.common.base.Preconditions;
30  
31  /**
32   * Filter that returns only cells whose timestamp (version) is
33   * in the specified list of timestamps (versions).
34   * <p>
35   * Note: Use of this filter overrides any time range/time stamp
36   * options specified using {@link org.apache.hadoop.hbase.client.Get#setTimeRange(long, long)},
37   * {@link org.apache.hadoop.hbase.client.Scan#setTimeRange(long, long)}, {@link org.apache.hadoop.hbase.client.Get#setTimeStamp(long)},
38   * or {@link org.apache.hadoop.hbase.client.Scan#setTimeStamp(long)}.
39   */
40  public class TimestampsFilter extends FilterBase {
41  
42    TreeSet<Long> timestamps;
43    private static final int MAX_LOG_TIMESTAMPS = 5;
44  
45    // Used during scans to hint the scan to stop early
46    // once the timestamps fall below the minTimeStamp.
47    long minTimeStamp = Long.MAX_VALUE;
48  
49    /**
50     * Used during deserialization. Do not use otherwise.
51     */
52    public TimestampsFilter() {
53      super();
54    }
55  
56    /**
57     * Constructor for filter that retains only those
58     * cells whose timestamp (version) is in the specified
59     * list of timestamps.
60     *
61     * @param timestamps
62     */
63    public TimestampsFilter(List<Long> timestamps) {
64      for (Long timestamp : timestamps) {
65        Preconditions.checkArgument(timestamp >= 0, "must be positive %s", timestamp);
66      }
67      this.timestamps = new TreeSet<Long>(timestamps);
68      init();
69    }
70  
71    /**
72     * @return the list of timestamps
73     */
74    public List<Long> getTimestamps() {
75      List<Long> list = new ArrayList<Long>(timestamps.size());
76      list.addAll(timestamps);
77      return list;
78    }
79  
80    private void init() {
81      if (this.timestamps.size() > 0) {
82        minTimeStamp = this.timestamps.first();
83      }
84    }
85  
86    /**
87     * Gets the minimum timestamp requested by filter.
88     * @return  minimum timestamp requested by filter.
89     */
90    public long getMin() {
91      return minTimeStamp;
92    }
93  
94    @Override
95    public ReturnCode filterKeyValue(KeyValue v) {
96      if (this.timestamps.contains(v.getTimestamp())) {
97        return ReturnCode.INCLUDE;
98      } else if (v.getTimestamp() < minTimeStamp) {
99        // The remaining versions of this column are guaranteed
100       // to be lesser than all of the other values.
101       return ReturnCode.NEXT_COL;
102     }
103     return ReturnCode.SKIP;
104   }
105 
106   public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
107     ArrayList<Long> timestamps = new ArrayList<Long>();
108     for (int i = 0; i<filterArguments.size(); i++) {
109       long timestamp = ParseFilter.convertByteArrayToLong(filterArguments.get(i));
110       timestamps.add(timestamp);
111     }
112     return new TimestampsFilter(timestamps);
113   }
114 
115   @Override
116   public void readFields(DataInput in) throws IOException {
117     int numTimestamps = in.readInt();
118     this.timestamps = new TreeSet<Long>();
119     for (int idx = 0; idx < numTimestamps; idx++) {
120       this.timestamps.add(in.readLong());
121     }
122     init();
123   }
124 
125   @Override
126   public void write(DataOutput out) throws IOException {
127     int numTimestamps = this.timestamps.size();
128     out.writeInt(numTimestamps);
129     for (Long timestamp : this.timestamps) {
130       out.writeLong(timestamp);
131     }
132   }
133 
134   @Override
135   public String toString() {
136     return toString(MAX_LOG_TIMESTAMPS);
137   }
138 
139   protected String toString(int maxTimestamps) {
140     StringBuilder tsList = new StringBuilder();
141 
142     int count = 0;
143     for (Long ts : this.timestamps) {
144       if (count >= maxTimestamps) {
145         break;
146       }
147       ++count;
148       tsList.append(ts.toString());
149       if (count < this.timestamps.size() && count < maxTimestamps) {
150         tsList.append(", ");
151       }
152     }
153 
154     return String.format("%s (%d/%d): [%s]", this.getClass().getSimpleName(),
155         count, this.timestamps.size(), tsList.toString());
156   }
157 }