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.rest;
21  
22  import java.io.IOException;
23  import java.util.Iterator;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.classification.InterfaceAudience;
28  import org.apache.hadoop.hbase.Cell;
29  import org.apache.hadoop.hbase.KeyValue;
30  import org.apache.hadoop.hbase.UnknownScannerException;
31  import org.apache.hadoop.hbase.client.HTableInterface;
32  import org.apache.hadoop.hbase.client.Result;
33  import org.apache.hadoop.hbase.client.ResultScanner;
34  import org.apache.hadoop.hbase.client.Scan;
35  import org.apache.hadoop.hbase.filter.Filter;
36  import org.apache.hadoop.hbase.rest.model.ScannerModel;
37  import org.apache.hadoop.util.StringUtils;
38  
39  @InterfaceAudience.Private
40  public class ScannerResultGenerator extends ResultGenerator {
41  
42    private static final Log LOG =
43      LogFactory.getLog(ScannerResultGenerator.class);
44  
45    public static Filter buildFilterFromModel(final ScannerModel model) 
46        throws Exception {
47      String filter = model.getFilter();
48      if (filter == null || filter.length() == 0) {
49        return null;
50      }
51      return buildFilter(filter);
52    }
53  
54    private String id;
55    private Iterator<Cell> rowI;
56    private Cell cache;
57    private ResultScanner scanner;
58    private Result cached;
59  
60    public ScannerResultGenerator(final String tableName, final RowSpec rowspec,
61        final Filter filter) throws IllegalArgumentException, IOException {
62      this(tableName, rowspec, filter, -1);
63    }
64  
65    public ScannerResultGenerator(final String tableName, final RowSpec rowspec,
66        final Filter filter, final int caching) throws IllegalArgumentException, IOException {
67      HTableInterface table = RESTServlet.getInstance().getTable(tableName);
68      try {
69        Scan scan;
70        if (rowspec.hasEndRow()) {
71          scan = new Scan(rowspec.getStartRow(), rowspec.getEndRow());
72        } else {
73          scan = new Scan(rowspec.getStartRow());
74        }
75        if (rowspec.hasColumns()) {
76          byte[][] columns = rowspec.getColumns();
77          for (byte[] column: columns) {
78            byte[][] split = KeyValue.parseColumn(column);
79            if (split.length == 1) {
80              scan.addFamily(split[0]);
81            } else if (split.length == 2) {
82              scan.addColumn(split[0], split[1]);
83            } else {
84              throw new IllegalArgumentException("Invalid familyAndQualifier provided.");
85            }
86          }
87        }
88        scan.setTimeRange(rowspec.getStartTime(), rowspec.getEndTime());          
89        scan.setMaxVersions(rowspec.getMaxVersions());
90        if (filter != null) {
91          scan.setFilter(filter);
92        }
93        // always disable block caching on the cluster when scanning
94        scan.setCacheBlocks(false);
95        if (caching > 0 ) {
96          scan.setCaching(caching);
97        }
98        scanner = table.getScanner(scan);
99        cached = null;
100       id = Long.toString(System.currentTimeMillis()) +
101              Integer.toHexString(scanner.hashCode());
102     } finally {
103       table.close();
104     }
105   }
106 
107   public String getID() {
108     return id;
109   }
110 
111   public void close() {
112     if (scanner != null) {
113       scanner.close();
114       scanner = null;
115     }
116   }
117 
118   public boolean hasNext() {
119     if (cache != null) {
120       return true;
121     }
122     if (rowI != null && rowI.hasNext()) {
123       return true;
124     }
125     if (cached != null) {
126       return true;
127     }
128     try {
129       Result result = scanner.next();
130       if (result != null && !result.isEmpty()) {
131         cached = result;
132       }
133     } catch (UnknownScannerException e) {
134       throw new IllegalArgumentException(e);
135     } catch (IOException e) {
136       LOG.error(StringUtils.stringifyException(e));
137     }
138     return cached != null;
139   }
140 
141   public Cell next() {
142     if (cache != null) {
143       Cell kv = cache;
144       cache = null;
145       return kv;
146     }
147     boolean loop;
148     do {
149       loop = false;
150       if (rowI != null) {
151         if (rowI.hasNext()) {
152           return rowI.next();
153         } else {
154           rowI = null;
155         }
156       }
157       if (cached != null) {
158         rowI = cached.listCells().iterator();
159         loop = true;
160         cached = null;
161       } else {
162         Result result = null;
163         try {
164           result = scanner.next();
165         } catch (UnknownScannerException e) {
166           throw new IllegalArgumentException(e);
167         } catch (IOException e) {
168           LOG.error(StringUtils.stringifyException(e));
169         }
170         if (result != null && !result.isEmpty()) {
171           rowI = result.listCells().iterator();
172           loop = true;
173         }
174       }
175     } while (loop);
176     return null;
177   }
178 
179   public void putBack(Cell kv) {
180     this.cache = kv;
181   }
182 
183   public void remove() {
184     throw new UnsupportedOperationException("remove not supported");
185   }
186 }