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