001/* 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020package org.apache.hadoop.hbase.rest; 021 022import java.io.IOException; 023import java.util.List; 024import javax.ws.rs.DefaultValue; 025import javax.ws.rs.Encoded; 026import javax.ws.rs.Path; 027import javax.ws.rs.PathParam; 028import javax.ws.rs.QueryParam; 029import org.apache.commons.lang3.StringUtils; 030import org.apache.hadoop.hbase.TableName; 031import org.apache.yetus.audience.InterfaceAudience; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034import org.apache.hadoop.hbase.client.Scan; 035import org.apache.hadoop.hbase.client.Table; 036import org.apache.hadoop.hbase.filter.Filter; 037import org.apache.hadoop.hbase.filter.FilterList; 038import org.apache.hadoop.hbase.filter.ParseFilter; 039import org.apache.hadoop.hbase.filter.PrefixFilter; 040import org.apache.hadoop.hbase.util.Bytes; 041 042@InterfaceAudience.Private 043public class TableResource extends ResourceBase { 044 045 String table; 046 private static final Logger LOG = LoggerFactory.getLogger(TableResource.class); 047 048 /** 049 * Constructor 050 * @param table 051 * @throws IOException 052 */ 053 public TableResource(String table) throws IOException { 054 super(); 055 this.table = table; 056 } 057 058 /** @return the table name */ 059 String getName() { 060 return table; 061 } 062 063 /** 064 * @return true if the table exists 065 * @throws IOException 066 */ 067 boolean exists() throws IOException { 068 return servlet.getAdmin().tableExists(TableName.valueOf(table)); 069 } 070 071 @Path("exists") 072 public ExistsResource getExistsResource() throws IOException { 073 return new ExistsResource(this); 074 } 075 076 @Path("regions") 077 public RegionsResource getRegionsResource() throws IOException { 078 return new RegionsResource(this); 079 } 080 081 @Path("scanner") 082 public ScannerResource getScannerResource() throws IOException { 083 return new ScannerResource(this); 084 } 085 086 @Path("schema") 087 public SchemaResource getSchemaResource() throws IOException { 088 return new SchemaResource(this); 089 } 090 091 @Path("{multiget: multiget.*}") 092 public MultiRowResource getMultipleRowResource(final @QueryParam("v") String versions, 093 @PathParam("multiget") String path) throws IOException { 094 return new MultiRowResource(this, versions, path.replace("multiget", "").replace("/", "")); 095 } 096 097 @Path("{rowspec: [^*]+}") 098 public RowResource getRowResource( 099 // We need the @Encoded decorator so Jersey won't urldecode before 100 // the RowSpec constructor has a chance to parse 101 final @PathParam("rowspec") @Encoded String rowspec, 102 final @QueryParam("v") String versions, 103 final @QueryParam("check") String check, 104 final @QueryParam("rr") String returnResult) throws IOException { 105 return new RowResource(this, rowspec, versions, check, returnResult); 106 } 107 108 @Path("{suffixglobbingspec: .*\\*/.+}") 109 public RowResource getRowResourceWithSuffixGlobbing( 110 // We need the @Encoded decorator so Jersey won't urldecode before 111 // the RowSpec constructor has a chance to parse 112 final @PathParam("suffixglobbingspec") @Encoded String suffixglobbingspec, 113 final @QueryParam("v") String versions, 114 final @QueryParam("check") String check, 115 final @QueryParam("rr") String returnResult) throws IOException { 116 return new RowResource(this, suffixglobbingspec, versions, check, returnResult); 117 } 118 119 @Path("{scanspec: .*[*]$}") 120 public TableScanResource getScanResource( 121 final @PathParam("scanspec") String scanSpec, 122 @DefaultValue(Integer.MAX_VALUE + "") 123 @QueryParam(Constants.SCAN_LIMIT) int userRequestedLimit, 124 @DefaultValue("") @QueryParam(Constants.SCAN_START_ROW) String startRow, 125 @DefaultValue("") @QueryParam(Constants.SCAN_END_ROW) String endRow, 126 @DefaultValue("") @QueryParam(Constants.SCAN_COLUMN) List<String> column, 127 @DefaultValue("1") @QueryParam(Constants.SCAN_MAX_VERSIONS) int maxVersions, 128 @DefaultValue("-1") @QueryParam(Constants.SCAN_BATCH_SIZE) int batchSize, 129 @DefaultValue("0") @QueryParam(Constants.SCAN_START_TIME) long startTime, 130 @DefaultValue(Long.MAX_VALUE + "") @QueryParam(Constants.SCAN_END_TIME) long endTime, 131 @DefaultValue("true") @QueryParam(Constants.SCAN_CACHE_BLOCKS) boolean cacheBlocks, 132 @DefaultValue("false") @QueryParam(Constants.SCAN_REVERSED) boolean reversed, 133 @DefaultValue("") @QueryParam(Constants.SCAN_FILTER) String paramFilter) { 134 try { 135 Filter prefixFilter = null; 136 Scan tableScan = new Scan(); 137 if (scanSpec.indexOf('*') > 0) { 138 String prefix = scanSpec.substring(0, scanSpec.indexOf('*')); 139 byte[] prefixBytes = Bytes.toBytes(prefix); 140 prefixFilter = new PrefixFilter(Bytes.toBytes(prefix)); 141 if (startRow.isEmpty()) { 142 tableScan.setStartRow(prefixBytes); 143 } 144 } 145 if (LOG.isTraceEnabled()) { 146 LOG.trace("Query parameters : Table Name = > " + this.table + " Start Row => " + startRow 147 + " End Row => " + endRow + " Columns => " + column + " Start Time => " + startTime 148 + " End Time => " + endTime + " Cache Blocks => " + cacheBlocks + " Max Versions => " 149 + maxVersions + " Batch Size => " + batchSize); 150 } 151 Table hTable = RESTServlet.getInstance().getTable(this.table); 152 tableScan.setBatch(batchSize); 153 tableScan.setMaxVersions(maxVersions); 154 tableScan.setTimeRange(startTime, endTime); 155 if (!startRow.isEmpty()) { 156 tableScan.setStartRow(Bytes.toBytes(startRow)); 157 } 158 tableScan.setStopRow(Bytes.toBytes(endRow)); 159 for (String csplit : column) { 160 String[] familysplit = csplit.trim().split(":"); 161 if (familysplit.length == 2) { 162 if (familysplit[1].length() > 0) { 163 if (LOG.isTraceEnabled()) { 164 LOG.trace("Scan family and column : " + familysplit[0] + " " + familysplit[1]); 165 } 166 tableScan.addColumn(Bytes.toBytes(familysplit[0]), Bytes.toBytes(familysplit[1])); 167 } else { 168 tableScan.addFamily(Bytes.toBytes(familysplit[0])); 169 if (LOG.isTraceEnabled()) { 170 LOG.trace("Scan family : " + familysplit[0] + " and empty qualifier."); 171 } 172 tableScan.addColumn(Bytes.toBytes(familysplit[0]), null); 173 } 174 } else if (StringUtils.isNotEmpty(familysplit[0])) { 175 if (LOG.isTraceEnabled()) { 176 LOG.trace("Scan family : " + familysplit[0]); 177 } 178 tableScan.addFamily(Bytes.toBytes(familysplit[0])); 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 if (filterList.size() > 0) { 193 tableScan.setFilter(filterList); 194 } 195 196 int fetchSize = this.servlet.getConfiguration().getInt(Constants.SCAN_FETCH_SIZE, 10); 197 tableScan.setCaching(fetchSize); 198 tableScan.setReversed(reversed); 199 tableScan.setCacheBlocks(cacheBlocks); 200 return new TableScanResource(hTable.getScanner(tableScan), userRequestedLimit); 201 } catch (IOException exp) { 202 servlet.getMetrics().incrementFailedScanRequests(1); 203 processException(exp); 204 LOG.warn(exp.toString(), exp); 205 return null; 206 } 207 } 208}