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