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 import java.util.ArrayList;
24 import java.util.List;
25
26 import javax.ws.rs.Consumes;
27 import javax.ws.rs.DELETE;
28 import javax.ws.rs.GET;
29 import javax.ws.rs.POST;
30 import javax.ws.rs.PUT;
31 import javax.ws.rs.Produces;
32 import javax.ws.rs.core.Context;
33 import javax.ws.rs.core.HttpHeaders;
34 import javax.ws.rs.core.MultivaluedMap;
35 import javax.ws.rs.core.Response;
36 import javax.ws.rs.core.Response.ResponseBuilder;
37 import javax.ws.rs.core.UriInfo;
38
39 import org.apache.commons.lang.StringUtils;
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42 import org.apache.hadoop.hbase.classification.InterfaceAudience;
43 import org.apache.hadoop.hbase.Cell;
44 import org.apache.hadoop.hbase.CellUtil;
45 import org.apache.hadoop.hbase.HConstants;
46 import org.apache.hadoop.hbase.KeyValue;
47 import org.apache.hadoop.hbase.client.Append;
48 import org.apache.hadoop.hbase.client.Delete;
49 import org.apache.hadoop.hbase.client.Increment;
50 import org.apache.hadoop.hbase.client.Put;
51 import org.apache.hadoop.hbase.client.Result;
52 import org.apache.hadoop.hbase.client.Table;
53 import org.apache.hadoop.hbase.rest.model.CellModel;
54 import org.apache.hadoop.hbase.rest.model.CellSetModel;
55 import org.apache.hadoop.hbase.rest.model.RowModel;
56 import org.apache.hadoop.hbase.util.Bytes;
57
58 @InterfaceAudience.Private
59 public class RowResource extends ResourceBase {
60 private static final Log LOG = LogFactory.getLog(RowResource.class);
61
62 private static final String CHECK_PUT = "put";
63 private static final String CHECK_DELETE = "delete";
64 private static final String CHECK_APPEND = "append";
65 private static final String CHECK_INCREMENT = "increment";
66
67 private TableResource tableResource;
68 private RowSpec rowspec;
69 private String check = null;
70 private boolean returnResult = false;
71
72
73
74
75
76
77
78
79
80
81 public RowResource(TableResource tableResource, String rowspec,
82 String versions, String check, String returnResult) throws IOException {
83 super();
84 this.tableResource = tableResource;
85 this.rowspec = new RowSpec(rowspec);
86 if (versions != null) {
87 this.rowspec.setMaxVersions(Integer.parseInt(versions));
88 }
89 this.check = check;
90 if (returnResult != null) {
91 this.returnResult = Boolean.valueOf(returnResult);
92 }
93 }
94
95 @GET
96 @Produces({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
97 MIMETYPE_PROTOBUF_IETF})
98 public Response get(final @Context UriInfo uriInfo) {
99 if (LOG.isTraceEnabled()) {
100 LOG.trace("GET " + uriInfo.getAbsolutePath());
101 }
102 servlet.getMetrics().incrementRequests(1);
103 MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
104 try {
105 ResultGenerator generator =
106 ResultGenerator.fromRowSpec(tableResource.getName(), rowspec, null,
107 !params.containsKey(NOCACHE_PARAM_NAME));
108 if (!generator.hasNext()) {
109 servlet.getMetrics().incrementFailedGetRequests(1);
110 return Response.status(Response.Status.NOT_FOUND)
111 .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
112 .build();
113 }
114 int count = 0;
115 CellSetModel model = new CellSetModel();
116 Cell value = generator.next();
117 byte[] rowKey = CellUtil.cloneRow(value);
118 RowModel rowModel = new RowModel(rowKey);
119 do {
120 if (!Bytes.equals(CellUtil.cloneRow(value), rowKey)) {
121 model.addRow(rowModel);
122 rowKey = CellUtil.cloneRow(value);
123 rowModel = new RowModel(rowKey);
124 }
125 rowModel.addCell(new CellModel(CellUtil.cloneFamily(value), CellUtil.cloneQualifier(value),
126 value.getTimestamp(), CellUtil.cloneValue(value)));
127 if (++count > rowspec.getMaxValues()) {
128 break;
129 }
130 value = generator.next();
131 } while (value != null);
132 model.addRow(rowModel);
133 servlet.getMetrics().incrementSucessfulGetRequests(1);
134 return Response.ok(model).build();
135 } catch (Exception e) {
136 servlet.getMetrics().incrementFailedPutRequests(1);
137 return processException(e);
138 }
139 }
140
141 @GET
142 @Produces(MIMETYPE_BINARY)
143 public Response getBinary(final @Context UriInfo uriInfo) {
144 if (LOG.isTraceEnabled()) {
145 LOG.trace("GET " + uriInfo.getAbsolutePath() + " as "+ MIMETYPE_BINARY);
146 }
147 servlet.getMetrics().incrementRequests(1);
148
149
150 if (!rowspec.hasColumns() || rowspec.getColumns().length > 1) {
151 servlet.getMetrics().incrementFailedGetRequests(1);
152 return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT)
153 .entity("Bad request: Default 'GET' method only works if there is exactly 1 column " +
154 "in the row. Using the 'Accept' header with one of these formats lets you " +
155 "retrieve the entire row if it has multiple columns: " +
156
157 MIMETYPE_XML + ", " + MIMETYPE_JSON + ", " +
158 MIMETYPE_PROTOBUF + ", " + MIMETYPE_PROTOBUF_IETF +
159 CRLF).build();
160 }
161 MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
162 try {
163 ResultGenerator generator =
164 ResultGenerator.fromRowSpec(tableResource.getName(), rowspec, null,
165 !params.containsKey(NOCACHE_PARAM_NAME));
166 if (!generator.hasNext()) {
167 servlet.getMetrics().incrementFailedGetRequests(1);
168 return Response.status(Response.Status.NOT_FOUND)
169 .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
170 .build();
171 }
172 Cell value = generator.next();
173 ResponseBuilder response = Response.ok(CellUtil.cloneValue(value));
174 response.header("X-Timestamp", value.getTimestamp());
175 servlet.getMetrics().incrementSucessfulGetRequests(1);
176 return response.build();
177 } catch (Exception e) {
178 servlet.getMetrics().incrementFailedGetRequests(1);
179 return processException(e);
180 }
181 }
182
183 Response update(final CellSetModel model, final boolean replace) {
184 servlet.getMetrics().incrementRequests(1);
185 if (servlet.isReadOnly()) {
186 servlet.getMetrics().incrementFailedPutRequests(1);
187 return Response.status(Response.Status.FORBIDDEN)
188 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
189 .build();
190 }
191
192 if (CHECK_PUT.equalsIgnoreCase(check)) {
193 return checkAndPut(model);
194 } else if (CHECK_DELETE.equalsIgnoreCase(check)) {
195 return checkAndDelete(model);
196 } else if (CHECK_APPEND.equalsIgnoreCase(check)) {
197 return append(model);
198 } else if (CHECK_INCREMENT.equalsIgnoreCase(check)) {
199 return increment(model);
200 } else if (check != null && check.length() > 0) {
201 return Response.status(Response.Status.BAD_REQUEST)
202 .type(MIMETYPE_TEXT).entity("Invalid check value '" + check + "'" + CRLF)
203 .build();
204 }
205
206 Table table = null;
207 try {
208 List<RowModel> rows = model.getRows();
209 List<Put> puts = new ArrayList<Put>();
210 for (RowModel row: rows) {
211 byte[] key = row.getKey();
212 if (key == null) {
213 key = rowspec.getRow();
214 }
215 if (key == null) {
216 servlet.getMetrics().incrementFailedPutRequests(1);
217 return Response.status(Response.Status.BAD_REQUEST)
218 .type(MIMETYPE_TEXT).entity("Bad request: Row key not specified." + CRLF)
219 .build();
220 }
221 Put put = new Put(key);
222 int i = 0;
223 for (CellModel cell: row.getCells()) {
224 byte[] col = cell.getColumn();
225 if (col == null) try {
226 col = rowspec.getColumns()[i++];
227 } catch (ArrayIndexOutOfBoundsException e) {
228 col = null;
229 }
230 if (col == null) {
231 servlet.getMetrics().incrementFailedPutRequests(1);
232 return Response.status(Response.Status.BAD_REQUEST)
233 .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
234 .build();
235 }
236 byte [][] parts = KeyValue.parseColumn(col);
237 if (parts.length != 2) {
238 return Response.status(Response.Status.BAD_REQUEST)
239 .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
240 .build();
241 }
242 put.addImmutable(parts[0], parts[1], cell.getTimestamp(), cell.getValue());
243 }
244 puts.add(put);
245 if (LOG.isTraceEnabled()) {
246 LOG.trace("PUT " + put.toString());
247 }
248 }
249 table = servlet.getTable(tableResource.getName());
250 table.put(puts);
251 ResponseBuilder response = Response.ok();
252 servlet.getMetrics().incrementSucessfulPutRequests(1);
253 return response.build();
254 } catch (Exception e) {
255 servlet.getMetrics().incrementFailedPutRequests(1);
256 return processException(e);
257 } finally {
258 if (table != null) try {
259 table.close();
260 } catch (IOException ioe) {
261 LOG.debug("Exception received while closing the table", ioe);
262 }
263 }
264 }
265
266
267 Response updateBinary(final byte[] message, final HttpHeaders headers,
268 final boolean replace) {
269 servlet.getMetrics().incrementRequests(1);
270 if (servlet.isReadOnly()) {
271 servlet.getMetrics().incrementFailedPutRequests(1);
272 return Response.status(Response.Status.FORBIDDEN)
273 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
274 .build();
275 }
276 Table table = null;
277 try {
278 byte[] row = rowspec.getRow();
279 byte[][] columns = rowspec.getColumns();
280 byte[] column = null;
281 if (columns != null) {
282 column = columns[0];
283 }
284 long timestamp = HConstants.LATEST_TIMESTAMP;
285 List<String> vals = headers.getRequestHeader("X-Row");
286 if (vals != null && !vals.isEmpty()) {
287 row = Bytes.toBytes(vals.get(0));
288 }
289 vals = headers.getRequestHeader("X-Column");
290 if (vals != null && !vals.isEmpty()) {
291 column = Bytes.toBytes(vals.get(0));
292 }
293 vals = headers.getRequestHeader("X-Timestamp");
294 if (vals != null && !vals.isEmpty()) {
295 timestamp = Long.parseLong(vals.get(0));
296 }
297 if (column == null) {
298 servlet.getMetrics().incrementFailedPutRequests(1);
299 return Response.status(Response.Status.BAD_REQUEST)
300 .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
301 .build();
302 }
303 Put put = new Put(row);
304 byte parts[][] = KeyValue.parseColumn(column);
305 if (parts.length != 2) {
306 return Response.status(Response.Status.BAD_REQUEST)
307 .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
308 .build();
309 }
310 put.addImmutable(parts[0], parts[1], timestamp, message);
311 table = servlet.getTable(tableResource.getName());
312 table.put(put);
313 if (LOG.isTraceEnabled()) {
314 LOG.trace("PUT " + put.toString());
315 }
316 servlet.getMetrics().incrementSucessfulPutRequests(1);
317 return Response.ok().build();
318 } catch (Exception e) {
319 servlet.getMetrics().incrementFailedPutRequests(1);
320 return processException(e);
321 } finally {
322 if (table != null) try {
323 table.close();
324 } catch (IOException ioe) {
325 LOG.debug("Exception received while closing the table", ioe);
326 }
327 }
328 }
329
330 @PUT
331 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
332 MIMETYPE_PROTOBUF_IETF})
333 public Response put(final CellSetModel model,
334 final @Context UriInfo uriInfo) {
335 if (LOG.isTraceEnabled()) {
336 LOG.trace("PUT " + uriInfo.getAbsolutePath()
337 + " " + uriInfo.getQueryParameters());
338 }
339 return update(model, true);
340 }
341
342 @PUT
343 @Consumes(MIMETYPE_BINARY)
344 public Response putBinary(final byte[] message,
345 final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
346 if (LOG.isTraceEnabled()) {
347 LOG.trace("PUT " + uriInfo.getAbsolutePath() + " as "+ MIMETYPE_BINARY);
348 }
349 return updateBinary(message, headers, true);
350 }
351
352 @POST
353 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
354 MIMETYPE_PROTOBUF_IETF})
355 public Response post(final CellSetModel model,
356 final @Context UriInfo uriInfo) {
357 if (LOG.isTraceEnabled()) {
358 LOG.trace("POST " + uriInfo.getAbsolutePath()
359 + " " + uriInfo.getQueryParameters());
360 }
361 return update(model, false);
362 }
363
364 @POST
365 @Consumes(MIMETYPE_BINARY)
366 public Response postBinary(final byte[] message,
367 final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
368 if (LOG.isTraceEnabled()) {
369 LOG.trace("POST " + uriInfo.getAbsolutePath() + " as "+MIMETYPE_BINARY);
370 }
371 return updateBinary(message, headers, false);
372 }
373
374 @DELETE
375 public Response delete(final @Context UriInfo uriInfo) {
376 if (LOG.isTraceEnabled()) {
377 LOG.trace("DELETE " + uriInfo.getAbsolutePath());
378 }
379 servlet.getMetrics().incrementRequests(1);
380 if (servlet.isReadOnly()) {
381 servlet.getMetrics().incrementFailedDeleteRequests(1);
382 return Response.status(Response.Status.FORBIDDEN)
383 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
384 .build();
385 }
386 Delete delete = null;
387 if (rowspec.hasTimestamp())
388 delete = new Delete(rowspec.getRow(), rowspec.getTimestamp());
389 else
390 delete = new Delete(rowspec.getRow());
391
392 for (byte[] column: rowspec.getColumns()) {
393 byte[][] split = KeyValue.parseColumn(column);
394 if (rowspec.hasTimestamp()) {
395 if (split.length == 1) {
396 delete.deleteFamily(split[0], rowspec.getTimestamp());
397 } else if (split.length == 2) {
398 delete.deleteColumns(split[0], split[1], rowspec.getTimestamp());
399 } else {
400 return Response.status(Response.Status.BAD_REQUEST)
401 .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
402 .build();
403 }
404 } else {
405 if (split.length == 1) {
406 delete.deleteFamily(split[0]);
407 } else if (split.length == 2) {
408 delete.deleteColumns(split[0], split[1]);
409 } else {
410 return Response.status(Response.Status.BAD_REQUEST)
411 .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
412 .build();
413 }
414 }
415 }
416 Table table = null;
417 try {
418 table = servlet.getTable(tableResource.getName());
419 table.delete(delete);
420 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
421 if (LOG.isTraceEnabled()) {
422 LOG.trace("DELETE " + delete.toString());
423 }
424 } catch (Exception e) {
425 servlet.getMetrics().incrementFailedDeleteRequests(1);
426 return processException(e);
427 } finally {
428 if (table != null) try {
429 table.close();
430 } catch (IOException ioe) {
431 LOG.debug("Exception received while closing the table", ioe);
432 }
433 }
434 return Response.ok().build();
435 }
436
437
438
439
440
441
442
443
444 Response checkAndPut(final CellSetModel model) {
445 Table table = null;
446 try {
447 table = servlet.getTable(tableResource.getName());
448 if (model.getRows().size() != 1) {
449 servlet.getMetrics().incrementFailedPutRequests(1);
450 return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT)
451 .entity("Bad request: Number of rows specified is not 1." + CRLF).build();
452 }
453
454 RowModel rowModel = model.getRows().get(0);
455 byte[] key = rowModel.getKey();
456 if (key == null) {
457 key = rowspec.getRow();
458 }
459
460 List<CellModel> cellModels = rowModel.getCells();
461 int cellModelCount = cellModels.size();
462 if (key == null || cellModelCount <= 1) {
463 servlet.getMetrics().incrementFailedPutRequests(1);
464 return Response
465 .status(Response.Status.BAD_REQUEST)
466 .type(MIMETYPE_TEXT)
467 .entity(
468 "Bad request: Either row key is null or no data found for columns specified." + CRLF)
469 .build();
470 }
471
472 Put put = new Put(key);
473 boolean retValue;
474 CellModel valueToCheckCell = cellModels.get(cellModelCount - 1);
475 byte[] valueToCheckColumn = valueToCheckCell.getColumn();
476 byte[][] valueToPutParts = KeyValue.parseColumn(valueToCheckColumn);
477 if (valueToPutParts.length == 2 && valueToPutParts[1].length > 0) {
478 CellModel valueToPutCell = null;
479
480
481
482 for (int i = 0, n = cellModelCount - 1; i < n ; i++) {
483 CellModel cell = cellModels.get(i);
484 byte[] col = cell.getColumn();
485
486 if (col == null) {
487 servlet.getMetrics().incrementFailedPutRequests(1);
488 return Response.status(Response.Status.BAD_REQUEST)
489 .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
490 .build();
491 }
492
493 byte [][] parts = KeyValue.parseColumn(col);
494
495 if (parts.length != 2) {
496 return Response.status(Response.Status.BAD_REQUEST)
497 .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
498 .build();
499 }
500 put.addImmutable(parts[0], parts[1], cell.getTimestamp(), cell.getValue());
501
502 if(Bytes.equals(col,
503 valueToCheckCell.getColumn())) {
504 valueToPutCell = cell;
505 }
506 }
507
508 if (valueToPutCell == null) {
509 servlet.getMetrics().incrementFailedPutRequests(1);
510 return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT)
511 .entity("Bad request: The column to put and check do not match." + CRLF).build();
512 } else {
513 retValue = table.checkAndPut(key, valueToPutParts[0], valueToPutParts[1],
514 valueToCheckCell.getValue(), put);
515 }
516 } else {
517 servlet.getMetrics().incrementFailedPutRequests(1);
518 return Response.status(Response.Status.BAD_REQUEST)
519 .type(MIMETYPE_TEXT).entity("Bad request: Column incorrectly specified." + CRLF)
520 .build();
521 }
522
523 if (LOG.isTraceEnabled()) {
524 LOG.trace("CHECK-AND-PUT " + put.toString() + ", returns " + retValue);
525 }
526 if (!retValue) {
527 servlet.getMetrics().incrementFailedPutRequests(1);
528 return Response.status(Response.Status.NOT_MODIFIED)
529 .type(MIMETYPE_TEXT).entity("Value not Modified" + CRLF)
530 .build();
531 }
532 ResponseBuilder response = Response.ok();
533 servlet.getMetrics().incrementSucessfulPutRequests(1);
534 return response.build();
535 } catch (Exception e) {
536 servlet.getMetrics().incrementFailedPutRequests(1);
537 return processException(e);
538 } finally {
539 if (table != null) try {
540 table.close();
541 } catch (IOException ioe) {
542 LOG.debug("Exception received while closing the table", ioe);
543 }
544 }
545 }
546
547
548
549
550
551
552
553
554 Response checkAndDelete(final CellSetModel model) {
555 Table table = null;
556 Delete delete = null;
557 try {
558 table = servlet.getTable(tableResource.getName());
559 if (model.getRows().size() != 1) {
560 servlet.getMetrics().incrementFailedDeleteRequests(1);
561 return Response.status(Response.Status.BAD_REQUEST)
562 .type(MIMETYPE_TEXT).entity("Bad request: Number of rows specified is not 1." + CRLF)
563 .build();
564 }
565 RowModel rowModel = model.getRows().get(0);
566 byte[] key = rowModel.getKey();
567 if (key == null) {
568 key = rowspec.getRow();
569 }
570 if (key == null) {
571 servlet.getMetrics().incrementFailedDeleteRequests(1);
572 return Response.status(Response.Status.BAD_REQUEST)
573 .type(MIMETYPE_TEXT).entity("Bad request: Row key found to be null." + CRLF)
574 .build();
575 }
576
577 List<CellModel> cellModels = rowModel.getCells();
578 int cellModelCount = cellModels.size();
579
580 delete = new Delete(key);
581 boolean retValue;
582 CellModel valueToDeleteCell = rowModel.getCells().get(cellModelCount -1);
583 byte[] valueToDeleteColumn = valueToDeleteCell.getColumn();
584 if (valueToDeleteColumn == null) {
585 try {
586 valueToDeleteColumn = rowspec.getColumns()[0];
587 } catch (final ArrayIndexOutOfBoundsException e) {
588 servlet.getMetrics().incrementFailedDeleteRequests(1);
589 return Response.status(Response.Status.BAD_REQUEST)
590 .type(MIMETYPE_TEXT).entity("Bad request: Column not specified for check." + CRLF)
591 .build();
592 }
593 }
594
595 byte[][] parts ;
596
597 if(cellModelCount > 1) {
598 for (int i = 0, n = cellModelCount - 1; i < n; i++) {
599 CellModel cell = cellModels.get(i);
600 byte[] col = cell.getColumn();
601
602 if (col == null) {
603 servlet.getMetrics().incrementFailedPutRequests(1);
604 return Response.status(Response.Status.BAD_REQUEST)
605 .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
606 .build();
607 }
608
609 parts = KeyValue.parseColumn(col);
610
611 if (parts.length == 1) {
612
613 delete.addFamily(parts[0], cell.getTimestamp());
614 } else if (parts.length == 2) {
615 delete.addColumn(parts[0], parts[1], cell.getTimestamp());
616 } else {
617 servlet.getMetrics().incrementFailedDeleteRequests(1);
618 return Response.status(Response.Status.BAD_REQUEST)
619 .type(MIMETYPE_TEXT)
620 .entity("Bad request: Column to delete incorrectly specified." + CRLF)
621 .build();
622 }
623 }
624 }
625
626 parts = KeyValue.parseColumn(valueToDeleteColumn);
627 if (parts.length == 2) {
628 if (parts[1].length != 0) {
629
630
631 if(cellModelCount == 1) {
632 delete.addColumns(parts[0], parts[1]);
633 }
634 retValue = table.checkAndDelete(key, parts[0], parts[1],
635 valueToDeleteCell.getValue(), delete);
636 } else {
637
638 if(cellModelCount == 1) {
639 delete.addColumns(parts[0], Bytes.toBytes(StringUtils.EMPTY));
640 }
641 retValue = table.checkAndDelete(key, parts[0], Bytes.toBytes(StringUtils.EMPTY),
642 valueToDeleteCell.getValue(), delete);
643 }
644 } else {
645 servlet.getMetrics().incrementFailedDeleteRequests(1);
646 return Response.status(Response.Status.BAD_REQUEST)
647 .type(MIMETYPE_TEXT).entity("Bad request: Column to check incorrectly specified." + CRLF)
648 .build();
649 }
650
651 if (LOG.isTraceEnabled()) {
652 LOG.trace("CHECK-AND-DELETE " + delete.toString() + ", returns "
653 + retValue);
654 }
655
656 if (!retValue) {
657 servlet.getMetrics().incrementFailedDeleteRequests(1);
658 return Response.status(Response.Status.NOT_MODIFIED)
659 .type(MIMETYPE_TEXT).entity(" Delete check failed." + CRLF)
660 .build();
661 }
662 ResponseBuilder response = Response.ok();
663 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
664 return response.build();
665 } catch (Exception e) {
666 servlet.getMetrics().incrementFailedDeleteRequests(1);
667 return processException(e);
668 } finally {
669 if (table != null) try {
670 table.close();
671 } catch (IOException ioe) {
672 LOG.debug("Exception received while closing the table", ioe);
673 }
674 }
675 }
676
677
678
679
680
681
682
683
684 Response append(final CellSetModel model) {
685 Table table = null;
686 Append append = null;
687 try {
688 table = servlet.getTable(tableResource.getName());
689 if (model.getRows().size() != 1) {
690 servlet.getMetrics().incrementFailedAppendRequests(1);
691 return Response.status(Response.Status.BAD_REQUEST)
692 .type(MIMETYPE_TEXT).entity("Bad request: Number of rows specified is not 1." + CRLF)
693 .build();
694 }
695 RowModel rowModel = model.getRows().get(0);
696 byte[] key = rowModel.getKey();
697 if (key == null) {
698 key = rowspec.getRow();
699 }
700 if (key == null) {
701 servlet.getMetrics().incrementFailedAppendRequests(1);
702 return Response.status(Response.Status.BAD_REQUEST)
703 .type(MIMETYPE_TEXT).entity("Bad request: Row key found to be null." + CRLF)
704 .build();
705 }
706
707 append = new Append(key);
708 append.setReturnResults(returnResult);
709 int i = 0;
710 for (CellModel cell: rowModel.getCells()) {
711 byte[] col = cell.getColumn();
712 if (col == null) {
713 try {
714 col = rowspec.getColumns()[i++];
715 } catch (ArrayIndexOutOfBoundsException e) {
716 col = null;
717 }
718 }
719 if (col == null) {
720 servlet.getMetrics().incrementFailedAppendRequests(1);
721 return Response.status(Response.Status.BAD_REQUEST)
722 .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
723 .build();
724 }
725 byte [][] parts = KeyValue.parseColumn(col);
726 if (parts.length != 2) {
727 servlet.getMetrics().incrementFailedAppendRequests(1);
728 return Response.status(Response.Status.BAD_REQUEST)
729 .type(MIMETYPE_TEXT).entity("Bad request: Column incorrectly specified." + CRLF)
730 .build();
731 }
732 append.add(parts[0], parts[1], cell.getValue());
733 }
734
735 if (LOG.isDebugEnabled()) {
736 LOG.debug("APPEND " + append.toString());
737 }
738 Result result = table.append(append);
739 if (returnResult) {
740 if (result.isEmpty()) {
741 servlet.getMetrics().incrementFailedAppendRequests(1);
742 return Response.status(Response.Status.NOT_MODIFIED)
743 .type(MIMETYPE_TEXT).entity("Append return empty." + CRLF)
744 .build();
745 }
746
747 CellSetModel rModel = new CellSetModel();
748 RowModel rRowModel = new RowModel(result.getRow());
749 for (Cell cell : result.listCells()) {
750 rRowModel.addCell(new CellModel(CellUtil.cloneFamily(cell), CellUtil.cloneQualifier(cell),
751 cell.getTimestamp(), CellUtil.cloneValue(cell)));
752 }
753 rModel.addRow(rRowModel);
754 servlet.getMetrics().incrementSucessfulAppendRequests(1);
755 return Response.ok(rModel).build();
756 }
757 servlet.getMetrics().incrementSucessfulAppendRequests(1);
758 return Response.ok().build();
759 } catch (Exception e) {
760 servlet.getMetrics().incrementFailedAppendRequests(1);
761 return processException(e);
762 } finally {
763 if (table != null) try {
764 table.close();
765 } catch (IOException ioe) {
766 LOG.debug("Exception received while closing the table" + table.getName(), ioe);
767 }
768 }
769 }
770
771
772
773
774
775
776
777
778 Response increment(final CellSetModel model) {
779 Table table = null;
780 Increment increment = null;
781 try {
782 table = servlet.getTable(tableResource.getName());
783 if (model.getRows().size() != 1) {
784 servlet.getMetrics().incrementFailedIncrementRequests(1);
785 return Response.status(Response.Status.BAD_REQUEST)
786 .type(MIMETYPE_TEXT).entity("Bad request: Number of rows specified is not 1." + CRLF)
787 .build();
788 }
789 RowModel rowModel = model.getRows().get(0);
790 byte[] key = rowModel.getKey();
791 if (key == null) {
792 key = rowspec.getRow();
793 }
794 if (key == null) {
795 servlet.getMetrics().incrementFailedIncrementRequests(1);
796 return Response.status(Response.Status.BAD_REQUEST)
797 .type(MIMETYPE_TEXT).entity("Bad request: Row key found to be null." + CRLF)
798 .build();
799 }
800
801 increment = new Increment(key);
802 increment.setReturnResults(returnResult);
803 int i = 0;
804 for (CellModel cell: rowModel.getCells()) {
805 byte[] col = cell.getColumn();
806 if (col == null) {
807 try {
808 col = rowspec.getColumns()[i++];
809 } catch (ArrayIndexOutOfBoundsException e) {
810 col = null;
811 }
812 }
813 if (col == null) {
814 servlet.getMetrics().incrementFailedIncrementRequests(1);
815 return Response.status(Response.Status.BAD_REQUEST)
816 .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
817 .build();
818 }
819 byte [][] parts = KeyValue.parseColumn(col);
820 if (parts.length != 2) {
821 servlet.getMetrics().incrementFailedIncrementRequests(1);
822 return Response.status(Response.Status.BAD_REQUEST)
823 .type(MIMETYPE_TEXT).entity("Bad request: Column incorrectly specified." + CRLF)
824 .build();
825 }
826 increment.addColumn(parts[0], parts[1], Long.parseLong(Bytes.toStringBinary(cell.getValue())));
827 }
828
829 if (LOG.isDebugEnabled()) {
830 LOG.debug("INCREMENT " + increment.toString());
831 }
832 Result result = table.increment(increment);
833
834 if (returnResult) {
835 if (result.isEmpty()) {
836 servlet.getMetrics().incrementFailedIncrementRequests(1);
837 return Response.status(Response.Status.NOT_MODIFIED)
838 .type(MIMETYPE_TEXT).entity("Increment return empty." + CRLF)
839 .build();
840 }
841
842 CellSetModel rModel = new CellSetModel();
843 RowModel rRowModel = new RowModel(result.getRow());
844 for (Cell cell : result.listCells()) {
845 rRowModel.addCell(new CellModel(CellUtil.cloneFamily(cell), CellUtil.cloneQualifier(cell),
846 cell.getTimestamp(), CellUtil.cloneValue(cell)));
847 }
848 rModel.addRow(rowModel);
849 servlet.getMetrics().incrementSucessfulIncrementRequests(1);
850 return Response.ok(rModel).build();
851 }
852
853 ResponseBuilder response = Response.ok();
854 servlet.getMetrics().incrementSucessfulIncrementRequests(1);
855 return response.build();
856 } catch (Exception e) {
857 servlet.getMetrics().incrementFailedIncrementRequests(1);
858 return processException(e);
859 } finally {
860 if (table != null) try {
861 table.close();
862 } catch (IOException ioe) {
863 LOG.debug("Exception received while closing the table " + table.getName(), ioe);
864 }
865 }
866 }
867 }