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.procedure2;
20  
21  import java.io.IOException;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.fs.FileSystem;
26  import org.apache.hadoop.fs.Path;
27  import org.apache.hadoop.hbase.HBaseCommonTestingUtility;
28  import org.apache.hadoop.hbase.ProcedureInfo;
29  import org.apache.hadoop.hbase.procedure2.store.ProcedureStore;
30  import org.apache.hadoop.hbase.testclassification.SmallTests;
31  import org.apache.hadoop.hbase.testclassification.MasterTests;
32  import org.junit.After;
33  import org.junit.Before;
34  import org.junit.Test;
35  import org.junit.experimental.categories.Category;
36  
37  import static org.junit.Assert.assertEquals;
38  import static org.junit.Assert.assertFalse;
39  import static org.junit.Assert.assertTrue;
40  
41  @Category({MasterTests.class, SmallTests.class})
42  public class TestChildProcedures {
43    private static final Log LOG = LogFactory.getLog(TestChildProcedures.class);
44  
45    private static final int PROCEDURE_EXECUTOR_SLOTS = 1;
46  
47    private static TestProcEnv procEnv;
48    private static ProcedureExecutor<TestProcEnv> procExecutor;
49    private static ProcedureStore procStore;
50  
51    private HBaseCommonTestingUtility htu;
52    private FileSystem fs;
53    private Path testDir;
54    private Path logDir;
55  
56    @Before
57    public void setUp() throws IOException {
58      htu = new HBaseCommonTestingUtility();
59      testDir = htu.getDataTestDir();
60      fs = testDir.getFileSystem(htu.getConfiguration());
61      assertTrue(testDir.depth() > 1);
62  
63      logDir = new Path(testDir, "proc-logs");
64      procEnv = new TestProcEnv();
65      procStore = ProcedureTestingUtility.createStore(htu.getConfiguration(), logDir);
66      procExecutor = new ProcedureExecutor(htu.getConfiguration(), procEnv, procStore);
67      procExecutor.testing = new ProcedureExecutor.Testing();
68      procStore.start(PROCEDURE_EXECUTOR_SLOTS);
69      procExecutor.start(PROCEDURE_EXECUTOR_SLOTS, true);
70    }
71  
72    @After
73    public void tearDown() throws IOException {
74      procExecutor.stop();
75      procStore.stop(false);
76      fs.delete(logDir, true);
77    }
78  
79    @Test
80    public void testChildLoad() throws Exception {
81      procEnv.toggleKillBeforeStoreUpdate = false;
82  
83      TestRootProcedure proc = new TestRootProcedure();
84      long procId = ProcedureTestingUtility.submitAndWait(procExecutor, proc);
85      ProcedureTestingUtility.restart(procExecutor);
86      ProcedureTestingUtility.waitProcedure(procExecutor, proc);
87  
88      assertTrue("expected completed proc", procExecutor.isFinished(procId));
89      ProcedureTestingUtility.assertProcNotFailed(procExecutor, procId);
90    }
91  
92    @Test
93    public void testChildLoadWithSteppedRestart() throws Exception {
94      procEnv.toggleKillBeforeStoreUpdate = true;
95  
96      TestRootProcedure proc = new TestRootProcedure();
97      long procId = ProcedureTestingUtility.submitAndWait(procExecutor, proc);
98      int restartCount = 0;
99      while (!procExecutor.isFinished(procId)) {
100       ProcedureTestingUtility.restart(procExecutor);
101       ProcedureTestingUtility.waitProcedure(procExecutor, proc);
102       restartCount++;
103     }
104     assertEquals(3, restartCount);
105     assertTrue("expected completed proc", procExecutor.isFinished(procId));
106     ProcedureTestingUtility.assertProcNotFailed(procExecutor, procId);
107   }
108 
109   @Test
110   public void testChildRollbackLoad() throws Exception {
111     procEnv.toggleKillBeforeStoreUpdate = false;
112     procEnv.triggerRollbackOnChild = true;
113 
114     TestRootProcedure proc = new TestRootProcedure();
115     long procId = ProcedureTestingUtility.submitAndWait(procExecutor, proc);
116     ProcedureTestingUtility.restart(procExecutor);
117     ProcedureTestingUtility.waitProcedure(procExecutor, proc);
118 
119     assertProcFailed(procId);
120   }
121 
122   @Test
123   public void testChildRollbackLoadWithSteppedRestart() throws Exception {
124     procEnv.toggleKillBeforeStoreUpdate = true;
125     procEnv.triggerRollbackOnChild = true;
126 
127     TestRootProcedure proc = new TestRootProcedure();
128     long procId = ProcedureTestingUtility.submitAndWait(procExecutor, proc);
129     int restartCount = 0;
130     while (!procExecutor.isFinished(procId)) {
131       ProcedureTestingUtility.restart(procExecutor);
132       ProcedureTestingUtility.waitProcedure(procExecutor, proc);
133       restartCount++;
134     }
135     assertEquals(2, restartCount);
136     assertProcFailed(procId);
137   }
138 
139   private void assertProcFailed(long procId) {
140     assertTrue("expected completed proc", procExecutor.isFinished(procId));
141     ProcedureInfo result = procExecutor.getResult(procId);
142     assertEquals(true, result.isFailed());
143     LOG.info(result.getExceptionFullMessage());
144   }
145 
146   public static class TestRootProcedure extends SequentialProcedure<TestProcEnv> {
147     public TestRootProcedure() {}
148 
149     @Override
150     public Procedure[] execute(TestProcEnv env) {
151       if (env.toggleKillBeforeStoreUpdate) {
152         ProcedureTestingUtility.toggleKillBeforeStoreUpdate(procExecutor);
153       }
154       return new Procedure[] { new TestChildProcedure(), new TestChildProcedure() };
155     }
156 
157     @Override
158     public void rollback(TestProcEnv env) {
159     }
160 
161     @Override
162     public boolean abort(TestProcEnv env) {
163       return false;
164     }
165   }
166 
167   public static class TestChildProcedure extends SequentialProcedure<TestProcEnv> {
168     public TestChildProcedure() {}
169 
170     @Override
171     public Procedure[] execute(TestProcEnv env) {
172       if (env.toggleKillBeforeStoreUpdate) {
173         ProcedureTestingUtility.toggleKillBeforeStoreUpdate(procExecutor);
174       }
175       if (env.triggerRollbackOnChild) {
176         setFailure("test", new Exception("test"));
177       }
178       return null;
179     }
180 
181     @Override
182     public void rollback(TestProcEnv env) {
183     }
184 
185     @Override
186     public boolean abort(TestProcEnv env) {
187       return false;
188     }
189   }
190 
191   private static class TestProcEnv {
192     public boolean toggleKillBeforeStoreUpdate = false;
193     public boolean triggerRollbackOnChild = false;
194   }
195 }