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 java.util.Random;
22  import java.util.List;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.HRegionInfo;
30  import org.apache.hadoop.hbase.HTableDescriptor;
31  import org.apache.hadoop.hbase.ProcedureInfo;
32  import org.apache.hadoop.hbase.TableName;
33  import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
34  import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
35  import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.ProcedureState;
36  import org.apache.hadoop.hbase.testclassification.MediumTests;
37  import org.junit.After;
38  import org.junit.AfterClass;
39  import org.junit.Before;
40  import org.junit.BeforeClass;
41  import org.junit.Test;
42  import org.junit.experimental.categories.Category;
43  
44  import static org.junit.Assert.*;
45  
46  @Category(MediumTests.class)
47  public class TestProcedureAdmin {
48    private static final Log LOG = LogFactory.getLog(TestProcedureAdmin.class);
49  
50    protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
51  
52    private static void setupConf(Configuration conf) {
53      conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
54    }
55  
56    @BeforeClass
57    public static void setupCluster() throws Exception {
58      setupConf(UTIL.getConfiguration());
59      UTIL.startMiniCluster(1);
60    }
61  
62    @AfterClass
63    public static void cleanupTest() throws Exception {
64      try {
65        UTIL.shutdownMiniCluster();
66      } catch (Exception e) {
67        LOG.warn("failure shutting down cluster", e);
68      }
69    }
70  
71    @Before
72    public void setup() throws Exception {
73      final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
74      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
75      assertTrue("expected executor to be running", procExec.isRunning());
76    }
77  
78    @After
79    public void tearDown() throws Exception {
80      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
81      for (HTableDescriptor htd: UTIL.getHBaseAdmin().listTables()) {
82        LOG.info("Tear down, remove table=" + htd.getTableName());
83        UTIL.deleteTable(htd.getTableName());
84      }
85    }
86  
87    @Test(timeout=60000)
88    public void testAbortProcedureSuccess() throws Exception {
89      final TableName tableName = TableName.valueOf("testAbortProcedureSuccess");
90      final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
91  
92      MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
93      ProcedureTestingUtility.waitNoProcedureRunning(procExec);
94      ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
95      // Submit an abortable procedure
96      long procId = procExec.submitProcedure(
97          new DisableTableProcedure(procExec.getEnvironment(), tableName, false));
98  
99      boolean abortResult = procExec.abort(procId, true);
100     assertTrue(abortResult);
101 
102     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
103     ProcedureTestingUtility.restart(procExec);
104     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
105     // Validate the disable table procedure was aborted successfully
106     MasterProcedureTestingUtility.validateTableIsEnabled(
107       UTIL.getHBaseCluster().getMaster(),
108       tableName);
109   }
110 
111   @Test(timeout=60000)
112   public void testAbortProcedureFailure() throws Exception {
113     final TableName tableName = TableName.valueOf("testAbortProcedureFailure");
114     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
115 
116     HRegionInfo[] regions =
117         MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
118     UTIL.getHBaseAdmin().disableTable(tableName);
119     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
120     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
121     // Submit an un-abortable procedure
122     long procId = procExec.submitProcedure(
123         new DeleteTableProcedure(procExec.getEnvironment(), tableName));
124 
125     boolean abortResult = procExec.abort(procId, true);
126     assertFalse(abortResult);
127 
128     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
129     ProcedureTestingUtility.restart(procExec);
130     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
131     ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
132     // Validate the delete table procedure was not aborted
133     MasterProcedureTestingUtility.validateTableDeletion(
134       UTIL.getHBaseCluster().getMaster(), tableName, regions, "f");
135   }
136 
137   @Test(timeout=60000)
138   public void testAbortProcedureInterruptedNotAllowed() throws Exception {
139     final TableName tableName = TableName.valueOf("testAbortProcedureInterruptedNotAllowed");
140     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
141 
142     HRegionInfo[] regions =
143         MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
144     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
145     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
146     // Submit a procedure
147     long procId = procExec.submitProcedure(
148         new DisableTableProcedure(procExec.getEnvironment(), tableName, true));
149     // Wait for one step to complete
150     ProcedureTestingUtility.waitProcedure(procExec, procId);
151 
152     // Set the mayInterruptIfRunning flag to false
153     boolean abortResult = procExec.abort(procId, false);
154     assertFalse(abortResult);
155 
156     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
157     ProcedureTestingUtility.restart(procExec);
158     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
159     ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
160     // Validate the delete table procedure was not aborted
161     MasterProcedureTestingUtility.validateTableIsDisabled(
162       UTIL.getHBaseCluster().getMaster(), tableName);
163   }
164 
165   @Test(timeout=60000)
166   public void testAbortNonExistProcedure() throws Exception {
167     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
168     Random randomGenerator = new Random();
169     long procId;
170     // Generate a non-existing procedure
171     do {
172       procId = randomGenerator.nextLong();
173     } while (procExec.getResult(procId) != null);
174 
175     boolean abortResult = procExec.abort(procId, true);
176     assertFalse(abortResult);
177   }
178 
179   @Test(timeout=60000)
180   public void testListProcedure() throws Exception {
181     final TableName tableName = TableName.valueOf("testListProcedure");
182     final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
183 
184     MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
185     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
186     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
187 
188     long procId = procExec.submitProcedure(
189       new DisableTableProcedure(procExec.getEnvironment(), tableName, false));
190 
191     List<ProcedureInfo> listProcedures = procExec.listProcedures();
192     assertTrue(listProcedures.size() >= 1);
193     boolean found = false;
194     for (ProcedureInfo procInfo: listProcedures) {
195       if (procInfo.getProcId() == procId) {
196         assertTrue(procInfo.getProcState() == ProcedureState.RUNNABLE);
197         found = true;
198       } else {
199         assertTrue(procInfo.getProcState() == ProcedureState.FINISHED);
200       }
201     }
202     assertTrue(found);
203 
204     ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
205     ProcedureTestingUtility.restart(procExec);
206     ProcedureTestingUtility.waitNoProcedureRunning(procExec);
207     ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
208     listProcedures = procExec.listProcedures();
209     for (ProcedureInfo procInfo: listProcedures) {
210       assertTrue(procInfo.getProcState() == ProcedureState.FINISHED);
211     }
212   }
213 
214   private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
215     return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
216   }
217 }