HBASE-26921 Rewrite the counting cells part in TestMultiVersions (#4316)
[hbase.git] / hbase-rest / src / main / java / org / apache / hadoop / hbase / rest / SchemaResource.java
blob0cdc2867f3513226c039a047a6a842b314e25ee1
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org.apache.hadoop.hbase.rest;
20 import java.io.IOException;
21 import java.util.Map;
22 import javax.xml.namespace.QName;
23 import org.apache.hadoop.hbase.TableExistsException;
24 import org.apache.hadoop.hbase.TableName;
25 import org.apache.hadoop.hbase.TableNotEnabledException;
26 import org.apache.hadoop.hbase.TableNotFoundException;
27 import org.apache.hadoop.hbase.client.Admin;
28 import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
29 import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
30 import org.apache.hadoop.hbase.client.Table;
31 import org.apache.hadoop.hbase.client.TableDescriptor;
32 import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
33 import org.apache.hadoop.hbase.rest.model.ColumnSchemaModel;
34 import org.apache.hadoop.hbase.rest.model.TableSchemaModel;
35 import org.apache.hadoop.hbase.util.Bytes;
36 import org.apache.yetus.audience.InterfaceAudience;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 import org.apache.hbase.thirdparty.javax.ws.rs.Consumes;
41 import org.apache.hbase.thirdparty.javax.ws.rs.DELETE;
42 import org.apache.hbase.thirdparty.javax.ws.rs.GET;
43 import org.apache.hbase.thirdparty.javax.ws.rs.POST;
44 import org.apache.hbase.thirdparty.javax.ws.rs.PUT;
45 import org.apache.hbase.thirdparty.javax.ws.rs.Produces;
46 import org.apache.hbase.thirdparty.javax.ws.rs.WebApplicationException;
47 import org.apache.hbase.thirdparty.javax.ws.rs.core.CacheControl;
48 import org.apache.hbase.thirdparty.javax.ws.rs.core.Context;
49 import org.apache.hbase.thirdparty.javax.ws.rs.core.Response;
50 import org.apache.hbase.thirdparty.javax.ws.rs.core.Response.ResponseBuilder;
51 import org.apache.hbase.thirdparty.javax.ws.rs.core.UriInfo;
53 @InterfaceAudience.Private
54 public class SchemaResource extends ResourceBase {
55 private static final Logger LOG = LoggerFactory.getLogger(SchemaResource.class);
57 static CacheControl cacheControl;
58 static {
59 cacheControl = new CacheControl();
60 cacheControl.setNoCache(true);
61 cacheControl.setNoTransform(false);
64 TableResource tableResource;
66 /**
67 * Constructor
69 public SchemaResource(TableResource tableResource) throws IOException {
70 super();
71 this.tableResource = tableResource;
74 private TableDescriptor getTableSchema() throws IOException, TableNotFoundException {
75 try (Table table = servlet.getTable(tableResource.getName())) {
76 return table.getDescriptor();
80 @GET
81 @Produces({MIMETYPE_TEXT, MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
82 MIMETYPE_PROTOBUF_IETF})
83 public Response get(final @Context UriInfo uriInfo) {
84 if (LOG.isTraceEnabled()) {
85 LOG.trace("GET " + uriInfo.getAbsolutePath());
87 servlet.getMetrics().incrementRequests(1);
88 try {
89 ResponseBuilder response =
90 Response.ok(new TableSchemaModel(getTableSchema()));
91 response.cacheControl(cacheControl);
92 servlet.getMetrics().incrementSucessfulGetRequests(1);
93 return response.build();
94 } catch (Exception e) {
95 servlet.getMetrics().incrementFailedGetRequests(1);
96 return processException(e);
100 private Response replace(final TableName name, final TableSchemaModel model,
101 final UriInfo uriInfo, final Admin admin) {
102 if (servlet.isReadOnly()) {
103 return Response.status(Response.Status.FORBIDDEN)
104 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
105 .build();
107 try {
108 TableDescriptorBuilder tableDescriptorBuilder =
109 TableDescriptorBuilder.newBuilder(name);
110 for (Map.Entry<QName, Object> e : model.getAny().entrySet()) {
111 tableDescriptorBuilder.setValue(e.getKey().getLocalPart(), e.getValue().toString());
113 for (ColumnSchemaModel family : model.getColumns()) {
114 ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder =
115 ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(family.getName()));
116 for (Map.Entry<QName, Object> e : family.getAny().entrySet()) {
117 columnFamilyDescriptorBuilder.setValue(e.getKey().getLocalPart(),
118 e.getValue().toString());
120 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptorBuilder.build());
122 TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
123 if (admin.tableExists(name)) {
124 admin.disableTable(name);
125 admin.modifyTable(tableDescriptor);
126 admin.enableTable(name);
127 servlet.getMetrics().incrementSucessfulPutRequests(1);
128 } else {
129 try {
130 admin.createTable(tableDescriptor);
131 servlet.getMetrics().incrementSucessfulPutRequests(1);
132 } catch (TableExistsException e) {
133 // race, someone else created a table with the same name
134 return Response.status(Response.Status.NOT_MODIFIED)
135 .type(MIMETYPE_TEXT).entity("Not modified" + CRLF)
136 .build();
139 return Response.created(uriInfo.getAbsolutePath()).build();
140 } catch (Exception e) {
141 LOG.info("Caught exception", e);
142 servlet.getMetrics().incrementFailedPutRequests(1);
143 return processException(e);
147 private Response update(final TableName name, final TableSchemaModel model,
148 final UriInfo uriInfo, final Admin admin) {
149 if (servlet.isReadOnly()) {
150 return Response.status(Response.Status.FORBIDDEN)
151 .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
152 .build();
154 try {
155 TableDescriptorBuilder tableDescriptorBuilder =
156 TableDescriptorBuilder.newBuilder(admin.getDescriptor(name));
157 admin.disableTable(name);
158 try {
159 for (ColumnSchemaModel family : model.getColumns()) {
160 ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder =
161 ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(family.getName()));
162 for (Map.Entry<QName, Object> e : family.getAny().entrySet()) {
163 columnFamilyDescriptorBuilder.setValue(e.getKey().getLocalPart(),
164 e.getValue().toString());
166 TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
167 ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorBuilder.build();
168 if (tableDescriptor.hasColumnFamily(columnFamilyDescriptor.getName())) {
169 admin.modifyColumnFamily(name, columnFamilyDescriptor);
170 } else {
171 admin.addColumnFamily(name, columnFamilyDescriptor);
174 } catch (IOException e) {
175 return Response.status(Response.Status.SERVICE_UNAVAILABLE)
176 .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
177 .build();
178 } finally {
179 admin.enableTable(TableName.valueOf(tableResource.getName()));
181 servlet.getMetrics().incrementSucessfulPutRequests(1);
182 return Response.ok().build();
183 } catch (Exception e) {
184 servlet.getMetrics().incrementFailedPutRequests(1);
185 return processException(e);
189 private Response update(final TableSchemaModel model, final boolean replace,
190 final UriInfo uriInfo) {
191 try {
192 TableName name = TableName.valueOf(tableResource.getName());
193 Admin admin = servlet.getAdmin();
194 if (replace || !admin.tableExists(name)) {
195 return replace(name, model, uriInfo, admin);
196 } else {
197 return update(name, model, uriInfo, admin);
199 } catch (Exception e) {
200 servlet.getMetrics().incrementFailedPutRequests(1);
201 // Avoid re-unwrapping the exception
202 if (e instanceof WebApplicationException) {
203 throw (WebApplicationException) e;
205 return processException(e);
209 @PUT
210 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
211 MIMETYPE_PROTOBUF_IETF})
212 public Response put(final TableSchemaModel model,
213 final @Context UriInfo uriInfo) {
214 if (LOG.isTraceEnabled()) {
215 LOG.trace("PUT " + uriInfo.getAbsolutePath());
217 servlet.getMetrics().incrementRequests(1);
218 return update(model, true, uriInfo);
221 @POST
222 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
223 MIMETYPE_PROTOBUF_IETF})
224 public Response post(final TableSchemaModel model,
225 final @Context UriInfo uriInfo) {
226 if (LOG.isTraceEnabled()) {
227 LOG.trace("PUT " + uriInfo.getAbsolutePath());
229 servlet.getMetrics().incrementRequests(1);
230 return update(model, false, uriInfo);
233 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="DE_MIGHT_IGNORE",
234 justification="Expected")
235 @DELETE
236 public Response delete(final @Context UriInfo uriInfo) {
237 if (LOG.isTraceEnabled()) {
238 LOG.trace("DELETE " + uriInfo.getAbsolutePath());
240 servlet.getMetrics().incrementRequests(1);
241 if (servlet.isReadOnly()) {
242 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT)
243 .entity("Forbidden" + CRLF).build();
245 try {
246 Admin admin = servlet.getAdmin();
247 try {
248 admin.disableTable(TableName.valueOf(tableResource.getName()));
249 } catch (TableNotEnabledException e) { /* this is what we want anyway */ }
250 admin.deleteTable(TableName.valueOf(tableResource.getName()));
251 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
252 return Response.ok().build();
253 } catch (Exception e) {
254 servlet.getMetrics().incrementFailedDeleteRequests(1);
255 return processException(e);