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.KeyValue;
29  import org.apache.hadoop.hbase.UnknownScannerException;
30  import org.apache.hadoop.hbase.client.HTableInterface;
31  import org.apache.hadoop.hbase.client.HTablePool;
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<KeyValue> rowI;
56    private KeyValue 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      HTablePool pool = RESTServlet.getInstance().getTablePool();
68      HTableInterface table = pool.getTable(tableName);
69      try {
70        Scan scan;
71        if (rowspec.hasEndRow()) {
72          scan = new Scan(rowspec.getStartRow(), rowspec.getEndRow());
73        } else {
74          scan = new Scan(rowspec.getStartRow());
75        }
76        if (rowspec.hasColumns()) {
77          byte[][] columns = rowspec.getColumns();
78          for (byte[] column: columns) {
79            byte[][] split = KeyValue.parseColumn(column);
80            if (split.length > 1 && (split[1] != null && split[1].length != 0)) {
81              scan.addColumn(split[0], split[1]);
82            } else {
83              scan.addFamily(split[0]);
84            }
85          }
86        }
87        scan.setTimeRange(rowspec.getStartTime(), rowspec.getEndTime());          
88        scan.setMaxVersions(rowspec.getMaxVersions());
89        if (filter != null) {
90          scan.setFilter(filter);
91        }
92        // always disable block caching on the cluster when scanning
93        scan.setCacheBlocks(false);
94        if (caching > 0 ) {
95          scan.setCaching(caching);
96        }
97        scanner = table.getScanner(scan);
98        cached = null;
99        id = Long.toString(System.currentTimeMillis()) +
100              Integer.toHexString(scanner.hashCode());
101     } finally {
102       table.close();
103     }
104   }
105 
106   public String getID() {
107     return id;
108   }
109 
110   public void close() {
111   }
112 
113   public boolean hasNext() {
114     if (cache != null) {
115       return true;
116     }
117     if (rowI != null && rowI.hasNext()) {
118       return true;
119     }
120     if (cached != null) {
121       return true;
122     }
123     try {
124       Result result = scanner.next();
125       if (result != null && !result.isEmpty()) {
126         cached = result;
127       }
128     } catch (UnknownScannerException e) {
129       throw new IllegalArgumentException(e);
130     } catch (IOException e) {
131       LOG.error(StringUtils.stringifyException(e));
132     }
133     return cached != null;
134   }
135 
136   public KeyValue next() {
137     if (cache != null) {
138       KeyValue kv = cache;
139       cache = null;
140       return kv;
141     }
142     boolean loop;
143     do {
144       loop = false;
145       if (rowI != null) {
146         if (rowI.hasNext()) {
147           return rowI.next();
148         } else {
149           rowI = null;
150         }
151       }
152       if (cached != null) {
153         rowI = cached.list().iterator();
154         loop = true;
155         cached = null;
156       } else {
157         Result result = null;
158         try {
159           result = scanner.next();
160         } catch (UnknownScannerException e) {
161           throw new IllegalArgumentException(e);
162         } catch (IOException e) {
163           LOG.error(StringUtils.stringifyException(e));
164         }
165         if (result != null && !result.isEmpty()) {
166           rowI = result.list().iterator();
167           loop = true;
168         }
169       }
170     } while (loop);
171     return null;
172   }
173 
174   public void putBack(KeyValue kv) {
175     this.cache = kv;
176   }
177 
178   public void remove() {
179     throw new UnsupportedOperationException("remove not supported");
180   }
181 }