You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2009/01/22 01:21:18 UTC
svn commit: r736503 [2/4] - in /hadoop/hbase/trunk: ./ lib/
src/java/org/apache/hadoop/hbase/ src/java/org/apache/hadoop/hbase/io/
src/java/org/apache/hadoop/hbase/regionserver/
src/java/org/apache/hadoop/hbase/rest/ src/java/org/apache/hadoop/hbase/re...
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java?rev=736503&r1=736502&r2=736503&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java Wed Jan 21 16:21:16 2009
@@ -1,346 +0,0 @@
-package org.apache.hadoop.hbase.rest;
-
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.io.BatchUpdate;
-import org.apache.hadoop.hbase.io.Cell;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.znerd.xmlenc.XMLOutputter;
-
-public class RowHandler extends GenericHandler {
-
- public RowHandler(HBaseConfiguration conf, HBaseAdmin admin)
- throws ServletException {
- super(conf, admin);
- }
-
- public void doGet(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments) throws ServletException, IOException {
- HTable table = getTable(pathSegments[0]);
- if (pathSegments[1].toLowerCase().equals(ROW)) {
- // get a row
- getRow(table, request, response, pathSegments);
- } else {
- doNotFound(response, "Not handled in RowHandler");
- }
- }
-
- public void doPost(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments) throws ServletException, IOException {
- putRow(request, response, pathSegments);
- }
-
- public void doPut(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments) throws ServletException, IOException {
- doPost(request, response, pathSegments);
- }
-
- public void doDelete(HttpServletRequest request,
- HttpServletResponse response, String[] pathSegments)
- throws ServletException, IOException {
- deleteRow(request, response, pathSegments);
- }
-
- /*
- * @param request
- * @param response
- * @param pathSegments info path split on the '/' character. First segment
- * is the tablename, second is 'row', and third is the row id.
- * @throws IOException
- * Retrieve a row in one of several output formats.
- */
- private void getRow(HTable table, final HttpServletRequest request,
- final HttpServletResponse response, final String [] pathSegments)
- throws IOException {
- // pull the row key out of the path
- byte[] row = Bytes.toBytes(URLDecoder.decode(pathSegments[2], HConstants.UTF8_ENCODING));
-
- String timestampStr = null;
- if (pathSegments.length == 4) {
- // A timestamp has been supplied.
- timestampStr = pathSegments[3];
- if (timestampStr.equals("timestamps")) {
- // Not supported in hbase just yet. TODO
- doMethodNotAllowed(response, "Not yet supported by hbase");
- return;
- }
- }
-
- String[] column_params = request.getParameterValues(COLUMN);
-
- byte[][] columns = null;
-
- if (column_params != null && column_params.length > 0) {
- List<String> available_columns = new ArrayList<String>();
- for (String column_param : column_params) {
- if (column_param.length() > 0 && table.getTableDescriptor().hasFamily(Bytes.toBytes(column_param))) {
- available_columns.add(column_param);
- }
- }
- columns = Bytes.toByteArrays(available_columns.toArray(new String[0]));
- }
-
- String[] version_params = request.getParameterValues(VERSION);
- int version = 0;
- if (version_params != null && version_params.length == 1) {
- version = Integer.parseInt(version_params[0]);
- }
-
- if (version > 0 && columns != null) {
- Map<byte[], Cell[]> result = new TreeMap<byte [], Cell[]>(Bytes.BYTES_COMPARATOR);
-
- for (byte[] col : columns) {
- Cell[] cells = timestampStr == null ? table.get(row, col, version)
- : table.get(row, col, Long.parseLong(timestampStr), version);
- if (cells != null) {
- result.put(col, cells);
- }
- }
-
- if (result == null || result.size() == 0) {
- doNotFound(response, "Row not found!");
- } else {
- switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
- case XML:
- outputRowWithMultiVersionsXml(request, response, result);
- break;
- case MIME:
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: "
- + request.getHeader(CONTENT_TYPE));
- }
- }
- } else {
- Map<byte[], Cell> result = timestampStr == null ? table.getRow(row, columns) : table.getRow(row, columns, Long.parseLong(timestampStr));
- if (result == null || result.size() == 0) {
- doNotFound(response, "Row not found!");
- } else {
- switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
- case XML:
- outputRowXml(request, response, result);
- break;
- case MIME:
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: "
- + request.getHeader(CONTENT_TYPE));
- }
- }
- }
- }
-
- /*
- * Output a row encoded as XML.
- * @param response
- * @param result
- * @throws IOException
- */
- private void outputRowXml(final HttpServletRequest request,
- final HttpServletResponse response, final Map<byte [], Cell> result)
- throws IOException {
- setResponseHeader(response, result.size() > 0? 200: 204,
- ContentType.XML.toString());
- XMLOutputter outputter = getXMLOutputter(response.getWriter());
- outputter.startTag(ROW);
- doElement(outputter, "count", String.valueOf(result.size()));
- outputColumnsXml(request, outputter, result);
- outputter.endTag();
- outputter.endDocument();
- outputter.getWriter().close();
- }
-
- private void outputRowWithMultiVersionsXml(final HttpServletRequest request,
- final HttpServletResponse response, final Map<byte[], Cell[]> result)
- throws IOException {
- setResponseHeader(response, result.size() > 0? 200: 204,
- ContentType.XML.toString());
- XMLOutputter outputter = getXMLOutputter(response.getWriter());
- outputter.startTag(ROW);
- doElement(outputter, "count", String.valueOf(result.size()));
- outputColumnsWithMultiVersionsXml(request, outputter, result);
- outputter.endTag();
- outputter.endDocument();
- outputter.getWriter().close();
- }
- /*
- * @param response
- * @param result
- * Output the results contained in result as a multipart/related response.
- */
- // private void outputRowMime(final HttpServletResponse response,
- // final Map<Text, Cell> result)
- // throws IOException {
- // response.setStatus(result.size() > 0? 200: 204);
- // // This code ties me to the jetty server.
- // MultiPartResponse mpr = new MultiPartResponse(response);
- // // Content type should look like this for multipart:
- // // Content-type: multipart/related;start="<ro...@example.jaxws.sun.com>";type="application/xop+xml";boundary="uuid:94ebf1e6-7eb5-43f1-85f4-2615fc40c5d6";start-info="text/xml"
- // String ct = ContentType.MIME.toString() + ";charset=\"UTF-8\";boundary=\"" +
- // mpr.getBoundary() + "\"";
- // // Setting content type is broken. I'm unable to set parameters on the
- // // content-type; They get stripped. Can't set boundary, etc.
- // // response.addHeader("Content-Type", ct);
- // response.setContentType(ct);
- // outputColumnsMime(mpr, result);
- // mpr.close();
- // }
-
- /*
- * @param request
- * @param response
- * @param pathSegments
- * Do a put based on the client request.
- */
- private void putRow(final HttpServletRequest request,
- final HttpServletResponse response, final String [] pathSegments)
- throws IOException, ServletException {
- HTable table = getTable(pathSegments[0]);
-
- // pull the row key out of the path
- String row = URLDecoder.decode(pathSegments[2], HConstants.UTF8_ENCODING);
-
- switch(ContentType.getContentType(request.getHeader(CONTENT_TYPE))) {
- case XML:
- putRowXml(table, row, request, response, pathSegments);
- break;
- case MIME:
- doNotAcceptable(response, "Don't support multipart/related yet...");
- break;
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: " +
- request.getHeader(CONTENT_TYPE));
- }
- }
-
- /*
- * @param request
- * @param response
- * @param pathSegments
- * Decode supplied XML and do a put to Hbase.
- */
- private void putRowXml(HTable table, String row,
- final HttpServletRequest request, final HttpServletResponse response,
- final String [] pathSegments)
- throws IOException, ServletException{
-
- DocumentBuilderFactory docBuilderFactory
- = DocumentBuilderFactory.newInstance();
- //ignore all comments inside the xml file
- docBuilderFactory.setIgnoringComments(true);
-
- DocumentBuilder builder = null;
- Document doc = null;
-
- String timestamp = pathSegments.length >= 4 ? pathSegments[3] : null;
-
- try{
- builder = docBuilderFactory.newDocumentBuilder();
- doc = builder.parse(request.getInputStream());
- } catch (javax.xml.parsers.ParserConfigurationException e) {
- throw new ServletException(e);
- } catch (org.xml.sax.SAXException e){
- throw new ServletException(e);
- }
-
- BatchUpdate batchUpdate;
-
- try{
- // start an update
- batchUpdate = timestamp == null ?
- new BatchUpdate(row) : new BatchUpdate(row, Long.parseLong(timestamp));
-
- // set the columns from the xml
- NodeList columns = doc.getElementsByTagName("column");
-
- for(int i = 0; i < columns.getLength(); i++){
- // get the current column element we're working on
- Element column = (Element)columns.item(i);
-
- // extract the name and value children
- Node name_node = column.getElementsByTagName("name").item(0);
- String name = name_node.getFirstChild().getNodeValue();
-
- Node value_node = column.getElementsByTagName("value").item(0);
-
- byte[] value = new byte[0];
-
- // for some reason there's no value here. probably indicates that
- // the consumer passed a null as the cell value.
- if(value_node.getFirstChild() != null &&
- value_node.getFirstChild().getNodeValue() != null){
- // decode the base64'd value
- value = org.apache.hadoop.hbase.util.Base64.decode(
- value_node.getFirstChild().getNodeValue());
- }
-
- // put the value
- batchUpdate.put(name, value);
- }
-
- // commit the update
- table.commit(batchUpdate);
-
- // respond with a 200
- response.setStatus(200);
- }
- catch(Exception e){
- throw new ServletException(e);
- }
- }
-
- /*
- * @param request
- * @param response
- * @param pathSegments
- * Delete some or all cells for a row.
- */
- private void deleteRow(final HttpServletRequest request,
- final HttpServletResponse response, final String [] pathSegments)
- throws IOException, ServletException {
- // grab the table we're operating on
- HTable table = getTable(getTableName(pathSegments));
-
- // pull the row key out of the path
- String row = URLDecoder.decode(pathSegments[2], HConstants.UTF8_ENCODING);
-
- String[] columns = request.getParameterValues(COLUMN);
-
- // hack - we'll actually test for the presence of the timestamp parameter
- // eventually
- boolean timestamp_present = false;
- if(timestamp_present){ // do a timestamp-aware delete
- doMethodNotAllowed(response, "DELETE with a timestamp not implemented!");
- }
- else{ // ignore timestamps
- if(columns == null || columns.length == 0){
- // retrieve all the columns
- doMethodNotAllowed(response,
- "DELETE without specified columns not implemented!");
- } else{
- // delete each column in turn
- for(int i = 0; i < columns.length; i++){
- table.deleteAll(row, columns[i]);
- }
- }
- response.setStatus(202);
- }
- }
-}
Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.rest;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.io.BatchUpdate;
+import org.apache.hadoop.hbase.io.RowResult;
+import org.apache.hadoop.hbase.rest.descriptors.TimestampsDescriptor;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+
+public class RowModel extends AbstractModel {
+
+ @SuppressWarnings("unused")
+ private Log LOG = LogFactory.getLog(RowModel.class);
+
+ public RowModel(HBaseConfiguration conf, HBaseAdmin admin) {
+ super.initialize(conf, admin);
+ }
+
+ public RowResult get(byte[] tableName, byte[] rowName)
+ throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ return table.getRow(rowName);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public RowResult get(byte[] tableName, byte[] rowName, byte[][] columns)
+ throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ return table.getRow(rowName, columns);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public RowResult get(byte[] tableName, byte[] rowName, byte[][] columns,
+ long timestamp) throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ return table.getRow(rowName, columns, timestamp);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public RowResult get(byte[] tableName, byte[] rowName, long timestamp)
+ throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ return table.getRow(rowName, timestamp);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public TimestampsDescriptor getTimestamps(
+ @SuppressWarnings("unused") byte[] tableName,
+ @SuppressWarnings("unused") byte[] rowName) throws HBaseRestException {
+ // try {
+ // TimestampsDescriptor tsd = new TimestampsDescriptor();
+ // HTable table = new HTable(tableName);
+ // RowResult row = table.getRow(rowName);
+
+ throw new HBaseRestException("operation currently unsupported");
+
+ // } catch (IOException e) {
+ // throw new HBaseRestException("Error finding timestamps for row: "
+ // + Bytes.toString(rowName), e);
+ // }
+
+ }
+
+ public void post(byte[] tableName, BatchUpdate b) throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ table.commit(b);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public void post(byte[] tableName, List<BatchUpdate> b)
+ throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ table.commit(b);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public void delete(byte[] tableName, byte[] rowName)
+ throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ table.deleteAll(rowName);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public void delete(byte[] tableName, byte[] rowName, byte[][] columns) throws HBaseRestException {
+ try {
+ HTable table = new HTable(tableName);
+ for (byte[] column : columns) {
+ table.deleteAll(rowName, column);
+ }
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+}
Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,358 @@
+/**
+ * Copyright 2007 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.rest;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.filter.RowFilterInterface;
+import org.apache.hadoop.hbase.filter.RowFilterSet;
+import org.apache.hadoop.hbase.filter.StopRowFilter;
+import org.apache.hadoop.hbase.filter.WhileMatchRowFilter;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerDescriptor;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerIdentifier;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+import org.apache.hadoop.hbase.rest.filter.FilterFactory;
+import org.apache.hadoop.hbase.rest.parser.IHBaseRestParser;
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ *
+ */
+public class ScannerController extends AbstractController {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.hadoop.hbase.rest.AbstractController#delete(org.apache.hadoop
+ * .hbase.rest.Status, byte[][], java.util.Map)
+ */
+ @Override
+ public void delete(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap) throws HBaseRestException {
+ ScannerModel innerModel = this.getModel();
+ if (pathSegments.length == 3
+ && Bytes.toString(pathSegments[1]).toLowerCase().equals(
+ RESTConstants.SCANNER)) {
+ // get the scannerId
+ Integer scannerId = null;
+ String scannerIdString = new String(pathSegments[2]);
+ if (!Pattern.matches("^\\d+$", scannerIdString)) {
+ throw new HBaseRestException(
+ "the scannerid in the path and must be an integer");
+ }
+ scannerId = Integer.parseInt(scannerIdString);
+
+ try {
+ innerModel.scannerClose(scannerId);
+ s.setOK();
+ } catch (HBaseRestException e) {
+ s.setNotFound();
+ }
+ } else {
+ s.setBadRequest("invalid query");
+ }
+ s.respond();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.hadoop.hbase.rest.AbstractController#generateModel(org.apache
+ * .hadoop.hbase.HBaseConfiguration,
+ * org.apache.hadoop.hbase.client.HBaseAdmin)
+ */
+ @Override
+ protected AbstractModel generateModel(HBaseConfiguration conf, HBaseAdmin a) {
+ return new ScannerModel(conf, a);
+ }
+
+ protected ScannerModel getModel() {
+ return (ScannerModel) model;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.hadoop.hbase.rest.AbstractController#get(org.apache.hadoop.hbase
+ * .rest.Status, byte[][], java.util.Map)
+ */
+ @Override
+ public void get(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap) throws HBaseRestException {
+
+ s.setBadRequest("invalid query");
+ s.respond();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.hadoop.hbase.rest.AbstractController#post(org.apache.hadoop.
+ * hbase.rest.Status, byte[][], java.util.Map, byte[],
+ * org.apache.hadoop.hbase.rest.parser.IHBaseRestParser)
+ */
+ @Override
+ public void post(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+ throws HBaseRestException {
+ ScannerModel innerModel = this.getModel();
+ byte[] tableName;
+ tableName = pathSegments[0];
+
+ // Otherwise we interpret this request as a scanner request.
+ if (pathSegments.length == 2
+ && Bytes.toString(pathSegments[1]).toLowerCase().equals(
+ RESTConstants.SCANNER)) { // new scanner request
+ ScannerDescriptor sd = this.getScannerDescriptor(queryMap);
+ s.setScannerCreated(createScanner(innerModel, tableName, sd));
+ } else if (pathSegments.length == 3
+ && Bytes.toString(pathSegments[1]).toLowerCase().equals(
+ RESTConstants.SCANNER)) { // open scanner request
+ // first see if the limit variable is present
+ Long numRows = 1L;
+ String[] numRowsString = queryMap.get(RESTConstants.LIMIT);
+ if (numRowsString != null && Pattern.matches("^\\d+$", numRowsString[0])) {
+ numRows = Long.parseLong(numRowsString[0]);
+ }
+ // get the scannerId
+ Integer scannerId = null;
+ String scannerIdString = new String(pathSegments[2]);
+ if (!Pattern.matches("^\\d+$", scannerIdString)) {
+ throw new HBaseRestException(
+ "the scannerid in the path and must be an integer");
+ }
+ scannerId = Integer.parseInt(scannerIdString);
+
+ try {
+ s.setOK(innerModel.scannerGet(scannerId, numRows));
+ } catch (HBaseRestException e) {
+ s.setNotFound();
+ }
+ } else {
+ s.setBadRequest("Unknown Query.");
+ }
+ s.respond();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.hadoop.hbase.rest.AbstractController#put(org.apache.hadoop.hbase
+ * .rest.Status, byte[][], java.util.Map, byte[],
+ * org.apache.hadoop.hbase.rest.parser.IHBaseRestParser)
+ */
+ @Override
+ public void put(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+ throws HBaseRestException {
+
+ s.setBadRequest("invalid query");
+ s.respond();
+
+ }
+
+ private ScannerDescriptor getScannerDescriptor(Map<String, String[]> queryMap) {
+ long timestamp = 0L;
+ byte[] startRow = null;
+ byte[] stopRow = null;
+ String filters = null;
+
+ String[] timeStampString = queryMap.get(RESTConstants.SCANNER_TIMESTAMP);
+ if (timeStampString != null && timeStampString.length == 1) {
+ timestamp = Long.parseLong(timeStampString[0]);
+ }
+
+ String[] startRowString = queryMap.get(RESTConstants.SCANNER_START_ROW);
+ if (startRowString != null && startRowString.length == 1) {
+ startRow = Bytes.toBytes(startRowString[0]);
+ }
+
+ String[] stopRowString = queryMap.get(RESTConstants.SCANNER_STOP_ROW);
+ if (stopRowString != null && stopRowString.length == 1) {
+ stopRow = Bytes.toBytes(stopRowString[0]);
+ }
+
+ String[] filtersStrings = queryMap.get(RESTConstants.SCANNER_FILTER);
+ if (filtersStrings != null && filtersStrings.length > 0) {
+ filters = "";
+ for (@SuppressWarnings("unused")
+ String filter : filtersStrings) {
+ // TODO filters are not hooked up yet... And the String should probably
+ // be changed to a set
+ }
+ }
+ return new ScannerDescriptor(this.getColumnsFromQueryMap(queryMap),
+ timestamp, startRow, stopRow, filters);
+ }
+
+ protected ScannerIdentifier createScanner(ScannerModel innerModel,
+ byte[] tableName, ScannerDescriptor scannerDescriptor)
+ throws HBaseRestException {
+
+ RowFilterInterface filterSet = null;
+
+ // Might want to change this. I am doing this so that I can use
+ // a switch statement that is more efficient.
+ int switchInt = 0;
+ if (scannerDescriptor.getColumns() != null
+ && scannerDescriptor.getColumns().length > 0) {
+ switchInt += 1;
+ }
+ switchInt += (scannerDescriptor.getTimestamp() != 0L) ? (1 << 1) : 0;
+ switchInt += (scannerDescriptor.getStartRow().length > 0) ? (1 << 2) : 0;
+ switchInt += (scannerDescriptor.getStopRow().length > 0) ? (1 << 3) : 0;
+ if (scannerDescriptor.getFilters() != null
+ && !scannerDescriptor.getFilters().equals("")) {
+ switchInt += (scannerDescriptor.getFilters() != null) ? (1 << 4) : 0;
+ filterSet = unionFilters(scannerDescriptor.getFilters());
+ }
+
+ return scannerSwitch(switchInt, innerModel, tableName, scannerDescriptor
+ .getColumns(), scannerDescriptor.getTimestamp(), scannerDescriptor
+ .getStartRow(), scannerDescriptor.getStopRow(), filterSet);
+ }
+
+ public ScannerIdentifier scannerSwitch(int switchInt,
+ ScannerModel innerModel, byte[] tableName, byte[][] columns,
+ long timestamp, byte[] startRow, byte[] stopRow,
+ RowFilterInterface filterSet) throws HBaseRestException {
+ switch (switchInt) {
+ case 0:
+ return innerModel.scannerOpen(tableName);
+ case 1:
+ return innerModel.scannerOpen(tableName, columns);
+ case 2:
+ return innerModel.scannerOpen(tableName, timestamp);
+ case 3:
+ return innerModel.scannerOpen(tableName, columns, timestamp);
+ case 4:
+ return innerModel.scannerOpen(tableName, startRow);
+ case 5:
+ return innerModel.scannerOpen(tableName, columns, startRow);
+ case 6:
+ return innerModel.scannerOpen(tableName, startRow, timestamp);
+ case 7:
+ return innerModel.scannerOpen(tableName, columns, startRow, timestamp);
+ case 8:
+ return innerModel.scannerOpen(tableName, getStopRow(stopRow));
+ case 9:
+ return innerModel.scannerOpen(tableName, columns, getStopRow(stopRow));
+ case 10:
+ return innerModel.scannerOpen(tableName, timestamp, getStopRow(stopRow));
+ case 11:
+ return innerModel.scannerOpen(tableName, columns, timestamp,
+ getStopRow(stopRow));
+ case 12:
+ return innerModel.scannerOpen(tableName, startRow, getStopRow(stopRow));
+ case 13:
+ return innerModel.scannerOpen(tableName, columns, startRow,
+ getStopRow(stopRow));
+ case 14:
+ return innerModel.scannerOpen(tableName, startRow, timestamp,
+ getStopRow(stopRow));
+ case 15:
+ return innerModel.scannerOpen(tableName, columns, startRow, timestamp,
+ getStopRow(stopRow));
+ case 16:
+ return innerModel.scannerOpen(tableName, filterSet);
+ case 17:
+ return innerModel.scannerOpen(tableName, columns, filterSet);
+ case 18:
+ return innerModel.scannerOpen(tableName, timestamp, filterSet);
+ case 19:
+ return innerModel.scannerOpen(tableName, columns, timestamp, filterSet);
+ case 20:
+ return innerModel.scannerOpen(tableName, startRow, filterSet);
+ case 21:
+ return innerModel.scannerOpen(tableName, columns, startRow, filterSet);
+ case 22:
+ return innerModel.scannerOpen(tableName, startRow, timestamp, filterSet);
+ case 23:
+ return innerModel.scannerOpen(tableName, columns, startRow, timestamp,
+ filterSet);
+ case 24:
+ return innerModel.scannerOpen(tableName, getStopRowUnionFilter(stopRow,
+ filterSet));
+ case 25:
+ return innerModel.scannerOpen(tableName, columns, getStopRowUnionFilter(
+ stopRow, filterSet));
+ case 26:
+ return innerModel.scannerOpen(tableName, timestamp,
+ getStopRowUnionFilter(stopRow, filterSet));
+ case 27:
+ return innerModel.scannerOpen(tableName, columns, timestamp,
+ getStopRowUnionFilter(stopRow, filterSet));
+ case 28:
+ return innerModel.scannerOpen(tableName, startRow, getStopRowUnionFilter(
+ stopRow, filterSet));
+ case 29:
+ return innerModel.scannerOpen(tableName, columns, startRow,
+ getStopRowUnionFilter(stopRow, filterSet));
+ case 30:
+ return innerModel.scannerOpen(tableName, startRow, timestamp,
+ getStopRowUnionFilter(stopRow, filterSet));
+ case 31:
+ return innerModel.scannerOpen(tableName, columns, startRow, timestamp,
+ getStopRowUnionFilter(stopRow, filterSet));
+ default:
+ return null;
+ }
+ }
+
+ protected RowFilterInterface getStopRow(byte[] stopRow) {
+ return new WhileMatchRowFilter(new StopRowFilter(stopRow));
+ }
+
+ protected RowFilterInterface getStopRowUnionFilter(byte[] stopRow,
+ RowFilterInterface filter) {
+ Set<RowFilterInterface> filterSet = new HashSet<RowFilterInterface>();
+ filterSet.add(getStopRow(stopRow));
+ filterSet.add(filter);
+ return new RowFilterSet(filterSet);
+ }
+
+ /**
+ * Given a list of filters in JSON string form, returns a RowSetFilter that
+ * returns true if all input filters return true on a Row (aka an AND
+ * statement).
+ *
+ * @param filters
+ * array of input filters in a JSON String
+ * @return RowSetFilter with all input filters in an AND Statement
+ * @throws org.apache.hadoop.hbase.rest.exception.HBaseRestException
+ */
+ protected RowFilterInterface unionFilters(String filters)
+ throws HBaseRestException {
+ FilterFactory f = RESTConstants.filterFactories.get("RowFilterSet");
+ return f.getFilterFromJSON(filters);
+ }
+
+}
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java?rev=736503&r1=736502&r2=736503&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java Wed Jan 21 16:21:16 2009
@@ -1,339 +0,0 @@
-/**
- * Copyright 2007 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase.rest;
-
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.client.Scanner;
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.hadoop.hbase.util.JenkinsHash;
-import org.apache.hadoop.hbase.io.Cell;
-import org.apache.hadoop.hbase.io.RowResult;
-import org.znerd.xmlenc.XMLOutputter;
-
-/**
- * ScannderHandler fields all scanner related requests.
- */
-public class ScannerHandler extends GenericHandler {
- private static final String ROWS = "rows";
-
- public ScannerHandler(HBaseConfiguration conf, HBaseAdmin admin)
- throws ServletException{
- super(conf, admin);
- }
-
- private class ScannerRecord {
- private final Scanner scanner;
- private List<RowResult> nextRows;
-
- ScannerRecord(final Scanner s) {
- this.scanner = s;
- nextRows = new ArrayList<RowResult>();
- }
-
- public Scanner getScanner() {
- return this.scanner;
- }
-
- public boolean hasNext(int nbRows) throws IOException {
- if (nextRows.size() < nbRows) {
- RowResult[] results = scanner.next(nbRows - nextRows.size());
- for (RowResult result : results) {
- nextRows.add(result);
- }
- return nextRows.size() > 0;
- } else {
- return true;
- }
- }
-
- /**
- * Call next on the scanner.
- * @return Null if finished, RowResult otherwise
- * @throws IOException
- */
- public RowResult[] next(int nbRows) throws IOException {
- if (!hasNext(nbRows)) {
- return null;
- }
- RowResult[] temp = nextRows.toArray(new RowResult[nextRows.size()]);
- nextRows.clear();
- return temp;
- }
- }
-
- /*
- * Map of outstanding scanners keyed by scannerid.
- */
- private final Map<String, ScannerRecord> scanners =
- new HashMap<String, ScannerRecord>();
-
- public void doGet(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- doMethodNotAllowed(response, "GET to a scanner not supported.");
- }
-
- public void doPost(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- if (pathSegments.length == 2) {
- // trying to create a scanner
- openScanner(request, response, pathSegments);
- }
- else if (pathSegments.length == 3) {
- // advancing a scanner
- getScanner(request, response, pathSegments[2]);
- }
- else{
- doNotFound(response, "No handler for request");
- }
- }
-
- public void doPut(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- doPost(request, response, pathSegments);
- }
-
- public void doDelete(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- deleteScanner(response, pathSegments[2]);
- }
-
- /*
- * Advance scanner and return current position.
- * @param request
- * @param response
- * @param scannerid
- * @throws IOException
- */
- private void getScanner(final HttpServletRequest request,
- final HttpServletResponse response, final String scannerid)
- throws IOException {
- ScannerRecord sr = this.scanners.get(scannerid);
- if (sr == null) {
- doNotFound(response, "No such scanner.");
- return;
- }
-
- String limitString = request.getParameter(LIMIT);
- int limit = 1;
- if (limitString != null && limitString.length() > 0) {
- limit = Integer.valueOf(limitString);
- }
- if (sr.hasNext(limit)) {
- switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
- case XML:
- outputScannerEntryXML(response, sr, limit);
- break;
- case MIME:
-/* outputScannerEntryMime(response, sr);*/
- doNotAcceptable(response);
- break;
- default:
- doNotAcceptable(response);
- }
- }
- else{
- this.scanners.remove(scannerid);
- doNotFound(response, "Scanner is expended");
- }
- }
-
- private void outputScannerEntryXML(final HttpServletResponse response,
- final ScannerRecord sr, int limit)
- throws IOException {
- // respond with a 200 and Content-type: text/xml
- setResponseHeader(response, 200, ContentType.XML.toString());
-
- // setup an xml outputter
- XMLOutputter outputter = getXMLOutputter(response.getWriter());
-
- boolean rows = false;
-
- if (limit > 1) {
- outputter.startTag(ROWS);
- rows = true;
- }
-
- RowResult[] rowResults = sr.next(limit);
-
- for (RowResult rowResult: rowResults) {
- outputter.startTag(ROW);
-
- // write the row key
- doElement(outputter, "name",
- org.apache.hadoop.hbase.util.Base64.encodeBytes(rowResult.getRow()));
-
- outputColumnsXml(outputter, rowResult);
- outputter.endTag();
- }
-
- if (rows) {
- outputter.endTag();
- }
-
- outputter.endDocument();
- outputter.getWriter().close();
- }
-
- // private void outputScannerEntryMime(final HttpServletResponse response,
- // final ScannerRecord sr)
- // throws IOException {
- // response.setStatus(200);
- // // This code ties me to the jetty server.
- // MultiPartResponse mpr = new MultiPartResponse(response);
- // // Content type should look like this for multipart:
- // // Content-type: multipart/related;start="<ro...@example.jaxws.sun.com>";type="application/xop+xml";boundary="uuid:94ebf1e6-7eb5-43f1-85f4-2615fc40c5d6";start-info="text/xml"
- // String ct = ContentType.MIME.toString() + ";charset=\"UTF-8\";boundary=\"" +
- // mpr.getBoundary() + "\"";
- // // Setting content type is broken. I'm unable to set parameters on the
- // // content-type; They get stripped. Can't set boundary, etc.
- // // response.addHeader("Content-Type", ct);
- // response.setContentType(ct);
- // // Write row, key-column and timestamp each in its own part.
- // mpr.startPart("application/octet-stream",
- // new String [] {"Content-Description: row",
- // "Content-Transfer-Encoding: binary",
- // "Content-Length: " + sr.getKey().getRow().getBytes().length});
- // mpr.getOut().write(sr.getKey().getRow().getBytes());
- //
- // // Usually key-column is empty when scanning.
- // if (sr.getKey().getColumn() != null &&
- // sr.getKey().getColumn().getLength() > 0) {
- // mpr.startPart("application/octet-stream",
- // new String [] {"Content-Description: key-column",
- // "Content-Transfer-Encoding: binary",
- // "Content-Length: " + sr.getKey().getColumn().getBytes().length});
- // }
- // mpr.getOut().write(sr.getKey().getColumn().getBytes());
- // // TODO: Fix. Need to write out the timestamp in the ordained timestamp
- // // format.
- // byte [] timestampBytes = Long.toString(sr.getKey().getTimestamp()).getBytes();
- // mpr.startPart("application/octet-stream",
- // new String [] {"Content-Description: timestamp",
- // "Content-Transfer-Encoding: binary",
- // "Content-Length: " + timestampBytes.length});
- // mpr.getOut().write(timestampBytes);
- // // Write out columns
- // outputColumnsMime(mpr, sr.getValue());
- // mpr.close();
- // }
-
- /*
- * Create scanner
- * @param request
- * @param response
- * @param pathSegments
- * @throws IOException
- */
- private void openScanner(final HttpServletRequest request,
- final HttpServletResponse response, final String [] pathSegments)
- throws IOException, ServletException {
- // get the table
- HTable table = getTable(getTableName(pathSegments));
-
- // get the list of columns we're supposed to interact with
- String[] raw_columns = request.getParameterValues(COLUMN);
- byte [][] columns = null;
-
- if (raw_columns != null) {
- columns = new byte [raw_columns.length][];
- for (int i = 0; i < raw_columns.length; i++) {
- // I think this decoding is redundant.
- columns[i] =
- Bytes.toBytes(URLDecoder.decode(raw_columns[i], HConstants.UTF8_ENCODING));
- }
- } else {
- // TODO: Need to put into the scanner all of the table's column
- // families. TODO: Verify this returns all rows. For now just fail.
- doMethodNotAllowed(response, "Unspecified columns parameter currently not supported!");
- return;
- }
-
- // TODO: Parse according to the timestamp format we agree on.
- String raw_ts = request.getParameter(TIMESTAMP);
-
- // TODO: Are these decodings redundant?
- byte [] startRow = request.getParameter(START_ROW) == null?
- HConstants.EMPTY_START_ROW:
- Bytes.toBytes(URLDecoder.decode(request.getParameter(START_ROW),
- HConstants.UTF8_ENCODING));
- // Empty start row is same value as empty end row.
- byte [] endRow = request.getParameter(END_ROW) == null?
- HConstants.EMPTY_START_ROW:
- Bytes.toBytes(URLDecoder.decode(request.getParameter(END_ROW),
- HConstants.UTF8_ENCODING));
-
- Scanner scanner = (request.getParameter(END_ROW) == null)?
- table.getScanner(columns, startRow):
- table.getScanner(columns, startRow, endRow);
-
- // Make a scanner id by hashing the object toString value (object name +
- // an id). Will make identifier less burdensome and more url friendly.
- String scannerid =
- Integer.toHexString(JenkinsHash.getInstance().hash(scanner.toString().getBytes(), -1));
- ScannerRecord sr = new ScannerRecord(scanner);
-
- // store the scanner for subsequent requests
- this.scanners.put(scannerid, sr);
-
- // set a 201 (Created) header and a Location pointing to the new
- // scanner
- response.setStatus(201);
- response.addHeader("Location", request.getContextPath() + "/" +
- pathSegments[0] + "/" + pathSegments[1] + "/" + scannerid);
- response.getOutputStream().close();
- }
-
- /*
- * Delete scanner
- * @param response
- * @param scannerid
- * @throws IOException
- */
- private void deleteScanner(final HttpServletResponse response,
- final String scannerid)
- throws IOException, ServletException {
- ScannerRecord sr = this.scanners.remove(scannerid);
- if (sr == null) {
- doNotFound(response, "No such scanner");
- } else {
- sr.getScanner().close();
- response.setStatus(200);
- response.getOutputStream().close();
- }
- }
-}
Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,282 @@
+/**
+ * Copyright 2007 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.rest;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Scanner;
+import org.apache.hadoop.hbase.filter.RowFilterInterface;
+import org.apache.hadoop.hbase.io.RowResult;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerIdentifier;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+
+/**
+ *
+ */
+public class ScannerModel extends AbstractModel {
+
+ @SuppressWarnings("unused")
+ private Log LOG = LogFactory.getLog(TableModel.class);
+
+ public ScannerModel(HBaseConfiguration config, HBaseAdmin admin) {
+ super.initialize(config, admin);
+ }
+
+ //
+ // Normal Scanner
+ //
+ protected static class ScannerMaster {
+
+ protected static Map<Integer, Scanner> scannerMap = new ConcurrentHashMap<Integer, Scanner>();
+ protected static AtomicInteger nextScannerId = new AtomicInteger(1);
+
+ public Integer addScanner(Scanner scanner) {
+ Integer i = new Integer(nextScannerId.getAndIncrement());
+ scannerMap.put(i, scanner);
+ return i;
+ }
+
+ public Scanner getScanner(Integer id) {
+ return scannerMap.get(id);
+ }
+
+ public Scanner removeScanner(Integer id) {
+ return scannerMap.remove(id);
+ }
+
+ /**
+ * @param id
+ * id of scanner to close
+ */
+ public void scannerClose(Integer id) {
+ Scanner s = scannerMap.remove(id);
+ s.close();
+ }
+ }
+
+ protected static ScannerMaster scannerMaster = new ScannerMaster();
+
+ /**
+ * returns the next numResults RowResults from the Scaner mapped to Integer
+ * id. If the end of the table is reached, the scanner is closed and all
+ * succesfully retrieved rows are returned.
+ *
+ * @param id
+ * id target scanner is mapped to.
+ * @param numRows
+ * number of results to return.
+ * @return all successfully retrieved rows.
+ * @throws org.apache.hadoop.hbase.rest.exception.HBaseRestException
+ */
+ public RowResult[] scannerGet(Integer id, Long numRows)
+ throws HBaseRestException {
+ try {
+ ArrayList<RowResult> a;
+ Scanner s;
+ RowResult r;
+
+ a = new ArrayList<RowResult>();
+ s = scannerMaster.getScanner(id);
+
+ if (s == null) {
+ throw new HBaseRestException("ScannerId: " + id
+ + " is unavailable. Please create a new scanner");
+ }
+
+ for (int i = 0; i < numRows; i++) {
+ if ((r = s.next()) != null) {
+ a.add(r);
+ } else {
+ scannerMaster.scannerClose(id);
+ break;
+ }
+ }
+
+ return a.toArray(new RowResult[0]);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ /**
+ * Returns all rows inbetween the scanners current position and the end of the
+ * table.
+ *
+ * @param id
+ * id of scanner to use
+ * @return all rows till end of table
+ * @throws org.apache.hadoop.hbase.rest.exception.HBaseRestException
+ */
+ public RowResult[] scannerGet(Integer id) throws HBaseRestException {
+ try {
+ ArrayList<RowResult> a;
+ Scanner s;
+ RowResult r;
+
+ a = new ArrayList<RowResult>();
+ s = scannerMaster.getScanner(id);
+
+ while ((r = s.next()) != null) {
+ a.add(r);
+ }
+
+ scannerMaster.scannerClose(id);
+
+ return a.toArray(new RowResult[0]);
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public boolean scannerClose(Integer id) throws HBaseRestException {
+ Scanner s = scannerMaster.removeScanner(id);
+
+ if (s == null) {
+ throw new HBaseRestException("Scanner id: " + id + " does not exist");
+ }
+ return true;
+ }
+
+ // Scanner Open Methods
+ // No Columns
+ public ScannerIdentifier scannerOpen(byte[] tableName)
+ throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName));
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, long timestamp)
+ throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName), timestamp);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow)
+ throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName), startRow);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow,
+ long timestamp) throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName), startRow, timestamp);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName,
+ RowFilterInterface filter) throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName), filter);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, long timestamp,
+ RowFilterInterface filter) throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName), timestamp, filter);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow,
+ RowFilterInterface filter) throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName), startRow, filter);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow,
+ long timestamp, RowFilterInterface filter) throws HBaseRestException {
+ return scannerOpen(tableName, getColumns(tableName), startRow, timestamp,
+ filter);
+ }
+
+ // With Columns
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+ long timestamp) throws HBaseRestException {
+ try {
+ HTable table;
+ table = new HTable(tableName);
+ return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+ columns, HConstants.EMPTY_START_ROW, timestamp)));
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns)
+ throws HBaseRestException {
+ return scannerOpen(tableName, columns, HConstants.LATEST_TIMESTAMP);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+ byte[] startRow, long timestamp) throws HBaseRestException {
+ try {
+ HTable table;
+ table = new HTable(tableName);
+ return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+ columns, startRow, timestamp)));
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+ byte[] startRow) throws HBaseRestException {
+ return scannerOpen(tableName, columns, startRow,
+ HConstants.LATEST_TIMESTAMP);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+ long timestamp, RowFilterInterface filter) throws HBaseRestException {
+ try {
+ HTable table;
+ table = new HTable(tableName);
+ return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+ columns, HConstants.EMPTY_START_ROW, timestamp, filter)));
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+ RowFilterInterface filter) throws HBaseRestException {
+ return scannerOpen(tableName, columns, HConstants.LATEST_TIMESTAMP, filter);
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+ byte[] startRow, long timestamp, RowFilterInterface filter)
+ throws HBaseRestException {
+ try {
+ HTable table;
+ table = new HTable(tableName);
+ return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+ columns, startRow, timestamp, filter)));
+ } catch (IOException e) {
+ throw new HBaseRestException(e);
+ }
+ }
+
+ public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+ byte[] startRow, RowFilterInterface filter) throws HBaseRestException {
+ return scannerOpen(tableName, columns, startRow,
+ HConstants.LATEST_TIMESTAMP, filter);
+ }
+
+}
Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,256 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.rest;
+
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerIdentifier;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+import org.apache.hadoop.hbase.rest.serializer.IRestSerializer;
+import org.apache.hadoop.hbase.rest.serializer.ISerializable;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import agilejson.TOJSON;
+
+public class Status {
+
+ @SuppressWarnings("unused")
+ private Log LOG = LogFactory.getLog(Status.class);
+
+ public static final HashMap<Integer, String> statNames = new HashMap<Integer, String>();
+
+ static {
+ statNames.put(HttpServletResponse.SC_CONTINUE, "continue");
+ statNames.put(HttpServletResponse.SC_SWITCHING_PROTOCOLS,
+ "switching protocols");
+ statNames.put(HttpServletResponse.SC_OK, "ok");
+ statNames.put(HttpServletResponse.SC_CREATED, "created");
+ statNames.put(HttpServletResponse.SC_ACCEPTED, "accepted");
+ statNames.put(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION,
+ "non-authoritative information");
+ statNames.put(HttpServletResponse.SC_NO_CONTENT, "no content");
+ statNames.put(HttpServletResponse.SC_RESET_CONTENT, "reset content");
+ statNames.put(HttpServletResponse.SC_PARTIAL_CONTENT, "partial content");
+ statNames.put(HttpServletResponse.SC_MULTIPLE_CHOICES, "multiple choices");
+ statNames
+ .put(HttpServletResponse.SC_MOVED_PERMANENTLY, "moved permanently");
+ statNames
+ .put(HttpServletResponse.SC_MOVED_TEMPORARILY, "moved temporarily");
+ statNames.put(HttpServletResponse.SC_FOUND, "found");
+ statNames.put(HttpServletResponse.SC_SEE_OTHER, "see other");
+ statNames.put(HttpServletResponse.SC_NOT_MODIFIED, "not modified");
+ statNames.put(HttpServletResponse.SC_USE_PROXY, "use proxy");
+ statNames.put(HttpServletResponse.SC_TEMPORARY_REDIRECT,
+ "temporary redirect");
+ statNames.put(HttpServletResponse.SC_BAD_REQUEST, "bad request");
+ statNames.put(HttpServletResponse.SC_UNAUTHORIZED, "unauthorized");
+ statNames.put(HttpServletResponse.SC_FORBIDDEN, "forbidden");
+ statNames.put(HttpServletResponse.SC_NOT_FOUND, "not found");
+ statNames.put(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
+ "method not allowed");
+ statNames.put(HttpServletResponse.SC_NOT_ACCEPTABLE, "not acceptable");
+ statNames.put(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED,
+ "proxy authentication required");
+ statNames.put(HttpServletResponse.SC_REQUEST_TIMEOUT, "request timeout");
+ statNames.put(HttpServletResponse.SC_CONFLICT, "conflict");
+ statNames.put(HttpServletResponse.SC_GONE, "gone");
+ statNames.put(HttpServletResponse.SC_LENGTH_REQUIRED, "length required");
+ statNames.put(HttpServletResponse.SC_PRECONDITION_FAILED,
+ "precondition failed");
+ statNames.put(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
+ "request entity too large");
+ statNames.put(HttpServletResponse.SC_REQUEST_URI_TOO_LONG,
+ "request uri too long");
+ statNames.put(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
+ "unsupported media type");
+ statNames.put(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE,
+ "requested range not satisfiable");
+ statNames.put(HttpServletResponse.SC_EXPECTATION_FAILED,
+ "expectation failed");
+ statNames.put(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ "internal server error");
+ statNames.put(HttpServletResponse.SC_NOT_IMPLEMENTED, "not implemented");
+ statNames.put(HttpServletResponse.SC_BAD_GATEWAY, "bad gateway");
+ statNames.put(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
+ "service unavailable");
+ statNames.put(HttpServletResponse.SC_GATEWAY_TIMEOUT, "gateway timeout");
+ statNames.put(HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED,
+ "http version not supported");
+ }
+ protected int statusCode;
+ protected HttpServletResponse response;
+ protected Object message;
+ protected IRestSerializer serializer;
+ protected byte[][] pathSegments;
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ @TOJSON
+ public Object getMessage() {
+ return message;
+ }
+
+ public static class StatusMessage implements ISerializable {
+ int statusCode;
+ boolean error;
+ Object reason;
+
+ public StatusMessage(int statusCode, boolean error, Object o) {
+ this.statusCode = statusCode;
+ this.error = error;
+ reason = o;
+ }
+
+ @TOJSON
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ @TOJSON
+ public boolean getError() {
+ return error;
+ }
+
+ @TOJSON
+ public Object getMessage() {
+ return reason;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.hadoop.hbase.rest.xml.IOutputXML#toXML(org.apache.hadoop.hbase
+ * .rest.serializer.IRestSerializer)
+ */
+ public void restSerialize(IRestSerializer serializer)
+ throws HBaseRestException {
+ serializer.serializeStatusMessage(this);
+ }
+ }
+
+ public Status(HttpServletResponse r, IRestSerializer serializer, byte[][] bs) {
+ this.setOK();
+ this.response = r;
+ this.serializer = serializer;
+ this.pathSegments = bs;
+ }
+
+ // Good Messages
+ public void setOK() {
+ this.statusCode = HttpServletResponse.SC_OK;
+ this.message = new StatusMessage(HttpServletResponse.SC_OK, false, "success");
+ }
+
+ public void setOK(Object message) {
+ this.statusCode = HttpServletResponse.SC_OK;
+ this.message = message;
+ }
+
+ public void setAccepted() {
+ this.statusCode = HttpServletResponse.SC_ACCEPTED;
+ this.message = new StatusMessage(HttpServletResponse.SC_ACCEPTED, false, "success");
+ }
+
+ public void setExists(boolean error) {
+ this.statusCode = HttpServletResponse.SC_CONFLICT;
+ this.message = new StatusMessage(statusCode, error, "table already exists");
+ }
+
+ public void setCreated() {
+ this.statusCode = HttpServletResponse.SC_CREATED;
+ this.setOK();
+ }
+
+ public void setScannerCreated(ScannerIdentifier scannerIdentifier) {
+ this.statusCode = HttpServletResponse.SC_OK;
+ this.message = scannerIdentifier;
+ response.addHeader("Location", "/" + Bytes.toString(pathSegments[0])
+ + "/scanner/" + scannerIdentifier.getId());
+ }
+ // Bad Messages
+
+ public void setInternalError(Exception e) {
+ this.statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+ this.message = new StatusMessage(statusCode, true, e);
+ }
+
+ public void setNoQueryResults() {
+ this.statusCode = HttpServletResponse.SC_NOT_FOUND;
+ this.message = new StatusMessage(statusCode, true, "no query results");
+ }
+
+ public void setConflict(Object message) {
+ this.statusCode = HttpServletResponse.SC_CONFLICT;
+ this.message = new StatusMessage(statusCode, true, message);
+ }
+
+ public void setNotFound(Object message) {
+ this.statusCode = HttpServletResponse.SC_NOT_FOUND;
+ this.message = new StatusMessage(statusCode, true, message);
+ }
+
+ public void setBadRequest(Object message) {
+ this.statusCode = HttpServletResponse.SC_BAD_REQUEST;
+ this.message = new StatusMessage(statusCode, true, message);
+ }
+
+ public void setNotFound() {
+ setNotFound("Unable to find requested URI");
+ }
+
+ public void setMethodNotImplemented() {
+ this.statusCode = HttpServletResponse.SC_METHOD_NOT_ALLOWED;
+ this.message = new StatusMessage(statusCode, true, "method not implemented");
+ }
+
+ public void setInvalidURI() {
+ setInvalidURI("Invalid URI");
+ }
+
+ public void setInvalidURI(Object message) {
+ this.statusCode = HttpServletResponse.SC_BAD_REQUEST;
+ this.message = new StatusMessage(statusCode, true, message);
+ }
+
+ public void setUnsupportedMediaType(Object message) {
+ this.statusCode = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
+ this.message = new StatusMessage(statusCode, true, message);
+ }
+
+ public void setGone() {
+ this.statusCode = HttpServletResponse.SC_GONE;
+ this.message = new StatusMessage(statusCode, true, "item no longer available");
+ }
+
+
+ // Utility
+ public void respond() throws HBaseRestException {
+ response.setStatus(this.statusCode);
+ this.serializer.writeOutput(this.message);
+ }
+
+}
Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,170 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.rest;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+import org.apache.hadoop.hbase.rest.parser.IHBaseRestParser;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TableController extends AbstractController {
+
+ @SuppressWarnings("unused")
+ private Log LOG = LogFactory.getLog(TableController.class);
+
+ protected TableModel getModel() {
+ return (TableModel) model;
+ }
+
+ @Override
+ protected AbstractModel generateModel(
+ @SuppressWarnings("hiding") HBaseConfiguration conf, HBaseAdmin admin) {
+ return new TableModel(conf, admin);
+ }
+
+ @Override
+ public void get(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap) throws HBaseRestException {
+ TableModel innerModel = getModel();
+
+ byte[] tableName;
+
+ tableName = pathSegments[0];
+ if (pathSegments.length < 2) {
+ s.setOK(innerModel.getTableMetadata(Bytes.toString(tableName)));
+ } else {
+ if (Bytes.toString(pathSegments[1]).toLowerCase().equals(REGIONS)) {
+ s.setOK(innerModel.getTableRegions(Bytes.toString(tableName)));
+ } else {
+ s.setBadRequest("unknown query.");
+ }
+ }
+ s.respond();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @param input column descriptor JSON. Should be of the form: <pre>
+ * {"column_families":[ { "name":STRING, "bloomfilter":BOOLEAN,
+ * "max_versions":INTEGER, "compression_type":STRING, "in_memory":BOOLEAN,
+ * "block_cache_enabled":BOOLEAN, "max_value_length":INTEGER,
+ * "time_to_live":INTEGER ]} </pre> If any of the json object fields (except
+ * name) are not included the default values will be included instead. The
+ * default values are: <pre> bloomfilter => false max_versions => 3
+ * compression_type => NONE in_memory => false block_cache_enabled => false
+ * max_value_length => 2147483647 time_to_live => Integer.MAX_VALUE </pre>
+ *
+ * @see
+ * org.apache.hadoop.hbase.rest.AbstractController#post(org.apache.hadoop.
+ * hbase.rest.Status, byte[][], java.util.Map, byte[],
+ * org.apache.hadoop.hbase.rest.parser.IHBaseRestParser)
+ */
+ @Override
+ public void post(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+ throws HBaseRestException {
+ TableModel innerModel = getModel();
+
+ byte[] tableName;
+
+ if (pathSegments.length == 0) {
+ // If no input, we don't know columnfamily schema, so send
+ // no data
+ if (input.length == 0) {
+ s.setBadRequest("no data send with post request");
+ } else {
+ HTableDescriptor htd = parser.getTableDescriptor(input);
+ // Send to innerModel. If iM returns false, means the
+ // table already exists so return conflict.
+ if (!innerModel.post(htd.getName(), htd)) {
+ s.setConflict("table already exists");
+ } else {
+ // Otherwise successfully created table. Return "created":true
+ s.setCreated();
+ }
+ }
+ } else if (Bytes.toString(pathSegments[1]).toLowerCase().equals(
+ RESTConstants.ENABLE)) {
+ tableName = pathSegments[0];
+ innerModel.enableTable(tableName);
+ s.setAccepted();
+ } else if (Bytes.toString(pathSegments[1]).toLowerCase().equals(
+ RESTConstants.DISABLE)) {
+ tableName = pathSegments[0];
+ innerModel.disableTable(tableName);
+ s.setAccepted();
+ } else {
+ s.setBadRequest("Unknown Query.");
+ }
+ s.respond();
+ }
+
+ @Override
+ public void put(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+ throws HBaseRestException {
+ if (pathSegments.length != 1) {
+ s.setBadRequest("must specifify the name of the table");
+ s.respond();
+ } else if (queryMap.size() > 0) {
+ s
+ .setBadRequest("no query string should be specified when updating a table");
+ s.respond();
+ } else {
+ ArrayList<HColumnDescriptor> newColumns = parser
+ .getColumnDescriptors(input);
+ byte[] tableName = pathSegments[0];
+ getModel().updateTable(Bytes.toString(tableName), newColumns);
+ s.setOK();
+ s.respond();
+ }
+ }
+
+ @Override
+ public void delete(Status s, byte[][] pathSegments,
+ Map<String, String[]> queryMap) throws HBaseRestException {
+ TableModel innerModel = getModel();
+
+ byte[] tableName;
+
+ tableName = pathSegments[0];
+
+ if (pathSegments.length == 1) {
+ if (!innerModel.delete(tableName)) {
+ s.setBadRequest("table does not exist");
+ } else {
+ s.setAccepted();
+ }
+ s.respond();
+ } else {
+
+ }
+ }
+
+}
\ No newline at end of file
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java?rev=736503&r1=736502&r2=736503&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java Wed Jan 21 16:21:16 2009
@@ -1,416 +0,0 @@
-/**
- * Copyright 2007 The Apache Software Foundation
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase.rest;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HColumnDescriptor;
-import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.HColumnDescriptor.CompressionType;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.znerd.xmlenc.XMLOutputter;
-
-
-/**
- * TableHandler fields all requests that deal with an individual table.
- * That means all requests that start with /api/[table_name]/... go to
- * this handler.
- */
-public class TableHandler extends GenericHandler {
- public static final String DISABLE = "disable";
- public static final String ENABLE = "enable";
-
- public TableHandler(HBaseConfiguration conf, HBaseAdmin admin)
- throws ServletException{
- super(conf, admin);
- }
-
- public void doGet(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- // if it's just table name, return the metadata
- if (pathSegments.length == 1) {
- getTableMetadata(request, response, pathSegments[0]);
- }
- else{
- HTable table = getTable(pathSegments[0]);
- if (pathSegments[1].toLowerCase().equals(REGIONS)) {
- // get a region list
- getTableRegions(table, request, response);
- }
- else{
- doNotFound(response, "Not handled in TableHandler");
- }
- }
- }
-
- public void doPost(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- if (pathSegments.length == 0 || pathSegments[0].length() <= 0) {
- // if it's a creation operation
- putTable(request, response, pathSegments);
- } else {
- // if it's a disable operation or enable operation
- String tableName = pathSegments[0];
- if (pathSegments[1].toLowerCase().equals(DISABLE)) {
- admin.disableTable(tableName);
- } else if (pathSegments[1].toLowerCase().equals(ENABLE)) {
- admin.enableTable(tableName);
- }
- response.setStatus(202);
- }
- }
-
- public void doPut(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- updateTable(request, response, pathSegments);
- }
-
- public void doDelete(HttpServletRequest request, HttpServletResponse response,
- String[] pathSegments)
- throws ServletException, IOException {
- deleteTable(request, response, pathSegments);
- }
-
- /*
- * Return region offsets.
- * @param request
- * @param response
- */
- private void getTableRegions(HTable table, final HttpServletRequest request,
- final HttpServletResponse response)
- throws IOException {
- // Presumption is that this.table has already been focused on target table.
- byte [][] startKeys = table.getStartKeys();
- // Presumption is that this.table has already been set against target table
- switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
- case XML:
- setResponseHeader(response, startKeys.length > 0? 200: 204,
- ContentType.XML.toString());
- XMLOutputter outputter = getXMLOutputter(response.getWriter());
- outputter.startTag("regions");
- for (int i = 0; i < startKeys.length; i++) {
- doElement(outputter, "region", Bytes.toString(startKeys[i]));
- }
- outputter.endTag();
- outputter.endDocument();
- outputter.getWriter().close();
- break;
- case PLAIN:
- setResponseHeader(response, startKeys.length > 0? 200: 204,
- ContentType.PLAIN.toString());
- PrintWriter out = response.getWriter();
- for (int i = 0; i < startKeys.length; i++) {
- // TODO: Add in the server location. Is it needed?
- out.print(Bytes.toString(startKeys[i]));
- }
- out.close();
- break;
- case MIME:
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: " +
- request.getHeader(CONTENT_TYPE));
- }
- }
- /*
- * Get table metadata.
- * @param request
- * @param response
- * @param tableName
- * @throws IOException
- */
- private void getTableMetadata(final HttpServletRequest request,
- final HttpServletResponse response, final String tableName)
- throws IOException {
- HTableDescriptor [] tables = this.admin.listTables();
- HTableDescriptor descriptor = null;
- for (int i = 0; i < tables.length; i++) {
- if (Bytes.toString(tables[i].getName()).equals(tableName)) {
- descriptor = tables[i];
- break;
- }
- }
- if (descriptor == null) {
- doNotFound(response, "Table not found!");
- } else {
- // Presumption is that this.table has already been set against target table
- ContentType type = ContentType.getContentType(request.getHeader(ACCEPT));
- switch (type) {
- case XML:
- setResponseHeader(response, 200, ContentType.XML.toString());
- XMLOutputter outputter = getXMLOutputter(response.getWriter());
- outputter.startTag("table");
- doElement(outputter, "name", Bytes.toString(descriptor.getName()));
- outputter.startTag("columnfamilies");
- for (HColumnDescriptor e: descriptor.getFamilies()) {
- outputter.startTag("columnfamily");
- doElement(outputter, "name", Bytes.toString(e.getName()));
- doElement(outputter, "compression", e.getCompression().toString());
- doElement(outputter, "bloomfilter",
- Boolean.toString(e.isBloomfilter()));
- doElement(outputter, "max-versions",
- Integer.toString(e.getMaxVersions()));
- doElement(outputter, "maximum-cell-size",
- Integer.toString(e.getMaxValueLength()));
- outputter.endTag();
- }
- outputter.endTag();
- outputter.endTag();
- outputter.endDocument();
- outputter.getWriter().close();
- break;
- case PLAIN:
- setResponseHeader(response, 200, ContentType.PLAIN.toString());
- PrintWriter out = response.getWriter();
- out.print(descriptor.toString());
- out.close();
- break;
- case MIME:
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: " +
- request.getHeader(CONTENT_TYPE));
- }
- }
- }
-
- private void putTable(HttpServletRequest request,
- HttpServletResponse response, String[] pathSegments)
- throws IOException, ServletException {
- switch(ContentType.getContentType(request.getHeader(CONTENT_TYPE))) {
- case XML:
- putTableXml(request, response, pathSegments);
- break;
- case MIME:
- doNotAcceptable(response, "Don't support multipart/related yet...");
- break;
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: " +
- request.getHeader(CONTENT_TYPE));
- }
- }
-
- private void updateTable(HttpServletRequest request,
- HttpServletResponse response, String[] pathSegments)
- throws IOException, ServletException {
- switch(ContentType.getContentType(request.getHeader(CONTENT_TYPE))) {
- case XML:
- updateTableXml(request, response, pathSegments);
- break;
- case MIME:
- doNotAcceptable(response, "Don't support multipart/related yet...");
- break;
- default:
- doNotAcceptable(response, "Unsupported Accept Header Content: " +
- request.getHeader(CONTENT_TYPE));
- }
- }
-
- private void deleteTable(HttpServletRequest request,
- HttpServletResponse response, String[] pathSegments)
- throws ServletException {
- try {
- String tableName = pathSegments[0];
- String[] column_params = request.getParameterValues(COLUMN);
- if (column_params != null && column_params.length > 0) {
- for (String column : column_params) {
- admin.deleteColumn(tableName, makeColumnName(column));
- }
- } else {
- admin.deleteTable(tableName);
- }
- response.setStatus(202);
- } catch (Exception e) {
- throw new ServletException(e);
- }
- }
-
- private void putTableXml(HttpServletRequest
- request, HttpServletResponse response, String[] pathSegments)
- throws IOException, ServletException {
- DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
- .newInstance();
- // ignore all comments inside the xml file
- docBuilderFactory.setIgnoringComments(true);
-
- DocumentBuilder builder = null;
- Document doc = null;
-
- try {
- builder = docBuilderFactory.newDocumentBuilder();
- doc = builder.parse(request.getInputStream());
- } catch (javax.xml.parsers.ParserConfigurationException e) {
- throw new ServletException(e);
- } catch (org.xml.sax.SAXException e) {
- throw new ServletException(e);
- }
-
- try {
- Node name_node = doc.getElementsByTagName("name").item(0);
- String table_name = name_node.getFirstChild().getNodeValue();
-
- HTableDescriptor htd = new HTableDescriptor(table_name);
- NodeList columnfamily_nodes = doc.getElementsByTagName("columnfamily");
- for (int i = 0; i < columnfamily_nodes.getLength(); i++) {
- Element columnfamily = (Element)columnfamily_nodes.item(i);
- htd.addFamily(putColumnFamilyXml(columnfamily));
- }
- admin.createTable(htd);
- } catch (Exception e) {
- throw new ServletException(e);
- }
- }
-
- private void updateTableXml(HttpServletRequest request,
- HttpServletResponse response, String[] pathSegments) throws IOException,
- ServletException {
- DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
- .newInstance();
- // ignore all comments inside the xml file
- docBuilderFactory.setIgnoringComments(true);
-
- DocumentBuilder builder = null;
- Document doc = null;
-
- try {
- builder = docBuilderFactory.newDocumentBuilder();
- doc = builder.parse(request.getInputStream());
- } catch (javax.xml.parsers.ParserConfigurationException e) {
- throw new ServletException(e);
- } catch (org.xml.sax.SAXException e) {
- throw new ServletException(e);
- }
-
- try {
- String tableName = pathSegments[0];
- HTableDescriptor htd = admin.getTableDescriptor(tableName);
-
- NodeList columnfamily_nodes = doc.getElementsByTagName("columnfamily");
-
- for (int i = 0; i < columnfamily_nodes.getLength(); i++) {
- Element columnfamily = (Element) columnfamily_nodes.item(i);
- HColumnDescriptor hcd = putColumnFamilyXml(columnfamily, htd);
- if (htd.hasFamily(Bytes.toBytes(hcd.getNameAsString()))) {
- admin.modifyColumn(tableName, hcd.getNameAsString(), hcd);
- } else {
- admin.addColumn(tableName, hcd);
- }
- }
- } catch (Exception e) {
- throw new ServletException(e);
- }
- }
-
- private HColumnDescriptor putColumnFamilyXml(Element columnfamily) {
- return putColumnFamilyXml(columnfamily, null);
- }
-
- private HColumnDescriptor putColumnFamilyXml(Element columnfamily, HTableDescriptor currentTDesp) {
- Node name_node = columnfamily.getElementsByTagName("name").item(0);
- String colname = makeColumnName(name_node.getFirstChild().getNodeValue());
-
- int max_versions = HColumnDescriptor.DEFAULT_VERSIONS;
- CompressionType compression = HColumnDescriptor.DEFAULT_COMPRESSION;
- boolean in_memory = HColumnDescriptor.DEFAULT_IN_MEMORY;
- boolean block_cache = HColumnDescriptor.DEFAULT_BLOCKCACHE;
- int max_cell_size = HColumnDescriptor.DEFAULT_LENGTH;
- int ttl = HColumnDescriptor.DEFAULT_TTL;
- boolean bloomfilter = HColumnDescriptor.DEFAULT_BLOOMFILTER;
-
- if (currentTDesp != null) {
- HColumnDescriptor currentCDesp = currentTDesp.getFamily(Bytes.toBytes(colname));
- if (currentCDesp != null) {
- max_versions = currentCDesp.getMaxVersions();
- compression = currentCDesp.getCompression();
- in_memory = currentCDesp.isInMemory();
- block_cache = currentCDesp.isBlockCacheEnabled();
- max_cell_size = currentCDesp.getMaxValueLength();
- ttl = currentCDesp.getTimeToLive();
- bloomfilter = currentCDesp.isBloomfilter();
- }
- }
-
- NodeList max_versions_list = columnfamily.getElementsByTagName("max-versions");
- if (max_versions_list.getLength() > 0) {
- max_versions = Integer.parseInt(max_versions_list.item(0).getFirstChild().getNodeValue());
- }
-
- NodeList compression_list = columnfamily.getElementsByTagName("compression");
- if (compression_list.getLength() > 0) {
- compression = CompressionType.valueOf(compression_list.item(0).getFirstChild().getNodeValue());
- }
-
- NodeList in_memory_list = columnfamily.getElementsByTagName("in-memory");
- if (in_memory_list.getLength() > 0) {
- in_memory = Boolean.valueOf(in_memory_list.item(0).getFirstChild().getNodeValue());
- }
-
- NodeList block_cache_list = columnfamily.getElementsByTagName("block-cache");
- if (block_cache_list.getLength() > 0) {
- block_cache = Boolean.valueOf(block_cache_list.item(0).getFirstChild().getNodeValue());
- }
-
- NodeList max_cell_size_list = columnfamily.getElementsByTagName("max-cell-size");
- if (max_cell_size_list.getLength() > 0) {
- max_cell_size = Integer.valueOf(max_cell_size_list.item(0).getFirstChild().getNodeValue());
- }
-
- NodeList ttl_list = columnfamily.getElementsByTagName("time-to-live");
- if (ttl_list.getLength() > 0) {
- ttl = Integer.valueOf(ttl_list.item(0).getFirstChild().getNodeValue());
- }
-
- NodeList bloomfilter_list = columnfamily.getElementsByTagName("bloomfilter");
- if (bloomfilter_list.getLength() > 0) {
- bloomfilter = Boolean.valueOf(bloomfilter_list.item(0).getFirstChild().getNodeValue());
- }
-
- HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toBytes(colname), max_versions,
- compression, in_memory, block_cache, max_cell_size, ttl, bloomfilter);
-
- NodeList metadataList = columnfamily.getElementsByTagName("metadata");
- for (int i = 0; i < metadataList.getLength(); i++) {
- Element metadataColumn = (Element)metadataList.item(i);
- // extract the name and value children
- Node mname_node = metadataColumn.getElementsByTagName("name").item(0);
- String mname = mname_node.getFirstChild().getNodeValue();
- Node mvalue_node = metadataColumn.getElementsByTagName("value").item(0);
- String mvalue = mvalue_node.getFirstChild().getNodeValue();
- hcd.setValue(mname, mvalue);
- }
-
- return hcd;
- }
-}