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.List;
24  
25  import javax.ws.rs.DefaultValue;
26  import javax.ws.rs.Encoded;
27  import javax.ws.rs.Path;
28  import javax.ws.rs.PathParam;
29  import javax.ws.rs.QueryParam;
30  
31  import org.apache.commons.lang.StringUtils;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.hbase.KeyValue;
35  import org.apache.hadoop.hbase.TableName;
36  import org.apache.hadoop.hbase.classification.InterfaceAudience;
37  import org.apache.hadoop.hbase.client.Scan;
38  import org.apache.hadoop.hbase.client.Table;
39  import org.apache.hadoop.hbase.filter.Filter;
40  import org.apache.hadoop.hbase.filter.FilterList;
41  import org.apache.hadoop.hbase.filter.ParseFilter;
42  import org.apache.hadoop.hbase.filter.PrefixFilter;
43  import org.apache.hadoop.hbase.util.Bytes;
44  
45  @InterfaceAudience.Private
46  public class TableResource extends ResourceBase {
47  
48    String table;
49    private static final Log LOG = LogFactory.getLog(TableResource.class);
50  
51    /**
52     * Constructor
53     * @param table
54     * @throws IOException
55     */
56    public TableResource(String table) throws IOException {
57      super();
58      this.table = table;
59    }
60  
61    /** @return the table name */
62    String getName() {
63      return table;
64    }
65  
66    /**
67     * @return true if the table exists
68     * @throws IOException
69     */
70    boolean exists() throws IOException {
71      return servlet.getAdmin().tableExists(TableName.valueOf(table));
72    }
73  
74    @Path("exists")
75    public ExistsResource getExistsResource() throws IOException {
76      return new ExistsResource(this);
77    }
78  
79    @Path("regions")
80    public RegionsResource getRegionsResource() throws IOException {
81      return new RegionsResource(this);
82    }
83  
84    @Path("scanner")
85    public ScannerResource getScannerResource() throws IOException {
86      return new ScannerResource(this);
87    }
88  
89    @Path("schema")
90    public SchemaResource getSchemaResource() throws IOException {
91      return new SchemaResource(this);
92    }
93  
94    @Path("{multiget: multiget.*}")
95    public MultiRowResource getMultipleRowResource(final @QueryParam("v") String versions,
96        @PathParam("multiget") String path) throws IOException {
97      return new MultiRowResource(this, versions, path.replace("multiget", "").replace("/", ""));
98    }
99  
100   @Path("{rowspec: [^*]+}")
101   public RowResource getRowResource(
102       // We need the @Encoded decorator so Jersey won't urldecode before
103       // the RowSpec constructor has a chance to parse
104       final @PathParam("rowspec") @Encoded String rowspec,
105       final @QueryParam("v") String versions,
106       final @QueryParam("check") String check,
107       final @QueryParam("rr") String returnResult) throws IOException {
108     return new RowResource(this, rowspec, versions, check, returnResult);
109   }
110 
111   @Path("{suffixglobbingspec: .*\\*/.+}")
112   public RowResource getRowResourceWithSuffixGlobbing(
113       // We need the @Encoded decorator so Jersey won't urldecode before
114       // the RowSpec constructor has a chance to parse
115       final @PathParam("suffixglobbingspec") @Encoded String suffixglobbingspec,
116       final @QueryParam("v") String versions,
117       final @QueryParam("check") String check,
118       final @QueryParam("rr") String returnResult) throws IOException {
119     return new RowResource(this, suffixglobbingspec, versions, check, returnResult);
120   }
121 
122   @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="REC_CATCH_EXCEPTION")
123   @Path("{scanspec: .*[*]$}")
124   public TableScanResource  getScanResource(
125       final @PathParam("scanspec") String scanSpec,
126       @DefaultValue(Integer.MAX_VALUE + "")
127       @QueryParam(Constants.SCAN_LIMIT) int userRequestedLimit,
128       @DefaultValue("") @QueryParam(Constants.SCAN_START_ROW) String startRow,
129       @DefaultValue("") @QueryParam(Constants.SCAN_END_ROW) String endRow,
130       @QueryParam(Constants.SCAN_COLUMN) List<String> column,
131       @DefaultValue("1") @QueryParam(Constants.SCAN_MAX_VERSIONS) int maxVersions,
132       @DefaultValue("-1") @QueryParam(Constants.SCAN_BATCH_SIZE) int batchSize,
133       @DefaultValue("0") @QueryParam(Constants.SCAN_START_TIME) long startTime,
134       @DefaultValue(Long.MAX_VALUE + "") @QueryParam(Constants.SCAN_END_TIME) long endTime,
135       @DefaultValue("true") @QueryParam(Constants.SCAN_CACHE_BLOCKS) boolean cacheBlocks,
136       @DefaultValue("false") @QueryParam(Constants.SCAN_REVERSED) boolean reversed,
137       @DefaultValue("") @QueryParam(Constants.SCAN_FILTER) String paramFilter) {
138     try {
139       Filter prefixFilter = null;
140       Scan tableScan = new Scan();
141       if (scanSpec.indexOf('*') > 0) {
142         String prefix = scanSpec.substring(0, scanSpec.indexOf('*'));
143         byte[] prefixBytes = Bytes.toBytes(prefix);
144         prefixFilter = new PrefixFilter(Bytes.toBytes(prefix));
145         if (startRow.isEmpty()) {
146           tableScan.setStartRow(prefixBytes);
147         }
148       }
149       if (LOG.isTraceEnabled()) {
150         LOG.trace("Query parameters  : Table Name = > " + this.table + " Start Row => " + startRow
151             + " End Row => " + endRow + " Columns => " + column + " Start Time => " + startTime
152             + " End Time => " + endTime + " Cache Blocks => " + cacheBlocks + " Max Versions => "
153             + maxVersions + " Batch Size => " + batchSize);
154       }
155       Table hTable = RESTServlet.getInstance().getTable(this.table);
156       tableScan.setBatch(batchSize);
157       tableScan.setMaxVersions(maxVersions);
158       tableScan.setTimeRange(startTime, endTime);
159       if (!startRow.isEmpty()) {
160         tableScan.setStartRow(Bytes.toBytes(startRow));
161       }
162       tableScan.setStopRow(Bytes.toBytes(endRow));
163       for (String col : column) {
164         byte [][] parts = KeyValue.parseColumn(Bytes.toBytes(col.trim()));
165         if (parts.length == 1) {
166           if (LOG.isTraceEnabled()) {
167             LOG.trace("Scan family : " + Bytes.toStringBinary(parts[0]));
168           }
169           tableScan.addFamily(parts[0]);
170         } else if (parts.length == 2) {
171           if (LOG.isTraceEnabled()) {
172             LOG.trace("Scan family and column : " + Bytes.toStringBinary(parts[0])
173                 + "  " + Bytes.toStringBinary(parts[1]));
174           }
175           tableScan.addColumn(parts[0], parts[1]);
176         } else {
177           throw new IllegalArgumentException("Invalid column specifier.");
178         }
179       }
180 
181       FilterList filterList = new FilterList();
182       if (StringUtils.isNotEmpty(paramFilter)) {
183         ParseFilter pf = new ParseFilter();
184         Filter parsedParamFilter = pf.parseFilterString(paramFilter);
185         if (parsedParamFilter != null) {
186           filterList.addFilter(parsedParamFilter);
187         }
188         if (prefixFilter != null) {
189           filterList.addFilter(prefixFilter);
190         }
191       }
192 
193       if (filterList.getFilters().size() > 0) {
194         tableScan.setFilter(filterList);
195       }
196 
197       int fetchSize = this.servlet.getConfiguration().getInt(Constants.SCAN_FETCH_SIZE, 10);
198       tableScan.setCaching(fetchSize);
199       tableScan.setReversed(reversed);
200       tableScan.setCacheBlocks(cacheBlocks);
201       return new TableScanResource(hTable.getScanner(tableScan), userRequestedLimit);
202     } catch (Exception exp) {
203       servlet.getMetrics().incrementFailedScanRequests(1);
204       processException(exp);
205       LOG.warn(exp);
206       return null;
207     }
208   }
209 }