View Javadoc

1   /**
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
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
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.
17   */
18  
19  package org.apache.hadoop.hbase.master.procedure;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.hbase.HBaseTestingUtility;
25  import org.apache.hadoop.hbase.HTableDescriptor;
26  import org.apache.hadoop.hbase.HRegionInfo;
27  import org.apache.hadoop.hbase.ProcedureInfo;
28  import org.apache.hadoop.hbase.TableName;
29  import org.apache.hadoop.hbase.TableNotDisabledException;
30  import org.apache.hadoop.hbase.TableNotFoundException;
31  import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
32  import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
33  import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.DeleteTableState;
34  import org.apache.hadoop.hbase.testclassification.MediumTests;
35  import org.apache.hadoop.hbase.util.Bytes;
36  import org.junit.After;
37  import org.junit.AfterClass;
38  import org.junit.Before;
39  import org.junit.BeforeClass;
40  import org.junit.Test;
41  import org.junit.experimental.categories.Category;
42  
43  import static org.junit.Assert.assertTrue;
44  
45  @Category(MediumTests.class)
46  public class TestDeleteTableProcedure {
47    private static final Log LOG = LogFactory.getLog(TestDeleteTableProcedure.class);
48  
49    protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
50  
51    private static void setupConf(Configuration conf) {
52      conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
53    }
54  
55    @BeforeClass
56    public static void setupCluster() throws Exception {
57      setupConf(UTIL.getConfiguration());
58      UTIL.startMiniCluster(1);
59    }
60  
61    @AfterClass
62    public static void cleanupTest() throws Exception {
63      try {
64        UTIL.shutdownMiniCluster();
65      } catch (Exception e) {
66        LOG.warn("failure shutting down cluster", e);
67      }
68    }
69  
70    @Before
71    public void setup() throws Exception {
72      final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
73      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
74      assertTrue("expected executor to be running", procExec.isRunning());
75    }
76  
77    @After
78    public void tearDown() throws Exception {
79      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
80      for (HTableDescriptor htd: UTIL.getHBaseAdmin().listTables()) {
81        LOG.info("Tear down, remove table=" + htd.getTableName());
82        UTIL.deleteTable(htd.getTableName());
83      }
84    }
85  
86    @Test(timeout=60000, expected=TableNotFoundException.class)
87    public void testDeleteNotExistentTable() throws Exception {
88      final TableName tableName = TableName.valueOf("testDeleteNotExistentTable");
89  
90      final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
91      ProcedurePrepareLatch latch = new ProcedurePrepareLatch.CompatibilityLatch();
92      long procId = ProcedureTestingUtility.submitAndWait(procExec,
93          new DeleteTableProcedure(procExec.getEnvironment(), tableName, latch));
94      latch.await();
95    }
96  
97    @Test(timeout=60000, expected=TableNotDisabledException.class)
98    public void testDeleteNotDisabledTable() throws Exception {
99      final TableName tableName = TableName.valueOf("testDeleteNotDisabledTable");
100 
101     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
102     MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
103 
104     ProcedurePrepareLatch latch = new ProcedurePrepareLatch.CompatibilityLatch();
105     long procId = ProcedureTestingUtility.submitAndWait(procExec,
106         new DeleteTableProcedure(procExec.getEnvironment(), tableName, latch));
107     latch.await();
108   }
109 
110   @Test(timeout=60000)
111   public void testDeleteDeletedTable() throws Exception {
112     final TableName tableName = TableName.valueOf("testDeleteDeletedTable");
113     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
114 
115     HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
116       procExec, tableName, null, "f");
117     UTIL.getHBaseAdmin().disableTable(tableName);
118 
119     // delete the table (that exists)
120     long procId1 = procExec.submitProcedure(
121         new DeleteTableProcedure(procExec.getEnvironment(), tableName));
122     // delete the table (that will no longer exist)
123     long procId2 = procExec.submitProcedure(
124         new DeleteTableProcedure(procExec.getEnvironment(), tableName));
125 
126     // Wait the completion
127     ProcedureTestingUtility.waitProcedure(procExec, procId1);
128     ProcedureTestingUtility.waitProcedure(procExec, procId2);
129 
130     // First delete should succeed
131     ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
132     MasterProcedureTestingUtility.validateTableDeletion(
133       UTIL.getHBaseCluster().getMaster(), tableName, regions, "f");
134 
135     // Second delete should fail with TableNotFound
136     ProcedureInfo result = procExec.getResult(procId2);
137     assertTrue(result.isFailed());
138     LOG.debug("Delete failed with exception: " + result.getExceptionFullMessage());
139     assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotFoundException);
140   }
141 
142   @Test(timeout=60000)
143   public void testSimpleDelete() throws Exception {
144     final TableName tableName = TableName.valueOf("testSimpleDelete");
145     final byte[][] splitKeys = null;
146     testSimpleDelete(tableName, splitKeys);
147   }
148 
149   @Test(timeout=60000)
150   public void testSimpleDeleteWithSplits() throws Exception {
151     final TableName tableName = TableName.valueOf("testSimpleDeleteWithSplits");
152     final byte[][] splitKeys = new byte[][] {
153       Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
154     };
155     testSimpleDelete(tableName, splitKeys);
156   }
157 
158   private void testSimpleDelete(final TableName tableName, byte[][] splitKeys) throws Exception {
159     HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
160       getMasterProcedureExecutor(), tableName, splitKeys, "f1", "f2");
161     UTIL.getHBaseAdmin().disableTable(tableName);
162 
163     // delete the table
164     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
165     long procId = ProcedureTestingUtility.submitAndWait(procExec,
166       new DeleteTableProcedure(procExec.getEnvironment(), tableName));
167     ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
168     MasterProcedureTestingUtility.validateTableDeletion(
169       UTIL.getHBaseCluster().getMaster(), tableName, regions, "f1", "f2");
170   }
171 
172   @Test(timeout=60000)
173   public void testRecoveryAndDoubleExecution() throws Exception {
174     final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution");
175 
176     // create the table
177     byte[][] splitKeys = null;
178     HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
179       getMasterProcedureExecutor(), tableName, splitKeys, "f1", "f2");
180     UTIL.getHBaseAdmin().disableTable(tableName);
181 
182     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
183     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
184     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
185 
186     // Start the Delete procedure && kill the executor
187     long procId = procExec.submitProcedure(
188       new DeleteTableProcedure(procExec.getEnvironment(), tableName));
189 
190     // Restart the executor and execute the step twice
191     // NOTE: the 6 (number of DeleteTableState steps) is hardcoded,
192     //       so you have to look at this test at least once when you add a new step.
193     MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
194       procExec, procId, 6, DeleteTableState.values());
195 
196     MasterProcedureTestingUtility.validateTableDeletion(
197       UTIL.getHBaseCluster().getMaster(), tableName, regions, "f1", "f2");
198   }
199 
200   private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
201     return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
202   }
203 }