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