View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.rest;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.IOException;
24  import java.net.InetSocketAddress;
25  import java.util.Iterator;
26  import java.util.Map;
27  
28  import javax.xml.bind.JAXBContext;
29  import javax.xml.bind.JAXBException;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.hbase.*;
34  import org.apache.hadoop.hbase.client.HBaseAdmin;
35  import org.apache.hadoop.hbase.client.HTable;
36  import org.apache.hadoop.hbase.client.Put;
37  import org.apache.hadoop.hbase.client.Durability;
38  import org.apache.hadoop.hbase.rest.client.Client;
39  import org.apache.hadoop.hbase.rest.client.Cluster;
40  import org.apache.hadoop.hbase.rest.client.Response;
41  import org.apache.hadoop.hbase.rest.model.TableModel;
42  import org.apache.hadoop.hbase.rest.model.TableInfoModel;
43  import org.apache.hadoop.hbase.rest.model.TableListModel;
44  import org.apache.hadoop.hbase.rest.model.TableRegionModel;
45  import org.apache.hadoop.hbase.testclassification.MediumTests;
46  import org.apache.hadoop.hbase.util.Bytes;
47  import org.apache.hadoop.util.StringUtils;
48  
49  import static org.junit.Assert.*;
50  
51  import org.junit.AfterClass;
52  import org.junit.BeforeClass;
53  import org.junit.Test;
54  import org.junit.experimental.categories.Category;
55  
56  @Category(MediumTests.class)
57  public class TestTableResource {
58    private static final Log LOG = LogFactory.getLog(TestTableResource.class);
59  
60    private static String TABLE = "TestTableResource";
61    private static String COLUMN_FAMILY = "test";
62    private static String COLUMN = COLUMN_FAMILY + ":qualifier";
63    private static Map<HRegionInfo, ServerName> regionMap;
64  
65    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
66    private static final HBaseRESTTestingUtility REST_TEST_UTIL = 
67      new HBaseRESTTestingUtility();
68    private static Client client;
69    private static JAXBContext context;
70  
71    @BeforeClass
72    public static void setUpBeforeClass() throws Exception {
73      TEST_UTIL.startMiniCluster(3);
74      REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
75      client = new Client(new Cluster().add("localhost", 
76        REST_TEST_UTIL.getServletPort()));
77      context = JAXBContext.newInstance(
78          TableModel.class,
79          TableInfoModel.class,
80          TableListModel.class,
81          TableRegionModel.class);
82      HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
83      if (admin.tableExists(TABLE)) {
84        return;
85      }
86      HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TABLE));
87      htd.addFamily(new HColumnDescriptor(COLUMN_FAMILY));
88      admin.createTable(htd);
89      HTable table = new HTable(TEST_UTIL.getConfiguration(), TABLE);
90      byte[] k = new byte[3];
91      byte [][] famAndQf = KeyValue.parseColumn(Bytes.toBytes(COLUMN));
92      for (byte b1 = 'a'; b1 < 'z'; b1++) {
93        for (byte b2 = 'a'; b2 < 'z'; b2++) {
94          for (byte b3 = 'a'; b3 < 'z'; b3++) {
95            k[0] = b1;
96            k[1] = b2;
97            k[2] = b3;
98            Put put = new Put(k);
99            put.setDurability(Durability.SKIP_WAL);
100           put.add(famAndQf[0], famAndQf[1], k);
101           table.put(put);
102         }
103       }
104     }
105     table.flushCommits();
106     // get the initial layout (should just be one region)
107     Map<HRegionInfo, ServerName> m = table.getRegionLocations();
108     assertEquals(m.size(), 1);
109     // tell the master to split the table
110     admin.split(TABLE);
111     // give some time for the split to happen
112 
113     long timeout = System.currentTimeMillis() + (15 * 1000);
114     while (System.currentTimeMillis() < timeout && m.size()!=2){
115       try {
116         Thread.sleep(250);
117       } catch (InterruptedException e) {
118         LOG.warn(StringUtils.stringifyException(e));
119       }
120       // check again
121       m = table.getRegionLocations();
122     }
123 
124     // should have two regions now
125     assertEquals(m.size(), 2);
126     regionMap = m;
127     LOG.info("regions: " + regionMap);
128     table.close();
129   }
130 
131   @AfterClass
132   public static void tearDownAfterClass() throws Exception {
133     REST_TEST_UTIL.shutdownServletContainer();
134     TEST_UTIL.shutdownMiniCluster();
135   }
136 
137   private static void checkTableList(TableListModel model) {
138     boolean found = false;
139     Iterator<TableModel> tables = model.getTables().iterator();
140     assertTrue(tables.hasNext());
141     while (tables.hasNext()) {
142       TableModel table = tables.next();
143       if (table.getName().equals(TABLE)) {
144         found = true;
145         break;
146       }
147     }
148     assertTrue(found);
149   }
150 
151   void checkTableInfo(TableInfoModel model) {
152     assertEquals(model.getName(), TABLE);
153     Iterator<TableRegionModel> regions = model.getRegions().iterator();
154     assertTrue(regions.hasNext());
155     while (regions.hasNext()) {
156       TableRegionModel region = regions.next();
157       boolean found = false;
158       for (Map.Entry<HRegionInfo, ServerName> e: regionMap.entrySet()) {
159         HRegionInfo hri = e.getKey();
160         String hriRegionName = hri.getRegionNameAsString();
161         String regionName = region.getName();
162         if (hriRegionName.equals(regionName)) {
163           found = true;
164           byte[] startKey = hri.getStartKey();
165           byte[] endKey = hri.getEndKey();
166           InetSocketAddress sa = new InetSocketAddress(e.getValue().getHostname(), e.getValue().getPort());
167           String location = sa.getHostName() + ":" +
168             Integer.valueOf(sa.getPort());
169           assertEquals(hri.getRegionId(), region.getId());
170           assertTrue(Bytes.equals(startKey, region.getStartKey()));
171           assertTrue(Bytes.equals(endKey, region.getEndKey()));
172           assertEquals(location, region.getLocation());
173           break;
174         }
175       }
176       assertTrue(found);
177     }
178   }
179 
180   @Test
181   public void testTableListText() throws IOException {
182     Response response = client.get("/", Constants.MIMETYPE_TEXT);
183     assertEquals(response.getCode(), 200);
184     assertEquals(Constants.MIMETYPE_TEXT, response.getHeader("content-type"));
185   }
186 
187   @Test
188   public void testTableListXML() throws IOException, JAXBException {
189     Response response = client.get("/", Constants.MIMETYPE_XML);
190     assertEquals(response.getCode(), 200);
191     assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
192     TableListModel model = (TableListModel)
193       context.createUnmarshaller()
194         .unmarshal(new ByteArrayInputStream(response.getBody()));
195     checkTableList(model);
196   }
197 
198   @Test
199   public void testTableListJSON() throws IOException {
200     Response response = client.get("/", Constants.MIMETYPE_JSON);
201     assertEquals(response.getCode(), 200);
202     assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
203   }
204 
205   @Test
206   public void testTableListPB() throws IOException, JAXBException {
207     Response response = client.get("/", Constants.MIMETYPE_PROTOBUF);
208     assertEquals(response.getCode(), 200);
209     assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
210     TableListModel model = new TableListModel();
211     model.getObjectFromMessage(response.getBody());
212     checkTableList(model);
213     response = client.get("/", Constants.MIMETYPE_PROTOBUF_IETF);
214     assertEquals(response.getCode(), 200);
215     assertEquals(Constants.MIMETYPE_PROTOBUF_IETF, response.getHeader("content-type"));
216     model = new TableListModel();
217     model.getObjectFromMessage(response.getBody());
218     checkTableList(model);
219   }
220 
221   @Test
222   public void testTableInfoText() throws IOException {
223     Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_TEXT);
224     assertEquals(response.getCode(), 200);
225     assertEquals(Constants.MIMETYPE_TEXT, response.getHeader("content-type"));
226   }
227 
228   @Test
229   public void testTableInfoXML() throws IOException, JAXBException {
230     Response response = client.get("/" + TABLE + "/regions",  Constants.MIMETYPE_XML);
231     assertEquals(response.getCode(), 200);
232     assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
233     TableInfoModel model = (TableInfoModel)
234       context.createUnmarshaller()
235         .unmarshal(new ByteArrayInputStream(response.getBody()));
236     checkTableInfo(model);
237   }
238 
239   @Test
240   public void testTableInfoJSON() throws IOException {
241     Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_JSON);
242     assertEquals(response.getCode(), 200);
243     assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
244   }
245 
246   @Test
247   public void testTableInfoPB() throws IOException, JAXBException {
248     Response response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_PROTOBUF);
249     assertEquals(response.getCode(), 200);
250     assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
251     TableInfoModel model = new TableInfoModel();
252     model.getObjectFromMessage(response.getBody());
253     checkTableInfo(model);
254     response = client.get("/" + TABLE + "/regions", Constants.MIMETYPE_PROTOBUF_IETF);
255     assertEquals(response.getCode(), 200);
256     assertEquals(Constants.MIMETYPE_PROTOBUF_IETF, response.getHeader("content-type"));
257     model = new TableInfoModel();
258     model.getObjectFromMessage(response.getBody());
259     checkTableInfo(model);
260   }
261 
262 }
263