HBASE-26921 Rewrite the counting cells part in TestMultiVersions (#4316)
[hbase.git] / hbase-rest / src / main / java / org / apache / hadoop / hbase / rest / TableResource.java
bloba7a40b859a04c77b54fe889fd220689487608a66
1 /*
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 package org.apache.hadoop.hbase.rest;
22 import java.io.IOException;
23 import java.util.List;
24 import org.apache.commons.lang3.StringUtils;
25 import org.apache.hadoop.hbase.CellUtil;
26 import org.apache.hadoop.hbase.TableName;
27 import org.apache.hadoop.hbase.client.Scan;
28 import org.apache.hadoop.hbase.client.Table;
29 import org.apache.hadoop.hbase.filter.Filter;
30 import org.apache.hadoop.hbase.filter.FilterList;
31 import org.apache.hadoop.hbase.filter.ParseFilter;
32 import org.apache.hadoop.hbase.filter.PrefixFilter;
33 import org.apache.hadoop.hbase.util.Bytes;
34 import org.apache.yetus.audience.InterfaceAudience;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import org.apache.hbase.thirdparty.javax.ws.rs.DefaultValue;
39 import org.apache.hbase.thirdparty.javax.ws.rs.Encoded;
40 import org.apache.hbase.thirdparty.javax.ws.rs.Path;
41 import org.apache.hbase.thirdparty.javax.ws.rs.PathParam;
42 import org.apache.hbase.thirdparty.javax.ws.rs.QueryParam;
44 @InterfaceAudience.Private
45 public class TableResource extends ResourceBase {
47 String table;
48 private static final Logger LOG = LoggerFactory.getLogger(TableResource.class);
50 /**
51 * Constructor
52 * @param table
53 * @throws IOException
55 public TableResource(String table) throws IOException {
56 super();
57 this.table = table;
60 /** @return the table name */
61 String getName() {
62 return table;
65 /**
66 * @return true if the table exists
67 * @throws IOException
69 boolean exists() throws IOException {
70 return servlet.getAdmin().tableExists(TableName.valueOf(table));
73 @Path("exists")
74 public ExistsResource getExistsResource() throws IOException {
75 return new ExistsResource(this);
78 @Path("regions")
79 public RegionsResource getRegionsResource() throws IOException {
80 return new RegionsResource(this);
83 @Path("scanner")
84 public ScannerResource getScannerResource() throws IOException {
85 return new ScannerResource(this);
88 @Path("schema")
89 public SchemaResource getSchemaResource() throws IOException {
90 return new SchemaResource(this);
93 @Path("{multiget: multiget.*}")
94 public MultiRowResource getMultipleRowResource(final @QueryParam("v") String versions,
95 @PathParam("multiget") String path) throws IOException {
96 return new MultiRowResource(this, versions, path.replace("multiget", "").replace("/", ""));
99 @Path("{rowspec: [^*]+}")
100 public RowResource getRowResource(
101 // We need the @Encoded decorator so Jersey won't urldecode before
102 // the RowSpec constructor has a chance to parse
103 final @PathParam("rowspec") @Encoded String rowspec,
104 final @QueryParam("v") String versions,
105 final @QueryParam("check") String check,
106 final @QueryParam("rr") String returnResult) throws IOException {
107 return new RowResource(this, rowspec, versions, check, returnResult);
110 @Path("{suffixglobbingspec: .*\\*/.+}")
111 public RowResource getRowResourceWithSuffixGlobbing(
112 // We need the @Encoded decorator so Jersey won't urldecode before
113 // the RowSpec constructor has a chance to parse
114 final @PathParam("suffixglobbingspec") @Encoded String suffixglobbingspec,
115 final @QueryParam("v") String versions,
116 final @QueryParam("check") String check,
117 final @QueryParam("rr") String returnResult) throws IOException {
118 return new RowResource(this, suffixglobbingspec, versions, check, returnResult);
121 @Path("{scanspec: .*[*]$}")
122 public TableScanResource getScanResource(
123 final @PathParam("scanspec") String scanSpec,
124 @DefaultValue(Integer.MAX_VALUE + "")
125 @QueryParam(Constants.SCAN_LIMIT) int userRequestedLimit,
126 @DefaultValue("") @QueryParam(Constants.SCAN_START_ROW) String startRow,
127 @DefaultValue("") @QueryParam(Constants.SCAN_END_ROW) String endRow,
128 @QueryParam(Constants.SCAN_COLUMN) List<String> column,
129 @DefaultValue("1") @QueryParam(Constants.SCAN_MAX_VERSIONS) int maxVersions,
130 @DefaultValue("-1") @QueryParam(Constants.SCAN_BATCH_SIZE) int batchSize,
131 @DefaultValue("0") @QueryParam(Constants.SCAN_START_TIME) long startTime,
132 @DefaultValue(Long.MAX_VALUE + "") @QueryParam(Constants.SCAN_END_TIME) long endTime,
133 @DefaultValue("true") @QueryParam(Constants.SCAN_CACHE_BLOCKS) boolean cacheBlocks,
134 @DefaultValue("false") @QueryParam(Constants.SCAN_REVERSED) boolean reversed,
135 @DefaultValue("") @QueryParam(Constants.SCAN_FILTER) String paramFilter) {
136 try {
137 Filter prefixFilter = null;
138 Scan tableScan = new Scan();
139 if (scanSpec.indexOf('*') > 0) {
140 String prefix = scanSpec.substring(0, scanSpec.indexOf('*'));
141 byte[] prefixBytes = Bytes.toBytes(prefix);
142 prefixFilter = new PrefixFilter(Bytes.toBytes(prefix));
143 if (startRow.isEmpty()) {
144 tableScan.withStartRow(prefixBytes);
147 if (LOG.isTraceEnabled()) {
148 LOG.trace("Query parameters : Table Name = > " + this.table + " Start Row => " + startRow
149 + " End Row => " + endRow + " Columns => " + column + " Start Time => " + startTime
150 + " End Time => " + endTime + " Cache Blocks => " + cacheBlocks + " Max Versions => "
151 + maxVersions + " Batch Size => " + batchSize);
153 Table hTable = RESTServlet.getInstance().getTable(this.table);
154 tableScan.setBatch(batchSize);
155 tableScan.readVersions(maxVersions);
156 tableScan.setTimeRange(startTime, endTime);
157 if (!startRow.isEmpty()) {
158 tableScan.withStartRow(Bytes.toBytes(startRow));
160 tableScan.withStopRow(Bytes.toBytes(endRow));
161 for (String col : column) {
162 byte [][] parts = CellUtil.parseColumn(Bytes.toBytes(col.trim()));
163 if (parts.length == 1) {
164 if (LOG.isTraceEnabled()) {
165 LOG.trace("Scan family : " + Bytes.toStringBinary(parts[0]));
167 tableScan.addFamily(parts[0]);
168 } else if (parts.length == 2) {
169 if (LOG.isTraceEnabled()) {
170 LOG.trace("Scan family and column : " + Bytes.toStringBinary(parts[0])
171 + " " + Bytes.toStringBinary(parts[1]));
173 tableScan.addColumn(parts[0], parts[1]);
174 } else {
175 throw new IllegalArgumentException("Invalid column specifier.");
178 FilterList filterList = new FilterList();
179 if (StringUtils.isNotEmpty(paramFilter)) {
180 ParseFilter pf = new ParseFilter();
181 Filter parsedParamFilter = pf.parseFilterString(paramFilter);
182 if (parsedParamFilter != null) {
183 filterList.addFilter(parsedParamFilter);
185 if (prefixFilter != null) {
186 filterList.addFilter(prefixFilter);
189 if (filterList.size() > 0) {
190 tableScan.setFilter(filterList);
193 int fetchSize = this.servlet.getConfiguration().getInt(Constants.SCAN_FETCH_SIZE, 10);
194 tableScan.setCaching(fetchSize);
195 tableScan.setReversed(reversed);
196 tableScan.setCacheBlocks(cacheBlocks);
197 return new TableScanResource(hTable.getScanner(tableScan), userRequestedLimit);
198 } catch (IOException exp) {
199 servlet.getMetrics().incrementFailedScanRequests(1);
200 processException(exp);
201 LOG.warn(exp.toString(), exp);
202 return null;