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 } else {
87
88 RESTServlet.getInstance().getConnectionCache().updateConnectionAccessTime();
89 }
90 CellSetModel model = new CellSetModel();
91 RowModel rowModel = null;
92 byte[] rowKey = null;
93 int limit = batch;
94 if (maxValues > 0) {
95 limit = maxValues;
96 }
97 int count = limit;
98 do {
99 Cell value = null;
100 try {
101 value = generator.next();
102 } catch (IllegalStateException e) {
103 if (ScannerResource.delete(id)) {
104 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
105 } else {
106 servlet.getMetrics().incrementFailedDeleteRequests(1);
107 }
108 servlet.getMetrics().incrementFailedGetRequests(1);
109 return Response.status(Response.Status.GONE)
110 .type(MIMETYPE_TEXT).entity("Gone" + CRLF)
111 .build();
112 } catch (IllegalArgumentException e) {
113 Throwable t = e.getCause();
114 if (t instanceof TableNotFoundException) {
115 return Response.status(Response.Status.NOT_FOUND)
116 .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
117 .build();
118 }
119 throw e;
120 }
121 if (value == null) {
122 if (LOG.isTraceEnabled()) {
123 LOG.trace("generator exhausted");
124 }
125
126
127 if (count == limit) {
128 return Response.noContent().build();
129 }
130 break;
131 }
132 if (rowKey == null) {
133 rowKey = CellUtil.cloneRow(value);
134 rowModel = new RowModel(rowKey);
135 }
136 if (!Bytes.equals(CellUtil.cloneRow(value), rowKey)) {
137
138
139 if (maxRows > 0) {
140 if (--maxRows == 0) {
141 generator.putBack(value);
142 break;
143 }
144 }
145 model.addRow(rowModel);
146 rowKey = CellUtil.cloneRow(value);
147 rowModel = new RowModel(rowKey);
148 }
149 rowModel.addCell(
150 new CellModel(CellUtil.cloneFamily(value), CellUtil.cloneQualifier(value),
151 value.getTimestamp(), CellUtil.cloneValue(value)));
152 } while (--count > 0);
153 model.addRow(rowModel);
154 ResponseBuilder response = Response.ok(model);
155 response.cacheControl(cacheControl);
156 servlet.getMetrics().incrementSucessfulGetRequests(1);
157 return response.build();
158 }
159
160 @GET
161 @Produces(MIMETYPE_BINARY)
162 public Response getBinary(final @Context UriInfo uriInfo) {
163 if (LOG.isTraceEnabled()) {
164 LOG.trace("GET " + uriInfo.getAbsolutePath() + " as " +
165 MIMETYPE_BINARY);
166 }
167 servlet.getMetrics().incrementRequests(1);
168 try {
169 Cell value = generator.next();
170 if (value == null) {
171 if (LOG.isTraceEnabled()) {
172 LOG.trace("generator exhausted");
173 }
174 return Response.noContent().build();
175 }
176 ResponseBuilder response = Response.ok(CellUtil.cloneValue(value));
177 response.cacheControl(cacheControl);
178 response.header("X-Row", Base64.encodeBytes(CellUtil.cloneRow(value)));
179 response.header("X-Column",
180 Base64.encodeBytes(
181 KeyValue.makeColumn(CellUtil.cloneFamily(value), CellUtil.cloneQualifier(value))));
182 response.header("X-Timestamp", value.getTimestamp());
183 servlet.getMetrics().incrementSucessfulGetRequests(1);
184 return response.build();
185 } catch (IllegalStateException e) {
186 if (ScannerResource.delete(id)) {
187 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
188 } else {
189 servlet.getMetrics().incrementFailedDeleteRequests(1);
190 }
191 servlet.getMetrics().incrementFailedGetRequests(1);
192 return Response.status(Response.Status.GONE)
193 .type(MIMETYPE_TEXT).entity("Gone" + CRLF)
194 .build();
195 }
196 }
197
198 @DELETE
199 public Response delete(final @Context UriInfo uriInfo) {
200 if (LOG.isTraceEnabled()) {
201 LOG.trace("DELETE " + uriInfo.getAbsolutePath());
202 }
203 servlet.getMetrics().incrementRequests(1);
204 if (servlet.isReadOnly()) {
205 return Response.status(Response.Status.FORBIDDEN)
206 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
207 .build();
208 }
209 if (ScannerResource.delete(id)) {
210 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
211 } else {
212 servlet.getMetrics().incrementFailedDeleteRequests(1);
213 }
214 return Response.ok().build();
215 }
216 }