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 String tableName;
66
67
68
69
70
71
72 public SchemaResource(String table) throws IOException {
73 super();
74 this.tableName = table;
75 }
76
77 private HTableDescriptor getTableSchema() throws IOException,
78 TableNotFoundException {
79 HTablePool pool = servlet.getTablePool();
80 HTableInterface table = pool.getTable(tableName);
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 try {
111 HTableDescriptor htd = new HTableDescriptor(name);
112 for (Map.Entry<QName,Object> e: model.getAny().entrySet()) {
113 htd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
114 }
115 for (ColumnSchemaModel family: model.getColumns()) {
116 HColumnDescriptor hcd = new HColumnDescriptor(family.getName());
117 for (Map.Entry<QName,Object> e: family.getAny().entrySet()) {
118 hcd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
119 }
120 htd.addFamily(hcd);
121 }
122 if (admin.tableExists(name)) {
123 admin.disableTable(name);
124 admin.modifyTable(name, htd);
125 admin.enableTable(name);
126 } else try {
127 admin.createTable(htd);
128 } catch (TableExistsException e) {
129
130 throw new WebApplicationException(e, Response.Status.NOT_MODIFIED);
131 }
132 return Response.created(uriInfo.getAbsolutePath()).build();
133 } catch (IOException e) {
134 throw new WebApplicationException(e,
135 Response.Status.SERVICE_UNAVAILABLE);
136 }
137 }
138
139 private Response update(final byte[] name, final TableSchemaModel model,
140 final UriInfo uriInfo, final HBaseAdmin admin) {
141 try {
142 HTableDescriptor htd = admin.getTableDescriptor(name);
143 admin.disableTable(name);
144 try {
145 for (ColumnSchemaModel family: model.getColumns()) {
146 HColumnDescriptor hcd = new HColumnDescriptor(family.getName());
147 for (Map.Entry<QName,Object> e: family.getAny().entrySet()) {
148 hcd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
149 }
150 if (htd.hasFamily(hcd.getName())) {
151 admin.modifyColumn(name, hcd.getName(), hcd);
152 } else {
153 admin.addColumn(model.getName(), hcd);
154 }
155 }
156 } catch (IOException e) {
157 throw new WebApplicationException(e,
158 Response.Status.INTERNAL_SERVER_ERROR);
159 } finally {
160 admin.enableTable(tableName);
161 }
162 return Response.ok().build();
163 } catch (IOException e) {
164 throw new WebApplicationException(e,
165 Response.Status.SERVICE_UNAVAILABLE);
166 }
167 }
168
169 private Response update(final TableSchemaModel model, final boolean replace,
170 final UriInfo uriInfo) {
171 try {
172 servlet.invalidateMaxAge(tableName);
173 byte[] name = Bytes.toBytes(tableName);
174 HBaseAdmin admin = new HBaseAdmin(servlet.getConfiguration());
175 if (replace || !admin.tableExists(name)) {
176 return replace(name, model, uriInfo, admin);
177 } else {
178 return update(name, model, uriInfo, admin);
179 }
180 } catch (IOException e) {
181 throw new WebApplicationException(e,
182 Response.Status.SERVICE_UNAVAILABLE);
183 }
184 }
185
186 @PUT
187 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF})
188 public Response put(final TableSchemaModel model,
189 final @Context UriInfo uriInfo) {
190 if (LOG.isDebugEnabled()) {
191 LOG.debug("PUT " + uriInfo.getAbsolutePath());
192 }
193 servlet.getMetrics().incrementRequests(1);
194 return update(model, true, uriInfo);
195 }
196
197 @POST
198 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF})
199 public Response post(final TableSchemaModel model,
200 final @Context UriInfo uriInfo) {
201 if (LOG.isDebugEnabled()) {
202 LOG.debug("PUT " + uriInfo.getAbsolutePath());
203 }
204 servlet.getMetrics().incrementRequests(1);
205 return update(model, false, uriInfo);
206 }
207
208 @DELETE
209 public Response delete(final @Context UriInfo uriInfo) {
210 if (LOG.isDebugEnabled()) {
211 LOG.debug("DELETE " + uriInfo.getAbsolutePath());
212 }
213 servlet.getMetrics().incrementRequests(1);
214 try {
215 HBaseAdmin admin = new HBaseAdmin(servlet.getConfiguration());
216 boolean success = false;
217 for (int i = 0; i < 10; i++) try {
218 admin.disableTable(tableName);
219 success = true;
220 break;
221 } catch (IOException e) {
222 }
223 if (!success) {
224 throw new IOException("could not disable table");
225 }
226 admin.deleteTable(tableName);
227 return Response.ok().build();
228 } catch (TableNotFoundException e) {
229 throw new WebApplicationException(Response.Status.NOT_FOUND);
230 } catch (IOException e) {
231 throw new WebApplicationException(e,
232 Response.Status.SERVICE_UNAVAILABLE);
233 }
234 }
235 }