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  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          // no-op
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      // stop
74      procExecutor.stop();
75      procExecutor.join();
76      procStore.stop(false);
77      // nothing running...
78      if (beforeStartAction != null) {
79        beforeStartAction.run();
80      }
81      // re-start
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 }