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
.HBaseTestingUtility
;
28 import org
.apache
.hadoop
.hbase
.HColumnDescriptor
;
29 import org
.apache
.hadoop
.hbase
.HConstants
;
30 import org
.apache
.hadoop
.hbase
.HTableDescriptor
;
31 import org
.apache
.hadoop
.hbase
.MetaTableAccessor
;
32 import org
.apache
.hadoop
.hbase
.TableName
;
33 import org
.apache
.hadoop
.hbase
.coprocessor
.CoprocessorHost
;
34 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterCoprocessor
;
35 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterCoprocessorEnvironment
;
36 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterObserver
;
37 import org
.apache
.hadoop
.hbase
.coprocessor
.ObserverContext
;
38 import org
.apache
.hadoop
.hbase
.testclassification
.MasterTests
;
39 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
40 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
41 import org
.junit
.After
;
42 import org
.junit
.Before
;
43 import org
.junit
.ClassRule
;
44 import org
.junit
.Rule
;
45 import org
.junit
.Test
;
46 import org
.junit
.experimental
.categories
.Category
;
47 import org
.junit
.rules
.TestName
;
48 import org
.slf4j
.Logger
;
49 import org
.slf4j
.LoggerFactory
;
51 @Category({ MasterTests
.class, MediumTests
.class })
52 public class TestEnableTable
{
55 public static final HBaseClassTestRule CLASS_RULE
=
56 HBaseClassTestRule
.forClass(TestEnableTable
.class);
58 private static final HBaseTestingUtility TEST_UTIL
= new HBaseTestingUtility();
59 private static final Logger LOG
= LoggerFactory
.getLogger(TestEnableTable
.class);
60 private static final byte[] FAMILYNAME
= Bytes
.toBytes("fam");
63 public TestName name
= new TestName();
66 public void setUp() throws Exception
{
67 TEST_UTIL
.getConfiguration().set(CoprocessorHost
.MASTER_COPROCESSOR_CONF_KEY
,
68 MasterSyncObserver
.class.getName());
69 TEST_UTIL
.startMiniCluster(1);
73 public void tearDown() throws Exception
{
74 TEST_UTIL
.shutdownMiniCluster();
78 * We were only clearing rows that had a hregioninfo column in hbase:meta. Mangled rows that
79 * were missing the hregioninfo because of error were being left behind messing up any
80 * subsequent table made with the same name. HBASE-12980
82 * @throws InterruptedException
85 public void testDeleteForSureClearsAllTableRowsFromMeta()
86 throws IOException
, InterruptedException
{
87 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
88 final Admin admin
= TEST_UTIL
.getAdmin();
89 final HTableDescriptor desc
= new HTableDescriptor(tableName
);
90 desc
.addFamily(new HColumnDescriptor(FAMILYNAME
));
92 createTable(TEST_UTIL
, desc
, HBaseTestingUtility
.KEYS_FOR_HBA_CREATE_TABLE
);
93 } catch (Exception e
) {
95 fail("Got an exception while creating " + tableName
);
97 // Now I have a nice table, mangle it by removing the HConstants.REGIONINFO_QUALIFIER_STR
98 // content from a few of the rows.
99 try (Table metaTable
= TEST_UTIL
.getConnection().getTable(TableName
.META_TABLE_NAME
)) {
100 try (ResultScanner scanner
= metaTable
.getScanner(
101 MetaTableAccessor
.getScanForTableName(TEST_UTIL
.getConnection(), tableName
))) {
102 for (Result result
: scanner
) {
103 // Just delete one row.
104 Delete d
= new Delete(result
.getRow());
105 d
.addColumn(HConstants
.CATALOG_FAMILY
, HConstants
.REGIONINFO_QUALIFIER
);
106 LOG
.info("Mangled: " + d
);
111 admin
.disableTable(tableName
);
112 TEST_UTIL
.waitTableDisabled(tableName
.getName());
113 // Rely on the coprocessor based latch to make the operation synchronous.
115 deleteTable(TEST_UTIL
, tableName
);
116 } catch (Exception e
) {
118 fail("Got an exception while deleting " + tableName
);
121 try (ResultScanner scanner
= metaTable
122 .getScanner(MetaTableAccessor
.getScanForTableName(TEST_UTIL
.getConnection(), tableName
))) {
123 for (Result result
: scanner
) {
124 LOG
.info("Found when none expected: " + result
);
128 assertEquals(0, rowCount
);
132 public static class MasterSyncObserver
implements MasterCoprocessor
, MasterObserver
{
133 volatile CountDownLatch tableCreationLatch
= null;
134 volatile CountDownLatch tableDeletionLatch
= null;
137 public Optional
<MasterObserver
> getMasterObserver() {
138 return Optional
.of(this);
142 public void postCompletedCreateTableAction(
143 final ObserverContext
<MasterCoprocessorEnvironment
> ctx
,
144 final TableDescriptor desc
,
145 final RegionInfo
[] regions
) throws IOException
{
146 // the AccessController test, some times calls only and directly the
147 // postCompletedCreateTableAction()
148 if (tableCreationLatch
!= null) {
149 tableCreationLatch
.countDown();
154 public void postCompletedDeleteTableAction(
155 final ObserverContext
<MasterCoprocessorEnvironment
> ctx
,
156 final TableName tableName
)
158 // the AccessController test, some times calls only and directly the postDeleteTableHandler()
159 if (tableDeletionLatch
!= null) {
160 tableDeletionLatch
.countDown();
165 public static void createTable(HBaseTestingUtility testUtil
,
166 HTableDescriptor htd
, byte [][] splitKeys
)
168 // NOTE: We need a latch because admin is not sync,
169 // so the postOp coprocessor method may be called after the admin operation returned.
170 MasterSyncObserver observer
= testUtil
.getHBaseCluster().getMaster()
171 .getMasterCoprocessorHost().findCoprocessor(MasterSyncObserver
.class);
172 observer
.tableCreationLatch
= new CountDownLatch(1);
173 Admin admin
= testUtil
.getAdmin();
174 if (splitKeys
!= null) {
175 admin
.createTable(htd
, splitKeys
);
177 admin
.createTable(htd
);
179 observer
.tableCreationLatch
.await();
180 observer
.tableCreationLatch
= null;
181 testUtil
.waitUntilAllRegionsAssigned(htd
.getTableName());
184 public static void deleteTable(HBaseTestingUtility testUtil
, TableName tableName
)
186 // NOTE: We need a latch because admin is not sync,
187 // so the postOp coprocessor method may be called after the admin operation returned.
188 MasterSyncObserver observer
= testUtil
.getHBaseCluster().getMaster()
189 .getMasterCoprocessorHost().findCoprocessor(MasterSyncObserver
.class);
190 observer
.tableDeletionLatch
= new CountDownLatch(1);
191 Admin admin
= testUtil
.getAdmin();
193 admin
.disableTable(tableName
);
194 } catch (Exception e
) {
195 LOG
.debug("Table: " + tableName
+ " already disabled, so just deleting it.");
197 admin
.deleteTable(tableName
);
198 observer
.tableDeletionLatch
.await();
199 observer
.tableDeletionLatch
= null;