1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 }