001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client;
019
020import static org.apache.hadoop.hbase.TableName.META_TABLE_NAME;
021import static org.hamcrest.CoreMatchers.instanceOf;
022import static org.junit.Assert.assertEquals;
023import static org.junit.Assert.assertFalse;
024import static org.junit.Assert.assertThat;
025import static org.junit.Assert.assertTrue;
026import static org.junit.Assert.fail;
027
028import java.util.List;
029import java.util.concurrent.ExecutionException;
030import java.util.regex.Pattern;
031import org.apache.hadoop.hbase.AsyncMetaTableAccessor;
032import org.apache.hadoop.hbase.DoNotRetryIOException;
033import org.apache.hadoop.hbase.HBaseClassTestRule;
034import org.apache.hadoop.hbase.HRegionLocation;
035import org.apache.hadoop.hbase.TableName;
036import org.apache.hadoop.hbase.client.TableDescriptorBuilder.ModifyableTableDescriptor;
037import org.apache.hadoop.hbase.testclassification.ClientTests;
038import org.apache.hadoop.hbase.testclassification.LargeTests;
039import org.apache.hadoop.hbase.util.Bytes;
040import org.junit.ClassRule;
041import org.junit.Test;
042import org.junit.experimental.categories.Category;
043import org.junit.runner.RunWith;
044import org.junit.runners.Parameterized;
045
046/**
047 * Class to test asynchronous table admin operations.
048 * @see TestAsyncTableAdminApi2 This test and it used to be joined it was taking longer than our
049 * ten minute timeout so they were split.
050 */
051@RunWith(Parameterized.class)
052@Category({ LargeTests.class, ClientTests.class })
053public class TestAsyncTableAdminApi3 extends TestAsyncAdminBase {
054  @ClassRule
055  public static final HBaseClassTestRule CLASS_RULE =
056      HBaseClassTestRule.forClass(TestAsyncTableAdminApi3.class);
057
058  @Test
059  public void testTableExist() throws Exception {
060    boolean exist;
061    exist = admin.tableExists(tableName).get();
062    assertFalse(exist);
063    TEST_UTIL.createTable(tableName, FAMILY);
064    exist = admin.tableExists(tableName).get();
065    assertTrue(exist);
066    exist = admin.tableExists(TableName.META_TABLE_NAME).get();
067    assertTrue(exist);
068    // meta table already exists
069    exist = admin.tableExists(TableName.META_TABLE_NAME).get();
070    assertTrue(exist);
071  }
072
073  @Test
074  public void testListTables() throws Exception {
075    int numTables = admin.listTableDescriptors().get().size();
076    final TableName tableName1 = TableName.valueOf(tableName.getNameAsString() + "1");
077    final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "2");
078    final TableName tableName3 = TableName.valueOf(tableName.getNameAsString() + "3");
079    TableName[] tables = new TableName[] { tableName1, tableName2, tableName3 };
080    for (int i = 0; i < tables.length; i++) {
081      createTableWithDefaultConf(tables[i]);
082    }
083
084    List<TableDescriptor> tableDescs = admin.listTableDescriptors().get();
085    int size = tableDescs.size();
086    assertTrue(size >= tables.length);
087    for (int i = 0; i < tables.length && i < size; i++) {
088      boolean found = false;
089      for (int j = 0; j < size; j++) {
090        if (tableDescs.get(j).getTableName().equals(tables[i])) {
091          found = true;
092          break;
093        }
094      }
095      assertTrue("Not found: " + tables[i], found);
096    }
097
098    List<TableName> tableNames = admin.listTableNames().get();
099    size = tableNames.size();
100    assertTrue(size == (numTables + tables.length));
101    for (int i = 0; i < tables.length && i < size; i++) {
102      boolean found = false;
103      for (int j = 0; j < size; j++) {
104        if (tableNames.get(j).equals(tables[i])) {
105          found = true;
106          break;
107        }
108      }
109      assertTrue("Not found: " + tables[i], found);
110    }
111
112    for (int i = 0; i < tables.length; i++) {
113      admin.disableTable(tables[i]).join();
114      admin.deleteTable(tables[i]).join();
115    }
116
117    tableDescs = admin.listTableDescriptors(true).get();
118    assertTrue("Not found system tables", tableDescs.size() > 0);
119    tableNames = admin.listTableNames(true).get();
120    assertTrue("Not found system tables", tableNames.size() > 0);
121  }
122
123  @Test
124  public void testGetTableDescriptor() throws Exception {
125    byte[][] families = { FAMILY, FAMILY_0, FAMILY_1 };
126    TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName);
127    for (byte[] family : families) {
128      builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(family));
129    }
130    TableDescriptor desc = builder.build();
131    admin.createTable(desc).join();
132    ModifyableTableDescriptor modifyableDesc = ((ModifyableTableDescriptor) desc);
133    TableDescriptor confirmedHtd = admin.getDescriptor(tableName).get();
134    assertEquals(0, modifyableDesc.compareTo((ModifyableTableDescriptor) confirmedHtd));
135  }
136
137  @Test
138  public void testDisableAndEnableTable() throws Exception {
139    createTableWithDefaultConf(tableName);
140    AsyncTable<?> table = ASYNC_CONN.getTable(tableName);
141    final byte[] row = Bytes.toBytes("row");
142    final byte[] qualifier = Bytes.toBytes("qualifier");
143    final byte[] value = Bytes.toBytes("value");
144    Put put = new Put(row);
145    put.addColumn(FAMILY, qualifier, value);
146    table.put(put).join();
147    Get get = new Get(row);
148    get.addColumn(FAMILY, qualifier);
149    table.get(get).get();
150
151    this.admin.disableTable(tableName).join();
152    assertTrue("Table must be disabled.", TEST_UTIL.getHBaseCluster().getMaster()
153        .getTableStateManager().isTableState(tableName, TableState.State.DISABLED));
154    assertEquals(TableState.State.DISABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName));
155
156    // Test that table is disabled
157    get = new Get(row);
158    get.addColumn(FAMILY, qualifier);
159    boolean ok = false;
160    try {
161      table.get(get).get();
162    } catch (ExecutionException e) {
163      ok = true;
164    }
165    ok = false;
166    // verify that scan encounters correct exception
167    try {
168      table.scanAll(new Scan()).get();
169    } catch (ExecutionException e) {
170      ok = true;
171    }
172    assertTrue(ok);
173    this.admin.enableTable(tableName).join();
174    assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster().getMaster()
175        .getTableStateManager().isTableState(tableName, TableState.State.ENABLED));
176    assertEquals(TableState.State.ENABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName));
177
178    // Test that table is enabled
179    try {
180      table.get(get).get();
181    } catch (Exception e) {
182      ok = false;
183    }
184    assertTrue(ok);
185    // meta table can not be disabled.
186    try {
187      admin.disableTable(TableName.META_TABLE_NAME).get();
188      fail("meta table can not be disabled");
189    } catch (ExecutionException e) {
190      Throwable cause = e.getCause();
191      assertThat(cause, instanceOf(DoNotRetryIOException.class));
192    }
193  }
194
195  @Test
196  public void testDisableAndEnableTables() throws Exception {
197    final TableName tableName1 = TableName.valueOf(tableName.getNameAsString() + "1");
198    final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "2");
199    createTableWithDefaultConf(tableName1);
200    createTableWithDefaultConf(tableName2);
201    AsyncTable<?> table1 = ASYNC_CONN.getTable(tableName1);
202    AsyncTable<?> table2 = ASYNC_CONN.getTable(tableName1);
203
204    final byte[] row = Bytes.toBytes("row");
205    final byte[] qualifier = Bytes.toBytes("qualifier");
206    final byte[] value = Bytes.toBytes("value");
207    Put put = new Put(row);
208    put.addColumn(FAMILY, qualifier, value);
209    table1.put(put).join();
210    table2.put(put).join();
211    Get get = new Get(row);
212    get.addColumn(FAMILY, qualifier);
213    table1.get(get).get();
214    table2.get(get).get();
215
216    admin.listTableNames(Pattern.compile(tableName.getNameAsString() + ".*"), false).get()
217        .forEach(t -> admin.disableTable(t).join());
218
219    // Test that tables are disabled
220    get = new Get(row);
221    get.addColumn(FAMILY, qualifier);
222    boolean ok = false;
223    try {
224      table1.get(get).get();
225    } catch (ExecutionException e) {
226      ok = true;
227    }
228    assertTrue(ok);
229
230    ok = false;
231    try {
232      table2.get(get).get();
233    } catch (ExecutionException e) {
234      ok = true;
235    }
236    assertTrue(ok);
237    assertEquals(TableState.State.DISABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName1));
238    assertEquals(TableState.State.DISABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName2));
239
240    admin.listTableNames(Pattern.compile(tableName.getNameAsString() + ".*"), false).get()
241        .forEach(t -> admin.enableTable(t).join());
242
243    // Test that tables are enabled
244    try {
245      table1.get(get).get();
246    } catch (Exception e) {
247      ok = false;
248    }
249    try {
250      table2.get(get).get();
251    } catch (Exception e) {
252      ok = false;
253    }
254    assertTrue(ok);
255    assertEquals(TableState.State.ENABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName1));
256    assertEquals(TableState.State.ENABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName2));
257  }
258
259  @Test
260  public void testEnableTableRetainAssignment() throws Exception {
261    byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, new byte[] { 3, 3, 3 },
262      new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 }, new byte[] { 6, 6, 6 },
263      new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 }, new byte[] { 9, 9, 9 } };
264    int expectedRegions = splitKeys.length + 1;
265    createTableWithDefaultConf(tableName, splitKeys);
266
267    AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME);
268    List<HRegionLocation> regions = AsyncMetaTableAccessor
269      .getTableHRegionLocations(metaTable, tableName).get();
270    assertEquals(
271      "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(),
272      expectedRegions, regions.size());
273
274    // Disable table.
275    admin.disableTable(tableName).join();
276    // Enable table, use retain assignment to assign regions.
277    admin.enableTable(tableName).join();
278
279    List<HRegionLocation> regions2 = AsyncMetaTableAccessor
280      .getTableHRegionLocations(metaTable, tableName).get();
281    // Check the assignment.
282    assertEquals(regions.size(), regions2.size());
283    assertTrue(regions2.containsAll(regions));
284  }
285
286  @Test
287  public void testIsTableEnabledAndDisabled() throws Exception {
288    createTableWithDefaultConf(tableName);
289    assertTrue(admin.isTableEnabled(tableName).get());
290    assertFalse(admin.isTableDisabled(tableName).get());
291    admin.disableTable(tableName).join();
292    assertFalse(admin.isTableEnabled(tableName).get());
293    assertTrue(admin.isTableDisabled(tableName).get());
294
295    // meta table is always enabled
296    assertTrue(admin.isTableEnabled(TableName.META_TABLE_NAME).get());
297    assertFalse(admin.isTableDisabled(TableName.META_TABLE_NAME).get());
298  }
299
300  @Test
301  public void testIsTableAvailable() throws Exception {
302    createTableWithDefaultConf(tableName);
303    TEST_UTIL.waitTableAvailable(tableName);
304    assertTrue(admin.isTableAvailable(tableName).get());
305    assertTrue(admin.isTableAvailable(TableName.META_TABLE_NAME).get());
306  }
307}