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.KeyValue;
39 import org.apache.hadoop.hbase.rest.model.CellModel;
40 import org.apache.hadoop.hbase.rest.model.CellSetModel;
41 import org.apache.hadoop.hbase.rest.model.RowModel;
42 import org.apache.hadoop.hbase.util.Base64;
43 import org.apache.hadoop.hbase.util.Bytes;
44
45 @InterfaceAudience.Private
46 public class ScannerInstanceResource extends ResourceBase {
47 private static final Log LOG =
48 LogFactory.getLog(ScannerInstanceResource.class);
49
50 static CacheControl cacheControl;
51 static {
52 cacheControl = new CacheControl();
53 cacheControl.setNoCache(true);
54 cacheControl.setNoTransform(false);
55 }
56
57 ResultGenerator generator = null;
58 String id = null;
59 int batch = 1;
60
61 public ScannerInstanceResource() throws IOException { }
62
63 public ScannerInstanceResource(String table, String id,
64 ResultGenerator generator, int batch) throws IOException {
65 this.id = id;
66 this.generator = generator;
67 this.batch = batch;
68 }
69
70 @GET
71 @Produces({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
72 MIMETYPE_PROTOBUF_IETF})
73 public Response get(final @Context UriInfo uriInfo,
74 @QueryParam("n") int maxRows, final @QueryParam("c") int maxValues) {
75 if (LOG.isDebugEnabled()) {
76 LOG.debug("GET " + uriInfo.getAbsolutePath());
77 }
78 servlet.getMetrics().incrementRequests(1);
79 if (generator == null) {
80 servlet.getMetrics().incrementFailedGetRequests(1);
81 return Response.status(Response.Status.NOT_FOUND)
82 .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
83 .build();
84 }
85 CellSetModel model = new CellSetModel();
86 RowModel rowModel = null;
87 byte[] rowKey = null;
88 int limit = batch;
89 if (maxValues > 0) {
90 limit = maxValues;
91 }
92 int count = limit;
93 do {
94 KeyValue value = null;
95 try {
96 value = generator.next();
97 } catch (IllegalStateException e) {
98 if (ScannerResource.delete(id)) {
99 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
100 } else {
101 servlet.getMetrics().incrementFailedDeleteRequests(1);
102 }
103 servlet.getMetrics().incrementFailedGetRequests(1);
104 return Response.status(Response.Status.GONE)
105 .type(MIMETYPE_TEXT).entity("Gone" + CRLF)
106 .build();
107 }
108 if (value == null) {
109 LOG.info("generator exhausted");
110
111
112 if (count == limit) {
113 return Response.noContent().build();
114 }
115 break;
116 }
117 if (rowKey == null) {
118 rowKey = value.getRow();
119 rowModel = new RowModel(rowKey);
120 }
121 if (!Bytes.equals(value.getRow(), rowKey)) {
122
123
124 if (maxRows > 0) {
125 if (--maxRows == 0) {
126 generator.putBack(value);
127 break;
128 }
129 }
130 model.addRow(rowModel);
131 rowKey = value.getRow();
132 rowModel = new RowModel(rowKey);
133 }
134 rowModel.addCell(
135 new CellModel(value.getFamily(), value.getQualifier(),
136 value.getTimestamp(), value.getValue()));
137 } while (--count > 0);
138 model.addRow(rowModel);
139 ResponseBuilder response = Response.ok(model);
140 response.cacheControl(cacheControl);
141 servlet.getMetrics().incrementSucessfulGetRequests(1);
142 return response.build();
143 }
144
145 @GET
146 @Produces(MIMETYPE_BINARY)
147 public Response getBinary(final @Context UriInfo uriInfo) {
148 if (LOG.isDebugEnabled()) {
149 LOG.debug("GET " + uriInfo.getAbsolutePath() + " as " +
150 MIMETYPE_BINARY);
151 }
152 servlet.getMetrics().incrementRequests(1);
153 try {
154 KeyValue value = generator.next();
155 if (value == null) {
156 LOG.info("generator exhausted");
157 return Response.noContent().build();
158 }
159 ResponseBuilder response = Response.ok(value.getValue());
160 response.cacheControl(cacheControl);
161 response.header("X-Row", Base64.encodeBytes(value.getRow()));
162 response.header("X-Column",
163 Base64.encodeBytes(
164 KeyValue.makeColumn(value.getFamily(), value.getQualifier())));
165 response.header("X-Timestamp", value.getTimestamp());
166 servlet.getMetrics().incrementSucessfulGetRequests(1);
167 return response.build();
168 } catch (IllegalStateException e) {
169 if (ScannerResource.delete(id)) {
170 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
171 } else {
172 servlet.getMetrics().incrementFailedDeleteRequests(1);
173 }
174 servlet.getMetrics().incrementFailedGetRequests(1);
175 return Response.status(Response.Status.GONE)
176 .type(MIMETYPE_TEXT).entity("Gone" + CRLF)
177 .build();
178 }
179 }
180
181 @DELETE
182 public Response delete(final @Context UriInfo uriInfo) {
183 if (LOG.isDebugEnabled()) {
184 LOG.debug("DELETE " + uriInfo.getAbsolutePath());
185 }
186 servlet.getMetrics().incrementRequests(1);
187 if (servlet.isReadOnly()) {
188 return Response.status(Response.Status.FORBIDDEN)
189 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
190 .build();
191 }
192 if (ScannerResource.delete(id)) {
193 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
194 } else {
195 servlet.getMetrics().incrementFailedDeleteRequests(1);
196 }
197 return Response.ok().build();
198 }
199 }