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 import java.io.InputStream;
23 import java.io.OutputStream;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.fs.FileSystem;
29 import org.apache.hadoop.fs.Path;
30 import org.apache.hadoop.hbase.ProcedureInfo;
31 import org.apache.hadoop.hbase.util.Threads;
32 import org.apache.hadoop.hbase.exceptions.IllegalArgumentIOException;
33 import org.apache.hadoop.hbase.exceptions.TimeoutIOException;
34 import org.apache.hadoop.hbase.procedure2.store.ProcedureStore;
35 import org.apache.hadoop.hbase.procedure2.store.wal.WALProcedureStore;
36 import org.apache.hadoop.hbase.protobuf.generated.ErrorHandlingProtos.ForeignExceptionMessage;
37
38 import static org.junit.Assert.assertEquals;
39 import static org.junit.Assert.assertFalse;
40 import static org.junit.Assert.assertTrue;
41
42 public class ProcedureTestingUtility {
43 private static final Log LOG = LogFactory.getLog(ProcedureTestingUtility.class);
44
45 private ProcedureTestingUtility() {
46 }
47
48 public static ProcedureStore createStore(final Configuration conf, final FileSystem fs,
49 final Path baseDir) throws IOException {
50 return createWalStore(conf, fs, baseDir);
51 }
52
53 public static WALProcedureStore createWalStore(final Configuration conf, final FileSystem fs,
54 final Path logDir) throws IOException {
55 return new WALProcedureStore(conf, fs, logDir, new WALProcedureStore.LeaseRecovery() {
56 @Override
57 public void recoverFileLease(FileSystem fs, Path path) throws IOException {
58
59 }
60 });
61 }
62
63 public static <TEnv> void restart(ProcedureExecutor<TEnv> procExecutor)
64 throws Exception {
65 restart(procExecutor, null);
66 }
67
68 public static <TEnv> void restart(ProcedureExecutor<TEnv> procExecutor,
69 Runnable beforeStartAction) throws Exception {
70 ProcedureStore procStore = procExecutor.getStore();
71 int storeThreads = procExecutor.getNumThreads();
72 int execThreads = procExecutor.getNumThreads();
73
74 procExecutor.stop();
75 procExecutor.join();
76 procStore.stop(false);
77
78 if (beforeStartAction != null) {
79 beforeStartAction.run();
80 }
81
82 procStore.start(storeThreads);
83 procExecutor.start(execThreads);
84 }
85
86 public static <TEnv> void setKillBeforeStoreUpdate(ProcedureExecutor<TEnv> procExecutor,
87 boolean value) {
88 if (procExecutor.testing == null) {
89 procExecutor.testing = new ProcedureExecutor.Testing();
90 }
91 procExecutor.testing.killBeforeStoreUpdate = value;
92 LOG.warn("Set Kill before store update to: " + procExecutor.testing.killBeforeStoreUpdate);
93 }
94
95 public static <TEnv> void setToggleKillBeforeStoreUpdate(ProcedureExecutor<TEnv> procExecutor,
96 boolean value) {
97 if (procExecutor.testing == null) {
98 procExecutor.testing = new ProcedureExecutor.Testing();
99 }
100 procExecutor.testing.toggleKillBeforeStoreUpdate = value;
101 }
102
103 public static <TEnv> void toggleKillBeforeStoreUpdate(ProcedureExecutor<TEnv> procExecutor) {
104 if (procExecutor.testing == null) {
105 procExecutor.testing = new ProcedureExecutor.Testing();
106 }
107 procExecutor.testing.killBeforeStoreUpdate = !procExecutor.testing.killBeforeStoreUpdate;
108 LOG.warn("Set Kill before store update to: " + procExecutor.testing.killBeforeStoreUpdate);
109 }
110
111 public static <TEnv> void setKillAndToggleBeforeStoreUpdate(ProcedureExecutor<TEnv> procExecutor,
112 boolean value) {
113 ProcedureTestingUtility.setKillBeforeStoreUpdate(procExecutor, value);
114 ProcedureTestingUtility.setToggleKillBeforeStoreUpdate(procExecutor, value);
115 }
116
117 public static <TEnv> long submitAndWait(ProcedureExecutor<TEnv> procExecutor, Procedure proc) {
118 long procId = procExecutor.submitProcedure(proc);
119 waitProcedure(procExecutor, procId);
120 return procId;
121 }
122
123 public static <TEnv> void waitProcedure(ProcedureExecutor<TEnv> procExecutor, long procId) {
124 while (!procExecutor.isFinished(procId) && procExecutor.isRunning()) {
125 Threads.sleepWithoutInterrupt(250);
126 }
127 }
128
129 public static <TEnv> void waitNoProcedureRunning(ProcedureExecutor<TEnv> procExecutor) {
130 int stableRuns = 0;
131 while (stableRuns < 10) {
132 if (procExecutor.getActiveExecutorCount() > 0 || procExecutor.getRunnableSet().size() > 0) {
133 stableRuns = 0;
134 Threads.sleepWithoutInterrupt(100);
135 } else {
136 stableRuns++;
137 Threads.sleepWithoutInterrupt(25);
138 }
139 }
140 }
141
142 public static <TEnv> void assertProcNotYetCompleted(ProcedureExecutor<TEnv> procExecutor,
143 long procId) {
144 assertFalse("expected a running proc", procExecutor.isFinished(procId));
145 assertEquals(null, procExecutor.getResult(procId));
146 }
147
148 public static <TEnv> void assertProcNotFailed(ProcedureExecutor<TEnv> procExecutor,
149 long procId) {
150 ProcedureInfo result = procExecutor.getResult(procId);
151 assertTrue("expected procedure result", result != null);
152 assertProcNotFailed(result);
153 }
154
155 public static void assertProcNotFailed(final ProcedureInfo result) {
156 ForeignExceptionMessage exception = result.getForeignExceptionMessage();
157 String msg = exception != null ? result.getExceptionFullMessage() : "no exception found";
158 assertFalse(msg, result.isFailed());
159 }
160
161 public static void assertIsAbortException(final ProcedureInfo result) {
162 assertEquals(true, result.isFailed());
163 LOG.info(result.getExceptionFullMessage());
164 Throwable cause = getExceptionCause(result);
165 assertTrue("expected abort exception, got " + cause,
166 cause instanceof ProcedureAbortedException);
167 }
168
169 public static void assertIsTimeoutException(final ProcedureInfo result) {
170 assertEquals(true, result.isFailed());
171 LOG.info(result.getExceptionFullMessage());
172 Throwable cause = getExceptionCause(result);
173 assertTrue("expected TimeoutIOException, got " + cause, cause instanceof TimeoutIOException);
174 }
175
176 public static void assertIsIllegalArgumentException(final ProcedureInfo result) {
177 assertEquals(true, result.isFailed());
178 LOG.info(result.getExceptionFullMessage());
179 Throwable cause = ProcedureTestingUtility.getExceptionCause(result);
180 assertTrue("expected IllegalArgumentIOException, got " + cause,
181 cause instanceof IllegalArgumentIOException);
182 }
183
184 public static Throwable getExceptionCause(final ProcedureInfo procInfo) {
185 assert procInfo.getForeignExceptionMessage() != null;
186 return RemoteProcedureException.fromProto(procInfo.getForeignExceptionMessage()).getCause();
187 }
188
189 public static class TestProcedure extends Procedure<Void> {
190 public TestProcedure() {}
191
192 public TestProcedure(long procId) {
193 this(procId, 0);
194 }
195
196 public TestProcedure(long procId, long parentId) {
197 setProcId(procId);
198 if (parentId > 0) {
199 setParentProcId(parentId);
200 }
201 }
202
203 public void addStackId(final int index) {
204 addStackIndex(index);
205 }
206
207 @Override
208 protected Procedure[] execute(Void env) { return null; }
209
210 @Override
211 protected void rollback(Void env) { }
212
213 @Override
214 protected boolean abort(Void env) { return false; }
215
216 @Override
217 protected void serializeStateData(final OutputStream stream) throws IOException { }
218
219 @Override
220 protected void deserializeStateData(final InputStream stream) throws IOException { }
221 }
222 }