1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.rest;
21
22 import java.io.IOException;
23
24 import javax.ws.rs.DELETE;
25 import javax.ws.rs.GET;
26 import javax.ws.rs.Produces;
27 import javax.ws.rs.QueryParam;
28 import javax.ws.rs.core.CacheControl;
29 import javax.ws.rs.core.Context;
30 import javax.ws.rs.core.Response;
31 import javax.ws.rs.core.Response.ResponseBuilder;
32 import javax.ws.rs.core.UriInfo;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.hbase.Cell;
37 import org.apache.hadoop.hbase.CellUtil;
38 import org.apache.hadoop.hbase.KeyValue;
39 import org.apache.hadoop.hbase.TableNotFoundException;
40 import org.apache.hadoop.hbase.classification.InterfaceAudience;
41 import org.apache.hadoop.hbase.rest.model.CellModel;
42 import org.apache.hadoop.hbase.rest.model.CellSetModel;
43 import org.apache.hadoop.hbase.rest.model.RowModel;
44 import org.apache.hadoop.hbase.util.Base64;
45 import org.apache.hadoop.hbase.util.Bytes;
46
47 @InterfaceAudience.Private
48 public class ScannerInstanceResource extends ResourceBase {
49 private static final Log LOG =
50 LogFactory.getLog(ScannerInstanceResource.class);
51
52 static CacheControl cacheControl;
53 static {
54 cacheControl = new CacheControl();
55 cacheControl.setNoCache(true);
56 cacheControl.setNoTransform(false);
57 }
58
59 ResultGenerator generator = null;
60 String id = null;
61 int batch = 1;
62
63 public ScannerInstanceResource() throws IOException { }
64
65 public ScannerInstanceResource(String table, String id,
66 ResultGenerator generator, int batch) throws IOException {
67 this.id = id;
68 this.generator = generator;
69 this.batch = batch;
70 }
71
72 @GET
73 @Produces({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
74 MIMETYPE_PROTOBUF_IETF})
75 public Response get(final @Context UriInfo uriInfo,
76 @QueryParam("n") int maxRows, final @QueryParam("c") int maxValues) {
77 if (LOG.isTraceEnabled()) {
78 LOG.trace("GET " + uriInfo.getAbsolutePath());
79 }
80 servlet.getMetrics().incrementRequests(1);
81 if (generator == null) {
82 servlet.getMetrics().incrementFailedGetRequests(1);
83 return Response.status(Response.Status.NOT_FOUND)
84 .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
85 .build();
86 }
87 CellSetModel model = new CellSetModel();
88 RowModel rowModel = null;
89 byte[] rowKey = null;
90 int limit = batch;
91 if (maxValues > 0) {
92 limit = maxValues;
93 }
94 int count = limit;
95 do {
96 Cell value = null;
97 try {
98 value = generator.next();
99 } catch (IllegalStateException e) {
100 if (ScannerResource.delete(id)) {
101 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
102 } else {
103 servlet.getMetrics().incrementFailedDeleteRequests(1);
104 }
105 servlet.getMetrics().incrementFailedGetRequests(1);
106 return Response.status(Response.Status.GONE)
107 .type(MIMETYPE_TEXT).entity("Gone" + CRLF)
108 .build();
109 } catch (IllegalArgumentException e) {
110 Throwable t = e.getCause();
111 if (t instanceof TableNotFoundException) {
112 return Response.status(Response.Status.NOT_FOUND)
113 .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
114 .build();
115 }
116 throw e;
117 }
118 if (value == null) {
119 if (LOG.isTraceEnabled()) {
120 LOG.trace("generator exhausted");
121 }
122
123
124 if (count == limit) {
125 return Response.noContent().build();
126 }
127 break;
128 }
129 if (rowKey == null) {
130 rowKey = CellUtil.cloneRow(value);
131 rowModel = new RowModel(rowKey);
132 }
133 if (!Bytes.equals(CellUtil.cloneRow(value), rowKey)) {
134
135
136 if (maxRows > 0) {
137 if (--maxRows == 0) {
138 generator.putBack(value);
139 break;
140 }
141 }
142 model.addRow(rowModel);
143 rowKey = CellUtil.cloneRow(value);
144 rowModel = new RowModel(rowKey);
145 }
146 rowModel.addCell(
147 new CellModel(CellUtil.cloneFamily(value), CellUtil.cloneQualifier(value),
148 value.getTimestamp(), CellUtil.cloneValue(value)));
149 } while (--count > 0);
150 model.addRow(rowModel);
151 ResponseBuilder response = Response.ok(model);
152 response.cacheControl(cacheControl);
153 servlet.getMetrics().incrementSucessfulGetRequests(1);
154 return response.build();
155 }
156
157 @GET
158 @Produces(MIMETYPE_BINARY)
159 public Response getBinary(final @Context UriInfo uriInfo) {
160 if (LOG.isTraceEnabled()) {
161 LOG.trace("GET " + uriInfo.getAbsolutePath() + " as " +
162 MIMETYPE_BINARY);
163 }
164 servlet.getMetrics().incrementRequests(1);
165 try {
166 Cell value = generator.next();
167 if (value == null) {
168 if (LOG.isTraceEnabled()) {
169 LOG.trace("generator exhausted");
170 }
171 return Response.noContent().build();
172 }
173 ResponseBuilder response = Response.ok(CellUtil.cloneValue(value));
174 response.cacheControl(cacheControl);
175 response.header("X-Row", Base64.encodeBytes(CellUtil.cloneRow(value)));
176 response.header("X-Column",
177 Base64.encodeBytes(
178 KeyValue.makeColumn(CellUtil.cloneFamily(value), CellUtil.cloneQualifier(value))));
179 response.header("X-Timestamp", value.getTimestamp());
180 servlet.getMetrics().incrementSucessfulGetRequests(1);
181 return response.build();
182 } catch (IllegalStateException e) {
183 if (ScannerResource.delete(id)) {
184 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
185 } else {
186 servlet.getMetrics().incrementFailedDeleteRequests(1);
187 }
188 servlet.getMetrics().incrementFailedGetRequests(1);
189 return Response.status(Response.Status.GONE)
190 .type(MIMETYPE_TEXT).entity("Gone" + CRLF)
191 .build();
192 }
193 }
194
195 @DELETE
196 public Response delete(final @Context UriInfo uriInfo) {
197 if (LOG.isTraceEnabled()) {
198 LOG.trace("DELETE " + uriInfo.getAbsolutePath());
199 }
200 servlet.getMetrics().incrementRequests(1);
201 if (servlet.isReadOnly()) {
202 return Response.status(Response.Status.FORBIDDEN)
203 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
204 .build();
205 }
206 if (ScannerResource.delete(id)) {
207 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
208 } else {
209 servlet.getMetrics().incrementFailedDeleteRequests(1);
210 }
211 return Response.ok().build();
212 }
213 }