2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
.client
;
20 import static org
.junit
.Assert
.assertEquals
;
21 import static org
.junit
.Assert
.fail
;
23 import java
.io
.IOException
;
24 import java
.util
.Optional
;
25 import java
.util
.concurrent
.CountDownLatch
;
26 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
27 import org
.apache
.hadoop
.hbase
.HBaseTestingUtil
;
28 import org
.apache
.hadoop
.hbase
.HConstants
;
29 import org
.apache
.hadoop
.hbase
.MetaTableAccessor
;
30 import org
.apache
.hadoop
.hbase
.TableName
;
31 import org
.apache
.hadoop
.hbase
.coprocessor
.CoprocessorHost
;
32 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterCoprocessor
;
33 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterCoprocessorEnvironment
;
34 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterObserver
;
35 import org
.apache
.hadoop
.hbase
.coprocessor
.ObserverContext
;
36 import org
.apache
.hadoop
.hbase
.testclassification
.MasterTests
;
37 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
38 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
39 import org
.junit
.After
;
40 import org
.junit
.Before
;
41 import org
.junit
.ClassRule
;
42 import org
.junit
.Rule
;
43 import org
.junit
.Test
;
44 import org
.junit
.experimental
.categories
.Category
;
45 import org
.junit
.rules
.TestName
;
46 import org
.slf4j
.Logger
;
47 import org
.slf4j
.LoggerFactory
;
49 @Category({ MasterTests
.class, MediumTests
.class })
50 public class TestEnableTable
{
53 public static final HBaseClassTestRule CLASS_RULE
=
54 HBaseClassTestRule
.forClass(TestEnableTable
.class);
56 private static final HBaseTestingUtil TEST_UTIL
= new HBaseTestingUtil();
57 private static final Logger LOG
= LoggerFactory
.getLogger(TestEnableTable
.class);
58 private static final byte[] FAMILYNAME
= Bytes
.toBytes("fam");
61 public TestName name
= new TestName();
64 public void setUp() throws Exception
{
65 TEST_UTIL
.getConfiguration().set(CoprocessorHost
.MASTER_COPROCESSOR_CONF_KEY
,
66 MasterSyncObserver
.class.getName());
67 TEST_UTIL
.startMiniCluster(1);
71 public void tearDown() throws Exception
{
72 TEST_UTIL
.shutdownMiniCluster();
76 * We were only clearing rows that had a hregioninfo column in hbase:meta. Mangled rows that
77 * were missing the hregioninfo because of error were being left behind messing up any
78 * subsequent table made with the same name. HBASE-12980
81 public void testDeleteForSureClearsAllTableRowsFromMeta()
82 throws IOException
, InterruptedException
{
83 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
84 final Admin admin
= TEST_UTIL
.getAdmin();
85 TableDescriptor tableDescriptor
= TableDescriptorBuilder
.newBuilder(tableName
)
86 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(FAMILYNAME
)).build();
88 createTable(TEST_UTIL
, tableDescriptor
, HBaseTestingUtil
.KEYS_FOR_HBA_CREATE_TABLE
);
89 } catch (Exception e
) {
91 fail("Got an exception while creating " + tableName
);
93 // Now I have a nice table, mangle it by removing the HConstants.REGIONINFO_QUALIFIER_STR
94 // content from a few of the rows.
95 try (Table metaTable
= TEST_UTIL
.getConnection().getTable(TableName
.META_TABLE_NAME
)) {
96 try (ResultScanner scanner
= metaTable
.getScanner(
97 MetaTableAccessor
.getScanForTableName(TEST_UTIL
.getConfiguration(), tableName
))) {
98 for (Result result
: scanner
) {
99 // Just delete one row.
100 Delete d
= new Delete(result
.getRow());
101 d
.addColumn(HConstants
.CATALOG_FAMILY
, HConstants
.REGIONINFO_QUALIFIER
);
102 LOG
.info("Mangled: " + d
);
107 admin
.disableTable(tableName
);
108 TEST_UTIL
.waitTableDisabled(tableName
.getName());
109 // Rely on the coprocessor based latch to make the operation synchronous.
111 deleteTable(TEST_UTIL
, tableName
);
112 } catch (Exception e
) {
114 fail("Got an exception while deleting " + tableName
);
117 try (ResultScanner scanner
= metaTable
.getScanner(
118 MetaTableAccessor
.getScanForTableName(TEST_UTIL
.getConfiguration(), tableName
))) {
119 for (Result result
: scanner
) {
120 LOG
.info("Found when none expected: " + result
);
124 assertEquals(0, rowCount
);
128 public static class MasterSyncObserver
implements MasterCoprocessor
, MasterObserver
{
129 volatile CountDownLatch tableCreationLatch
= null;
130 volatile CountDownLatch tableDeletionLatch
= null;
133 public Optional
<MasterObserver
> getMasterObserver() {
134 return Optional
.of(this);
138 public void postCompletedCreateTableAction(
139 final ObserverContext
<MasterCoprocessorEnvironment
> ctx
,
140 final TableDescriptor desc
,
141 final RegionInfo
[] regions
) throws IOException
{
142 // the AccessController test, some times calls only and directly the
143 // postCompletedCreateTableAction()
144 if (tableCreationLatch
!= null) {
145 tableCreationLatch
.countDown();
150 public void postCompletedDeleteTableAction(
151 final ObserverContext
<MasterCoprocessorEnvironment
> ctx
,
152 final TableName tableName
)
154 // the AccessController test, some times calls only and directly the postDeleteTableHandler()
155 if (tableDeletionLatch
!= null) {
156 tableDeletionLatch
.countDown();
161 public static void createTable(HBaseTestingUtil testUtil
, TableDescriptor tableDescriptor
,
162 byte[][] splitKeys
) throws Exception
{
163 // NOTE: We need a latch because admin is not sync,
164 // so the postOp coprocessor method may be called after the admin operation returned.
165 MasterSyncObserver observer
= testUtil
.getHBaseCluster().getMaster().getMasterCoprocessorHost()
166 .findCoprocessor(MasterSyncObserver
.class);
167 observer
.tableCreationLatch
= new CountDownLatch(1);
168 Admin admin
= testUtil
.getAdmin();
169 if (splitKeys
!= null) {
170 admin
.createTable(tableDescriptor
, splitKeys
);
172 admin
.createTable(tableDescriptor
);
174 observer
.tableCreationLatch
.await();
175 observer
.tableCreationLatch
= null;
176 testUtil
.waitUntilAllRegionsAssigned(tableDescriptor
.getTableName());
179 public static void deleteTable(HBaseTestingUtil testUtil
, TableName tableName
)
181 // NOTE: We need a latch because admin is not sync,
182 // so the postOp coprocessor method may be called after the admin operation returned.
183 MasterSyncObserver observer
= testUtil
.getHBaseCluster().getMaster()
184 .getMasterCoprocessorHost().findCoprocessor(MasterSyncObserver
.class);
185 observer
.tableDeletionLatch
= new CountDownLatch(1);
186 Admin admin
= testUtil
.getAdmin();
188 admin
.disableTable(tableName
);
189 } catch (Exception e
) {
190 LOG
.debug("Table: " + tableName
+ " already disabled, so just deleting it.");
192 admin
.deleteTable(tableName
);
193 observer
.tableDeletionLatch
.await();
194 observer
.tableDeletionLatch
= null;