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
37 import org.apache.hadoop.hbase.classification.InterfaceAudience;
38 import org.apache.hadoop.hbase.Cell;
39 import org.apache.hadoop.hbase.CellUtil;
40 import org.apache.hadoop.hbase.KeyValue;
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 }
110 if (value == null) {
111 if (LOG.isTraceEnabled()) {
112 LOG.trace("generator exhausted");
113 }
114
115
116 if (count == limit) {
117 return Response.noContent().build();
118 }
119 break;
120 }
121 if (rowKey == null) {
122 rowKey = CellUtil.cloneRow(value);
123 rowModel = new RowModel(rowKey);
124 }
125 if (!Bytes.equals(CellUtil.cloneRow(value), rowKey)) {
126
127
128 if (maxRows > 0) {
129 if (--maxRows == 0) {
130 generator.putBack(value);
131 break;
132 }
133 }
134 model.addRow(rowModel);
135 rowKey = CellUtil.cloneRow(value);
136 rowModel = new RowModel(rowKey);
137 }
138 rowModel.addCell(
139 new CellModel(CellUtil.cloneFamily(value), CellUtil.cloneQualifier(value),
140 value.getTimestamp(), CellUtil.cloneValue(value)));
141 } while (--count > 0);
142 model.addRow(rowModel);
143 ResponseBuilder response = Response.ok(model);
144 response.cacheControl(cacheControl);
145 servlet.getMetrics().incrementSucessfulGetRequests(1);
146 return response.build();
147 }
148
149 @GET
150 @Produces(MIMETYPE_BINARY)
151 public Response getBinary(final @Context UriInfo uriInfo) {
152 if (LOG.isTraceEnabled()) {
153 LOG.trace("GET " + uriInfo.getAbsolutePath() + " as " +
154 MIMETYPE_BINARY);
155 }
156 servlet.getMetrics().incrementRequests(1);
157 try {
158 Cell value = generator.next();
159 if (value == null) {
160 if (LOG.isTraceEnabled()) {
161 LOG.trace("generator exhausted");
162 }
163 return Response.noContent().build();
164 }
165 ResponseBuilder response = Response.ok(CellUtil.cloneValue(value));
166 response.cacheControl(cacheControl);
167 response.header("X-Row", Base64.encodeBytes(CellUtil.cloneRow(value)));
168 response.header("X-Column",
169 Base64.encodeBytes(
170 KeyValue.makeColumn(CellUtil.cloneFamily(value), CellUtil.cloneQualifier(value))));
171 response.header("X-Timestamp", value.getTimestamp());
172 servlet.getMetrics().incrementSucessfulGetRequests(1);
173 return response.build();
174 } catch (IllegalStateException e) {
175 if (ScannerResource.delete(id)) {
176 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
177 } else {
178 servlet.getMetrics().incrementFailedDeleteRequests(1);
179 }
180 servlet.getMetrics().incrementFailedGetRequests(1);
181 return Response.status(Response.Status.GONE)
182 .type(MIMETYPE_TEXT).entity("Gone" + CRLF)
183 .build();
184 }
185 }
186
187 @DELETE
188 public Response delete(final @Context UriInfo uriInfo) {
189 if (LOG.isTraceEnabled()) {
190 LOG.trace("DELETE " + uriInfo.getAbsolutePath());
191 }
192 servlet.getMetrics().incrementRequests(1);
193 if (servlet.isReadOnly()) {
194 return Response.status(Response.Status.FORBIDDEN)
195 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
196 .build();
197 }
198 if (ScannerResource.delete(id)) {
199 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
200 } else {
201 servlet.getMetrics().incrementFailedDeleteRequests(1);
202 }
203 return Response.ok().build();
204 }
205 }