1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tradefed.util;
18 
19 import com.android.tradefed.command.CommandScheduler;
20 
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.util.List;
25 
26 /**
27  * Interface for running timed operations and system commands.
28  */
29 public interface IRunUtil {
30 
31     /**
32      * An interface for asynchronously executing an operation that returns a boolean status.
33      */
34     public static interface IRunnableResult {
35         /**
36          * Execute the operation.
37          *
38          * @return <code>true</code> if operation is performed successfully, <code>false</code>
39          *         otherwise
40          * @throws Exception if operation terminated abnormally
41          */
run()42         public boolean run() throws Exception;
43 
44         /**
45          * Cancel the operation.
46          */
cancel()47         public void cancel();
48     }
49 
50     /**
51      * Sets the working directory for system commands.
52      *
53      * @param dir the working directory
54      *
55      * @see ProcessBuilder#directory(File)
56      */
setWorkingDir(File dir)57     public void setWorkingDir(File dir);
58 
59     /**
60      * Sets a environment variable to be used when running system commands.
61      *
62      * @param key the variable name
63      * @param value the variable value
64      *
65      * @see ProcessBuilder#environment()
66      *
67      */
setEnvVariable(String key, String value)68     public void setEnvVariable(String key, String value);
69 
70     /**
71      * Unsets an environment variable, so the system commands run without this environment variable.
72      *
73      * @param key the variable name
74      *
75      * @see ProcessBuilder#environment()
76      */
unsetEnvVariable(String key)77     public void unsetEnvVariable(String key);
78 
79     /**
80      * Helper method to execute a system command, and aborting if it takes longer than a specified
81      * time.
82      *
83      * @param timeout maximum time to wait in ms. 0 means no timeout.
84      * @param command the specified system command and optionally arguments to exec
85      * @return a {@link CommandResult} containing result from command run
86      */
runTimedCmd(final long timeout, final String... command)87     public CommandResult runTimedCmd(final long timeout, final String... command);
88 
89     /**
90      * Helper method to execute a system command, abort if it takes longer than a specified time,
91      * and redirect output to files if specified. When {@link OutputStream} are provided this way,
92      * they will be left open at the end of the function.
93      *
94      * @param timeout timeout maximum time to wait in ms. 0 means no timeout.
95      * @param stdout {@link OutputStream} where the std output will be redirected. Can be null.
96      * @param stderr {@link OutputStream} where the error output will be redirected. Can be null.
97      * @param command the specified system command and optionally arguments to exec
98      * @return a {@link CommandResult} containing result from command run
99      */
runTimedCmd( final long timeout, OutputStream stdout, OutputStream stderr, final String... command)100     public CommandResult runTimedCmd(
101             final long timeout, OutputStream stdout, OutputStream stderr, final String... command);
102 
103     /**
104      * Helper method to execute a system command, and aborting if it takes longer than a specified
105      * time.
106      *
107      * @param timeout maximum time to wait in ms for each attempt
108      * @param command the specified system command and optionally arguments to exec
109      * @param retryInterval time to wait between command retries
110      * @param attempts the maximum number of attempts to try
111      * @return a {@link CommandResult} containing result from command run
112      */
runTimedCmdRetry(final long timeout, long retryInterval, int attempts, final String... command)113     public CommandResult runTimedCmdRetry(final long timeout, long retryInterval,
114             int attempts, final String... command);
115 
116     /**
117      * Helper method to execute a system command, and aborting if it takes longer than a specified
118      * time. Similar to {@link #runTimedCmd(long, String...)}, but does not log any errors on
119      * exception.
120      *
121      * @param timeout maximum time to wait in ms
122      * @param command the specified system command and optionally arguments to exec
123      * @return a {@link CommandResult} containing result from command run
124      */
runTimedCmdSilently(final long timeout, final String... command)125     public CommandResult runTimedCmdSilently(final long timeout, final String... command);
126 
127     /**
128      * Helper method to execute a system command, and aborting if it takes longer than a specified
129      * time. Similar to {@link #runTimedCmdRetry(long, long, int, String[])},
130      * but does not log any errors on exception.
131      *
132      * @param timeout maximum time to wait in ms
133      * @param command the specified system command and optionally arguments to exec
134      * @param retryInterval time to wait between command retries
135      * @param attempts the maximum number of attempts to try
136      * @return a {@link CommandResult} containing result from command run
137      */
runTimedCmdSilentlyRetry(final long timeout, long retryInterval, int attempts, final String... command)138     public CommandResult runTimedCmdSilentlyRetry(final long timeout, long retryInterval,
139             int attempts, final String... command);
140 
141     /**
142      * Helper method to execute a system command that requires stdin input, and aborting if it
143      * takes longer than a specified time.
144      *
145      * @param timeout maximum time to wait in ms
146      * @param input the stdin input to pass to process
147      * @param command the specified system command and optionally arguments to exec
148      * @return a {@link CommandResult} containing result from command run
149      */
runTimedCmdWithInput(long timeout, String input, String... command)150     CommandResult runTimedCmdWithInput(long timeout, String input, String... command);
151 
152     /**
153      * Helper method to execute a system command that requires stdin input, and aborting if it
154      * takes longer than a specified time.
155      *
156      * @param timeout maximum time to wait in ms
157      * @param input the stdin input to pass to process
158      * @param command {@link List} containing the system command and optionally arguments to exec
159      * @return a {@link CommandResult} containing result from command run
160      */
runTimedCmdWithInput(long timeout, String input, List<String> command)161     CommandResult runTimedCmdWithInput(long timeout, String input, List<String> command);
162 
163     /**
164      * Helper method to execute a system command asynchronously.
165      * <p/>
166      * Will return immediately after launching command.
167      *
168      * @param command the specified system command and optionally arguments to exec
169      * @return the {@link Process} of the executed command
170      * @throws IOException if command failed to run
171      */
runCmdInBackground(String... command)172     public Process runCmdInBackground(String... command) throws IOException;
173 
174     /**
175      * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments
176      * in {@link List} form.
177      *
178      * @param command the {@link List} containing specified system command and optionally arguments
179      *            to exec
180      * @return the {@link Process} of the executed command
181      * @throws IOException if command failed to run
182      */
runCmdInBackground(List<String> command)183     public Process runCmdInBackground(List<String> command) throws IOException;
184 
185     /**
186      * Running command with a {@link OutputStream} log the output of the command.
187      * Stdout and stderr are merged together.
188      * @param command the command to run
189      * @param output the OutputStream to save the output
190      * @return the {@link Process} running the command
191      * @throws IOException
192      */
runCmdInBackground(List<String> command, OutputStream output)193     public Process runCmdInBackground(List<String> command, OutputStream output)
194             throws IOException;
195 
196     /**
197      * Block and executes an operation, aborting if it takes longer than a specified time.
198      *
199      * @param timeout maximum time to wait in ms
200      * @param runnable {@link IRunUtil.IRunnableResult} to execute
201      * @param logErrors log errors on exception or not.
202      * @return the {@link CommandStatus} result of operation.
203      */
runTimed(long timeout, IRunUtil.IRunnableResult runnable, boolean logErrors)204     public CommandStatus runTimed(long timeout, IRunUtil.IRunnableResult runnable,
205             boolean logErrors);
206 
207     /**
208      * Block and executes an operation multiple times until it is successful.
209      *
210      * @param opTimeout maximum time to wait in ms for one operation attempt
211      * @param pollInterval time to wait between command retries
212      * @param attempts the maximum number of attempts to try
213      * @param runnable {@link IRunUtil.IRunnableResult} to execute
214      * @return <code>true</code> if operation completed successfully before attempts reached.
215      */
runTimedRetry(long opTimeout, long pollInterval, int attempts, IRunUtil.IRunnableResult runnable)216     public boolean runTimedRetry(long opTimeout, long pollInterval, int attempts,
217             IRunUtil.IRunnableResult runnable);
218 
219     /**
220      * Block and executes an operation multiple times until it is successful.
221      *
222      * @param opTimeout maximum time to wait in ms for a single operation attempt
223      * @param pollInterval initial time to wait between operation attempts
224      * @param maxTime the total approximate maximum time to keep trying the operation
225      * @param runnable {@link IRunUtil.IRunnableResult} to execute
226      * @return <code>true</code> if operation completed successfully before maxTime expired
227      */
runFixedTimedRetry(final long opTimeout, final long pollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)228     public boolean runFixedTimedRetry(final long opTimeout, final long pollInterval,
229             final long maxTime, final IRunUtil.IRunnableResult runnable);
230 
231     /**
232      * Block and executes an operation multiple times until it is successful.
233      * <p/>
234      * Exponentially increase the wait time between operation attempts. This is intended to be used
235      * when performing an operation such as polling a server, to give it time to recover in case it
236      * is temporarily down.
237      *
238      * @param opTimeout maximum time to wait in ms for a single operation attempt
239      * @param initialPollInterval initial time to wait between operation attempts
240      * @param maxPollInterval the max time to wait between operation attempts
241      * @param maxTime the total approximate maximum time to keep trying the operation
242      * @param runnable {@link IRunUtil.IRunnableResult} to execute
243      * @return <code>true</code> if operation completed successfully before maxTime expired
244      */
runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)245     public boolean runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval,
246             final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult
247             runnable);
248 
249     /**
250      * Helper method to sleep for given time, ignoring any exceptions.
251      *
252      * @param time ms to sleep. values less than or equal to 0 will be ignored
253      */
sleep(long time)254     public void sleep(long time);
255 
256     /**
257      * Allows/disallows run interrupts on the current thread. If it is allowed, run operations of
258      * the current thread can be interrupted from other threads via {@link #interrupt} method.
259      *
260      * @param allow whether to allow run interrupts on the current thread.
261      */
allowInterrupt(boolean allow)262     public void allowInterrupt(boolean allow);
263 
264     /**
265      * Give the interrupt status of the RunUtil.
266      * @return true if the Run can be interrupted, false otherwise.
267      */
isInterruptAllowed()268     public boolean isInterruptAllowed();
269 
270     /**
271      * Set as interruptible after some waiting time.
272      * {@link CommandScheduler#shutdownHard()} to enforce we terminate eventually.
273      *
274      * @param thread the thread that will become interruptible.
275      * @param timeMs time to wait before setting interruptible.
276      */
setInterruptibleInFuture(Thread thread, long timeMs)277     public void setInterruptibleInFuture(Thread thread, long timeMs);
278 
279     /**
280      * Interrupts the ongoing/forthcoming run operations on the given thread. The run operations on
281      * the given thread will throw {@link RunInterruptedException}.
282      *
283      * @param thread
284      * @param message the message for {@link RunInterruptedException}.
285      */
interrupt(Thread thread, String message)286     public void interrupt(Thread thread, String message);
287 
288     /**
289      * Decide whether or not when creating a process, unsetting environment variable is higher
290      * priority than setting them.
291      * By Default, unsetting is higher priority: meaning if an attempt to set a variable with the
292      * same name is made, it won't happen since the variable will be unset.
293      * Cannot be used on the default {@link IRunUtil} instance.
294      */
setEnvVariablePriority(EnvPriority priority)295     public void setEnvVariablePriority(EnvPriority priority);
296 
297     /**
298      * Enum that defines whether setting or unsetting a particular env. variable has priority.
299      */
300     public enum EnvPriority {
301         SET,
302         UNSET
303     }
304 }
305