1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.rest;
22
23 import java.io.IOException;
24 import java.util.Map;
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.WebApplicationException;
33 import javax.ws.rs.core.CacheControl;
34 import javax.ws.rs.core.Context;
35 import javax.ws.rs.core.Response;
36 import javax.ws.rs.core.UriInfo;
37 import javax.ws.rs.core.Response.ResponseBuilder;
38
39 import javax.xml.namespace.QName;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43
44 import org.apache.hadoop.hbase.HColumnDescriptor;
45 import org.apache.hadoop.hbase.HTableDescriptor;
46 import org.apache.hadoop.hbase.TableExistsException;
47 import org.apache.hadoop.hbase.TableNotFoundException;
48 import org.apache.hadoop.hbase.client.HBaseAdmin;
49 import org.apache.hadoop.hbase.client.HTableInterface;
50 import org.apache.hadoop.hbase.client.HTablePool;
51 import org.apache.hadoop.hbase.rest.model.ColumnSchemaModel;
52 import org.apache.hadoop.hbase.rest.model.TableSchemaModel;
53 import org.apache.hadoop.hbase.util.Bytes;
54
55 public class SchemaResource extends ResourceBase {
56 private static final Log LOG = LogFactory.getLog(SchemaResource.class);
57
58 static CacheControl cacheControl;
59 static {
60 cacheControl = new CacheControl();
61 cacheControl.setNoCache(true);
62 cacheControl.setNoTransform(false);
63 }
64
65 TableResource tableResource;
66
67
68
69
70
71
72 public SchemaResource(TableResource tableResource) throws IOException {
73 super();
74 this.tableResource = tableResource;
75 }
76
77 private HTableDescriptor getTableSchema() throws IOException,
78 TableNotFoundException {
79 HTablePool pool = servlet.getTablePool();
80 HTableInterface table = pool.getTable(tableResource.getName());
81 try {
82 return table.getTableDescriptor();
83 } finally {
84 pool.putTable(table);
85 }
86 }
87
88 @GET
89 @Produces({MIMETYPE_TEXT, MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF})
90 public Response get(final @Context UriInfo uriInfo) {
91 if (LOG.isDebugEnabled()) {
92 LOG.debug("GET " + uriInfo.getAbsolutePath());
93 }
94 servlet.getMetrics().incrementRequests(1);
95 try {
96 ResponseBuilder response =
97 Response.ok(new TableSchemaModel(getTableSchema()));
98 response.cacheControl(cacheControl);
99 return response.build();
100 } catch (TableNotFoundException e) {
101 throw new WebApplicationException(Response.Status.NOT_FOUND);
102 } catch (IOException e) {
103 throw new WebApplicationException(e,
104 Response.Status.SERVICE_UNAVAILABLE);
105 }
106 }
107
108 private Response replace(final byte[] name, final TableSchemaModel model,
109 final UriInfo uriInfo, final HBaseAdmin admin) {
110 if (servlet.isReadOnly()) {
111 throw new WebApplicationException(Response.Status.FORBIDDEN);
112 }
113 try {
114 HTableDescriptor htd = new HTableDescriptor(name);
115 for (Map.Entry<QName,Object> e: model.getAny().entrySet()) {
116 htd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
117 }
118 for (ColumnSchemaModel family: model.getColumns()) {
119 HColumnDescriptor hcd = new HColumnDescriptor(family.getName());
120 for (Map.Entry<QName,Object> e: family.getAny().entrySet()) {
121 hcd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
122 }
123 htd.addFamily(hcd);
124 }
125 if (admin.tableExists(name)) {
126 admin.disableTable(name);
127 admin.modifyTable(name, htd);
128 admin.enableTable(name);
129 } else try {
130 admin.createTable(htd);
131 } catch (TableExistsException e) {
132
133 throw new WebApplicationException(e, Response.Status.NOT_MODIFIED);
134 }
135 return Response.created(uriInfo.getAbsolutePath()).build();
136 } catch (IOException e) {
137 throw new WebApplicationException(e,
138 Response.Status.SERVICE_UNAVAILABLE);
139 }
140 }
141
142 private Response update(final byte[] name, final TableSchemaModel model,
143 final UriInfo uriInfo, final HBaseAdmin admin) {
144 if (servlet.isReadOnly()) {
145 throw new WebApplicationException(Response.Status.FORBIDDEN);
146 }
147 try {
148 HTableDescriptor htd = admin.getTableDescriptor(name);
149 admin.disableTable(name);
150 try {
151 for (ColumnSchemaModel family: model.getColumns()) {
152 HColumnDescriptor hcd = new HColumnDescriptor(family.getName());
153 for (Map.Entry<QName,Object> e: family.getAny().entrySet()) {
154 hcd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
155 }
156 if (htd.hasFamily(hcd.getName())) {
157 admin.modifyColumn(name, hcd);
158 } else {
159 admin.addColumn(name, hcd);
160 }
161 }
162 } catch (IOException e) {
163 throw new WebApplicationException(e,
164 Response.Status.INTERNAL_SERVER_ERROR);
165 } finally {
166 admin.enableTable(tableResource.getName());
167 }
168 return Response.ok().build();
169 } catch (IOException e) {
170 throw new WebApplicationException(e,
171 Response.Status.SERVICE_UNAVAILABLE);
172 }
173 }
174
175 private Response update(final TableSchemaModel model, final boolean replace,
176 final UriInfo uriInfo) {
177 try {
178 byte[] name = Bytes.toBytes(tableResource.getName());
179 HBaseAdmin admin = new HBaseAdmin(servlet.getConfiguration());
180 if (replace || !admin.tableExists(name)) {
181 return replace(name, model, uriInfo, admin);
182 } else {
183 return update(name, model, uriInfo, admin);
184 }
185 } catch (IOException e) {
186 throw new WebApplicationException(e,
187 Response.Status.SERVICE_UNAVAILABLE);
188 }
189 }
190
191 @PUT
192 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF})
193 public Response put(final TableSchemaModel model,
194 final @Context UriInfo uriInfo) {
195 if (LOG.isDebugEnabled()) {
196 LOG.debug("PUT " + uriInfo.getAbsolutePath());
197 }
198 servlet.getMetrics().incrementRequests(1);
199 return update(model, true, uriInfo);
200 }
201
202 @POST
203 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF})
204 public Response post(final TableSchemaModel model,
205 final @Context UriInfo uriInfo) {
206 if (LOG.isDebugEnabled()) {
207 LOG.debug("PUT " + uriInfo.getAbsolutePath());
208 }
209 servlet.getMetrics().incrementRequests(1);
210 return update(model, false, uriInfo);
211 }
212
213 @DELETE
214 public Response delete(final @Context UriInfo uriInfo) {
215 if (LOG.isDebugEnabled()) {
216 LOG.debug("DELETE " + uriInfo.getAbsolutePath());
217 }
218 servlet.getMetrics().incrementRequests(1);
219 try {
220 HBaseAdmin admin = new HBaseAdmin(servlet.getConfiguration());
221 boolean success = false;
222 for (int i = 0; i < 10; i++) try {
223 admin.disableTable(tableResource.getName());
224 success = true;
225 break;
226 } catch (IOException e) {
227 }
228 if (!success) {
229 throw new IOException("could not disable table");
230 }
231 admin.deleteTable(tableResource.getName());
232 return Response.ok().build();
233 } catch (TableNotFoundException e) {
234 throw new WebApplicationException(Response.Status.NOT_FOUND);
235 } catch (IOException e) {
236 throw new WebApplicationException(e,
237 Response.Status.SERVICE_UNAVAILABLE);
238 }
239 }
240 }