001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.rest; 019 020import com.fasterxml.jackson.annotation.JsonIgnore; 021import com.fasterxml.jackson.annotation.JsonProperty; 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.Iterator; 025import javax.xml.bind.annotation.XmlAccessType; 026import javax.xml.bind.annotation.XmlAccessorType; 027import javax.xml.bind.annotation.XmlElement; 028import javax.xml.bind.annotation.XmlRootElement; 029import org.apache.hadoop.hbase.client.Result; 030import org.apache.hadoop.hbase.client.ResultScanner; 031import org.apache.hadoop.hbase.rest.model.RowModel; 032import org.apache.yetus.audience.InterfaceAudience; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import org.apache.hbase.thirdparty.javax.ws.rs.GET; 037import org.apache.hbase.thirdparty.javax.ws.rs.HeaderParam; 038import org.apache.hbase.thirdparty.javax.ws.rs.Produces; 039import org.apache.hbase.thirdparty.javax.ws.rs.core.Context; 040import org.apache.hbase.thirdparty.javax.ws.rs.core.Response; 041import org.apache.hbase.thirdparty.javax.ws.rs.core.Response.ResponseBuilder; 042import org.apache.hbase.thirdparty.javax.ws.rs.core.StreamingOutput; 043import org.apache.hbase.thirdparty.javax.ws.rs.core.UriInfo; 044 045@InterfaceAudience.Private 046public class TableScanResource extends ResourceBase { 047 private static final Logger LOG = LoggerFactory.getLogger(TableScanResource.class); 048 049 TableResource tableResource; 050 ResultScanner results; 051 int userRequestedLimit; 052 053 public TableScanResource(ResultScanner scanner, int userRequestedLimit) throws IOException { 054 super(); 055 this.results = scanner; 056 this.userRequestedLimit = userRequestedLimit; 057 } 058 059 @GET 060 @Produces({ Constants.MIMETYPE_XML, Constants.MIMETYPE_JSON }) 061 public CellSetModelStream get(final @Context UriInfo uriInfo) { 062 if (LOG.isTraceEnabled()) { 063 LOG.trace("GET " + uriInfo.getAbsolutePath()); 064 } 065 servlet.getMetrics().incrementRequests(1); 066 final int rowsToSend = userRequestedLimit; 067 servlet.getMetrics().incrementSucessfulScanRequests(1); 068 final Iterator<Result> itr = results.iterator(); 069 return new CellSetModelStream(new ArrayList<RowModel>() { 070 @Override 071 public Iterator<RowModel> iterator() { 072 return new Iterator<RowModel>() { 073 int count = rowsToSend; 074 075 @Override 076 public boolean hasNext() { 077 return count > 0 && itr.hasNext(); 078 } 079 080 @Override 081 public RowModel next() { 082 Result rs = itr.next(); 083 if ((rs == null) || (count <= 0)) { 084 return null; 085 } 086 RowModel rModel = RestUtil.createRowModelFromResult(rs); 087 count--; 088 if (count == 0) { 089 results.close(); 090 } 091 return rModel; 092 } 093 }; 094 } 095 }); 096 } 097 098 @GET 099 @Produces({ Constants.MIMETYPE_PROTOBUF, Constants.MIMETYPE_PROTOBUF_IETF }) 100 public Response getProtobuf(final @Context UriInfo uriInfo, 101 final @HeaderParam("Accept") String contentType) { 102 if (LOG.isTraceEnabled()) { 103 LOG.trace("GET " + uriInfo.getAbsolutePath() + " as " + MIMETYPE_BINARY); 104 } 105 servlet.getMetrics().incrementRequests(1); 106 try { 107 int fetchSize = this.servlet.getConfiguration().getInt(Constants.SCAN_FETCH_SIZE, 10); 108 StreamingOutput stream = 109 new ProtobufStreamingOutput(this.results, contentType, userRequestedLimit, fetchSize); 110 servlet.getMetrics().incrementSucessfulScanRequests(1); 111 ResponseBuilder response = Response.ok(stream); 112 response.header("content-type", contentType); 113 return response.build(); 114 } catch (Exception exp) { 115 servlet.getMetrics().incrementFailedScanRequests(1); 116 processException(exp); 117 LOG.warn(exp.toString(), exp); 118 return null; 119 } 120 } 121 122 @XmlRootElement(name = "CellSet") 123 @XmlAccessorType(XmlAccessType.FIELD) 124 public static class CellSetModelStream { 125 // JAXB needs an arraylist for streaming 126 @XmlElement(name = "Row") 127 @JsonIgnore 128 private ArrayList<RowModel> Row; 129 130 public CellSetModelStream() { 131 } 132 133 public CellSetModelStream(final ArrayList<RowModel> rowList) { 134 this.Row = rowList; 135 } 136 137 // jackson needs an iterator for streaming 138 @JsonProperty("Row") 139 public Iterator<RowModel> getIterator() { 140 return Row.iterator(); 141 } 142 } 143}