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 */ 019package org.apache.hadoop.hbase.rest; 020 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.Iterator; 024import java.util.List; 025 026import javax.ws.rs.GET; 027import javax.ws.rs.HeaderParam; 028import javax.ws.rs.Produces; 029import javax.ws.rs.core.Context; 030import javax.ws.rs.core.Response; 031import javax.ws.rs.core.Response.ResponseBuilder; 032import javax.ws.rs.core.StreamingOutput; 033import javax.ws.rs.core.UriInfo; 034import javax.xml.bind.annotation.XmlAccessType; 035import javax.xml.bind.annotation.XmlAccessorType; 036import javax.xml.bind.annotation.XmlElement; 037import javax.xml.bind.annotation.XmlRootElement; 038 039import org.apache.hadoop.hbase.Cell; 040import org.apache.hadoop.hbase.CellUtil; 041import org.apache.hadoop.hbase.client.Result; 042import org.apache.hadoop.hbase.client.ResultScanner; 043import org.apache.hadoop.hbase.rest.model.CellModel; 044import org.apache.hadoop.hbase.rest.model.RowModel; 045import org.apache.yetus.audience.InterfaceAudience; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049import com.fasterxml.jackson.annotation.JsonIgnore; 050import com.fasterxml.jackson.annotation.JsonProperty; 051 052@InterfaceAudience.Private 053public class TableScanResource extends ResourceBase { 054 private static final Logger LOG = LoggerFactory.getLogger(TableScanResource.class); 055 056 TableResource tableResource; 057 ResultScanner results; 058 int userRequestedLimit; 059 060 public TableScanResource(ResultScanner scanner, int userRequestedLimit) throws IOException { 061 super(); 062 this.results = scanner; 063 this.userRequestedLimit = userRequestedLimit; 064 } 065 066 @GET 067 @Produces({ Constants.MIMETYPE_XML, Constants.MIMETYPE_JSON }) 068 public CellSetModelStream get(final @Context UriInfo uriInfo) { 069 if (LOG.isTraceEnabled()) { 070 LOG.trace("GET " + uriInfo.getAbsolutePath()); 071 } 072 servlet.getMetrics().incrementRequests(1); 073 final int rowsToSend = userRequestedLimit; 074 servlet.getMetrics().incrementSucessfulScanRequests(1); 075 final Iterator<Result> itr = results.iterator(); 076 return new CellSetModelStream(new ArrayList<RowModel>() { 077 @Override 078 public Iterator<RowModel> iterator() { 079 return new Iterator<RowModel>() { 080 int count = rowsToSend; 081 082 @Override 083 public boolean hasNext() { 084 return count > 0 && itr.hasNext(); 085 } 086 087 @Override 088 public RowModel next() { 089 Result rs = itr.next(); 090 if ((rs == null) || (count <= 0)) { 091 return null; 092 } 093 byte[] rowKey = rs.getRow(); 094 RowModel rModel = new RowModel(rowKey); 095 List<Cell> kvs = rs.listCells(); 096 for (Cell kv : kvs) { 097 rModel.addCell(new CellModel(CellUtil.cloneFamily(kv), CellUtil.cloneQualifier(kv), 098 kv.getTimestamp(), CellUtil.cloneValue(kv))); 099 } 100 count--; 101 if (count == 0) { 102 results.close(); 103 } 104 return rModel; 105 } 106 }; 107 } 108 }); 109 } 110 111 @GET 112 @Produces({ Constants.MIMETYPE_PROTOBUF, Constants.MIMETYPE_PROTOBUF_IETF }) 113 public Response getProtobuf( 114 final @Context UriInfo uriInfo, 115 final @HeaderParam("Accept") String contentType) { 116 if (LOG.isTraceEnabled()) { 117 LOG.trace("GET " + uriInfo.getAbsolutePath() + " as " + 118 MIMETYPE_BINARY); 119 } 120 servlet.getMetrics().incrementRequests(1); 121 try { 122 int fetchSize = this.servlet.getConfiguration().getInt(Constants.SCAN_FETCH_SIZE, 10); 123 StreamingOutput stream = new ProtobufStreamingOutput(this.results, contentType, 124 userRequestedLimit, fetchSize); 125 servlet.getMetrics().incrementSucessfulScanRequests(1); 126 ResponseBuilder response = Response.ok(stream); 127 response.header("content-type", contentType); 128 return response.build(); 129 } catch (Exception exp) { 130 servlet.getMetrics().incrementFailedScanRequests(1); 131 processException(exp); 132 LOG.warn(exp.toString(), exp); 133 return null; 134 } 135 } 136 137 @XmlRootElement(name = "CellSet") 138 @XmlAccessorType(XmlAccessType.FIELD) 139 public static class CellSetModelStream { 140 // JAXB needs an arraylist for streaming 141 @XmlElement(name = "Row") 142 @JsonIgnore 143 private ArrayList<RowModel> Row; 144 145 public CellSetModelStream() { 146 } 147 148 public CellSetModelStream(final ArrayList<RowModel> rowList) { 149 this.Row = rowList; 150 } 151 152 // jackson needs an iterator for streaming 153 @JsonProperty("Row") 154 public Iterator<RowModel> getIterator() { 155 return Row.iterator(); 156 } 157 } 158}