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 static org.junit.Assert.assertTrue;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HBaseTestingUtility;
27  import org.apache.hadoop.hbase.HTableDescriptor;
28  import org.apache.hadoop.hbase.ProcedureInfo;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.TableNotDisabledException;
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.EnableTableState;
34  import org.apache.hadoop.hbase.testclassification.MediumTests;
35  import org.apache.hadoop.hbase.util.Bytes;
36  
37  import org.junit.After;
38  import org.junit.AfterClass;
39  import org.junit.Assert;
40  import org.junit.Before;
41  import org.junit.BeforeClass;
42  import org.junit.Test;
43  import org.junit.experimental.categories.Category;
44  
45  @Category(MediumTests.class)
46  public class TestEnableTableProcedure {
47    private static final Log LOG = LogFactory.getLog(TestEnableTableProcedure.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      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
73    }
74  
75    @After
76    public void tearDown() throws Exception {
77      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
78      for (HTableDescriptor htd: UTIL.getHBaseAdmin().listTables()) {
79        LOG.info("Tear down, remove table=" + htd.getTableName());
80        UTIL.deleteTable(htd.getTableName());
81      }
82    }
83  
84    @Test(timeout = 60000)
85    public void testEnableTable() throws Exception {
86      final TableName tableName = TableName.valueOf("testEnableTable");
87      final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
88  
89      MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
90      UTIL.getHBaseAdmin().disableTable(tableName);
91  
92      // Enable the table
93      long procId = procExec.submitProcedure(
94        new EnableTableProcedure(procExec.getEnvironment(), tableName, false));
95      // Wait the completion
96      ProcedureTestingUtility.waitProcedure(procExec, procId);
97      ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
98      MasterProcedureTestingUtility.validateTableIsEnabled(UTIL.getHBaseCluster().getMaster(),
99        tableName);
100   }
101 
102   @Test(timeout=60000, expected=TableNotDisabledException.class)
103   public void testEnableNonDisabledTable() throws Exception {
104     final TableName tableName = TableName.valueOf("testEnableNonExistingTable");
105     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
106 
107     MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
108 
109     // Enable the table - expect failure
110     long procId1 = procExec.submitProcedure(
111         new EnableTableProcedure(procExec.getEnvironment(), tableName, false));
112     ProcedureTestingUtility.waitProcedure(procExec, procId1);
113 
114     ProcedureInfo result = procExec.getResult(procId1);
115     assertTrue(result.isFailed());
116     LOG.debug("Enable failed with exception: " + result.getExceptionFullMessage());
117     assertTrue(
118       ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotDisabledException);
119 
120     // Enable the table with skipping table state check flag (simulate recovery scenario)
121     long procId2 = procExec.submitProcedure(
122         new EnableTableProcedure(procExec.getEnvironment(), tableName, true));
123     // Wait the completion
124     ProcedureTestingUtility.waitProcedure(procExec, procId2);
125     ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
126 
127     // Enable the table - expect failure from ProcedurePrepareLatch
128     final ProcedurePrepareLatch prepareLatch = new ProcedurePrepareLatch.CompatibilityLatch();
129     long procId3 = procExec.submitProcedure(
130         new EnableTableProcedure(procExec.getEnvironment(), tableName, false, prepareLatch));
131     prepareLatch.await();
132     Assert.fail("Enable should throw exception through latch.");
133   }
134 
135   @Test(timeout = 60000)
136   public void testRecoveryAndDoubleExecution() throws Exception {
137     final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution");
138     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
139 
140     final byte[][] splitKeys = new byte[][] {
141       Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
142     };
143     MasterProcedureTestingUtility.createTable(procExec, tableName, splitKeys, "f1", "f2");
144     UTIL.getHBaseAdmin().disableTable(tableName);
145     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
146     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
147 
148     // Start the Enable procedure && kill the executor
149     long procId = procExec.submitProcedure(
150         new EnableTableProcedure(procExec.getEnvironment(), tableName, false));
151 
152     // Restart the executor and execute the step twice
153     int numberOfSteps = EnableTableState.values().length;
154     MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
155       procExec,
156       procId,
157       numberOfSteps,
158       EnableTableState.values());
159     MasterProcedureTestingUtility.validateTableIsEnabled(UTIL.getHBaseCluster().getMaster(),
160       tableName);
161   }
162 
163   @Test(timeout = 60000)
164   public void testRollbackAndDoubleExecution() throws Exception {
165     final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution");
166     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
167 
168     final byte[][] splitKeys = new byte[][] {
169       Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
170     };
171     MasterProcedureTestingUtility.createTable(procExec, tableName, splitKeys, "f1", "f2");
172     UTIL.getHBaseAdmin().disableTable(tableName);
173     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
174     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
175 
176     // Start the Enable procedure && kill the executor
177     long procId = procExec.submitProcedure(
178         new EnableTableProcedure(procExec.getEnvironment(), tableName, false));
179 
180     int numberOfSteps = EnableTableState.values().length - 2; // failing in the middle of proc
181     MasterProcedureTestingUtility.testRollbackAndDoubleExecution(
182       procExec,
183       procId,
184       numberOfSteps,
185       EnableTableState.values());
186     MasterProcedureTestingUtility.validateTableIsDisabled(UTIL.getHBaseCluster().getMaster(),
187       tableName);
188   }
189 
190   private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
191     return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
192   }
193 }