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.net.URI; 024import java.util.Collections; 025import java.util.HashMap; 026import java.util.Map; 027 028import javax.ws.rs.Consumes; 029import javax.ws.rs.POST; 030import javax.ws.rs.PUT; 031import javax.ws.rs.Path; 032import javax.ws.rs.PathParam; 033import javax.ws.rs.core.Context; 034import javax.ws.rs.core.Response; 035import javax.ws.rs.core.UriBuilder; 036import javax.ws.rs.core.UriInfo; 037 038import org.apache.yetus.audience.InterfaceAudience; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042import com.fasterxml.jackson.core.JsonParseException; 043import com.fasterxml.jackson.databind.JsonMappingException; 044 045import org.apache.hadoop.hbase.TableNotFoundException; 046import org.apache.hadoop.hbase.filter.Filter; 047import org.apache.hadoop.hbase.rest.model.ScannerModel; 048 049@InterfaceAudience.Private 050public class ScannerResource extends ResourceBase { 051 052 private static final Logger LOG = LoggerFactory.getLogger(ScannerResource.class); 053 054 static final Map<String,ScannerInstanceResource> scanners = 055 Collections.synchronizedMap(new HashMap<String,ScannerInstanceResource>()); 056 057 TableResource tableResource; 058 059 /** 060 * Constructor 061 * @param tableResource 062 * @throws IOException 063 */ 064 public ScannerResource(TableResource tableResource)throws IOException { 065 super(); 066 this.tableResource = tableResource; 067 } 068 069 static boolean delete(final String id) { 070 ScannerInstanceResource instance = scanners.remove(id); 071 if (instance != null) { 072 instance.generator.close(); 073 return true; 074 } else { 075 return false; 076 } 077 } 078 079 Response update(final ScannerModel model, final boolean replace, 080 final UriInfo uriInfo) { 081 servlet.getMetrics().incrementRequests(1); 082 if (servlet.isReadOnly()) { 083 return Response.status(Response.Status.FORBIDDEN) 084 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF) 085 .build(); 086 } 087 byte[] endRow = model.hasEndRow() ? model.getEndRow() : null; 088 RowSpec spec = null; 089 if (model.getLabels() != null) { 090 spec = new RowSpec(model.getStartRow(), endRow, model.getColumns(), model.getStartTime(), 091 model.getEndTime(), model.getMaxVersions(), model.getLabels()); 092 } else { 093 spec = new RowSpec(model.getStartRow(), endRow, model.getColumns(), model.getStartTime(), 094 model.getEndTime(), model.getMaxVersions()); 095 } 096 097 try { 098 Filter filter = ScannerResultGenerator.buildFilterFromModel(model); 099 String tableName = tableResource.getName(); 100 ScannerResultGenerator gen = 101 new ScannerResultGenerator(tableName, spec, filter, model.getCaching(), 102 model.getCacheBlocks()); 103 String id = gen.getID(); 104 ScannerInstanceResource instance = 105 new ScannerInstanceResource(tableName, id, gen, model.getBatch()); 106 scanners.put(id, instance); 107 if (LOG.isTraceEnabled()) { 108 LOG.trace("new scanner: " + id); 109 } 110 UriBuilder builder = uriInfo.getAbsolutePathBuilder(); 111 URI uri = builder.path(id).build(); 112 servlet.getMetrics().incrementSucessfulPutRequests(1); 113 return Response.created(uri).build(); 114 } catch (Exception e) { 115 LOG.error("Exception occured while processing " + uriInfo.getAbsolutePath() + " : ", e); 116 servlet.getMetrics().incrementFailedPutRequests(1); 117 if (e instanceof TableNotFoundException) { 118 return Response.status(Response.Status.NOT_FOUND) 119 .type(MIMETYPE_TEXT).entity("Not found" + CRLF) 120 .build(); 121 } else if (e instanceof RuntimeException 122 || e instanceof JsonMappingException | e instanceof JsonParseException) { 123 return Response.status(Response.Status.BAD_REQUEST) 124 .type(MIMETYPE_TEXT).entity("Bad request" + CRLF) 125 .build(); 126 } 127 return Response.status(Response.Status.SERVICE_UNAVAILABLE) 128 .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF) 129 .build(); 130 } 131 } 132 133 @PUT 134 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF, 135 MIMETYPE_PROTOBUF_IETF}) 136 public Response put(final ScannerModel model, 137 final @Context UriInfo uriInfo) { 138 if (LOG.isTraceEnabled()) { 139 LOG.trace("PUT " + uriInfo.getAbsolutePath()); 140 } 141 return update(model, true, uriInfo); 142 } 143 144 @POST 145 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF, 146 MIMETYPE_PROTOBUF_IETF}) 147 public Response post(final ScannerModel model, 148 final @Context UriInfo uriInfo) { 149 if (LOG.isTraceEnabled()) { 150 LOG.trace("POST " + uriInfo.getAbsolutePath()); 151 } 152 return update(model, false, uriInfo); 153 } 154 155 @Path("{scanner: .+}") 156 public ScannerInstanceResource getScannerInstanceResource( 157 final @PathParam("scanner") String id) throws IOException { 158 ScannerInstanceResource instance = scanners.get(id); 159 if (instance == null) { 160 servlet.getMetrics().incrementFailedGetRequests(1); 161 return new ScannerInstanceResource(); 162 } else { 163 servlet.getMetrics().incrementSucessfulGetRequests(1); 164 } 165 return instance; 166 } 167}