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.annotations.Nullable; 20 21 import java.io.File; 22 import java.io.IOException; 23 import java.io.OutputStream; 24 import java.lang.ProcessBuilder.Redirect; 25 import java.util.List; 26 27 /** 28 * Interface for running timed operations and system commands. 29 */ 30 public interface IRunUtil { 31 32 /** 33 * An interface for asynchronously executing an operation that returns a boolean status. 34 */ 35 public static interface IRunnableResult { 36 /** 37 * Execute the operation. 38 * 39 * @return <code>true</code> if operation is performed successfully, <code>false</code> 40 * otherwise 41 * @throws Exception if operation terminated abnormally 42 */ run()43 public boolean run() throws Exception; 44 45 /** 46 * Cancel the operation. 47 */ cancel()48 public void cancel(); 49 50 /** Returns the command associated with the runnable. */ getCommand()51 public default List<String> getCommand() { 52 return null; 53 } 54 55 /** Returns the {@link CommandResult} associated with the command. */ getResult()56 public default CommandResult getResult() { 57 return null; 58 } 59 } 60 61 /** 62 * Sets the working directory for system commands. 63 * 64 * @param dir the working directory 65 * 66 * @see ProcessBuilder#directory(File) 67 */ setWorkingDir(File dir)68 public void setWorkingDir(File dir); 69 70 /** 71 * Sets a environment variable to be used when running system commands. 72 * 73 * @param key the variable name 74 * @param value the variable value 75 * 76 * @see ProcessBuilder#environment() 77 * 78 */ setEnvVariable(String key, String value)79 public void setEnvVariable(String key, String value); 80 81 /** 82 * Unsets an environment variable, so the system commands run without this environment variable. 83 * 84 * @param key the variable name 85 * 86 * @see ProcessBuilder#environment() 87 */ unsetEnvVariable(String key)88 public void unsetEnvVariable(String key); 89 90 /** 91 * Set the standard error stream to redirect to the standard output stream when running system 92 * commands. Initial value is false. 93 * 94 * @param redirect new value for whether or not to redirect 95 * @see ProcessBuilder#redirectErrorStream(boolean) 96 */ setRedirectStderrToStdout(boolean redirect)97 public void setRedirectStderrToStdout(boolean redirect); 98 99 /** 100 * Helper method to execute a system command, and aborting if it takes longer than a specified 101 * time. 102 * 103 * @param timeout maximum time to wait in ms. 0 means no timeout. 104 * @param command the specified system command and optionally arguments to exec 105 * @return a {@link CommandResult} containing result from command run 106 */ runTimedCmd(final long timeout, final String... command)107 public CommandResult runTimedCmd(final long timeout, final String... command); 108 109 /** 110 * Helper method to execute a system command, abort if it takes longer than a specified time, 111 * and redirect output to files if specified. When {@link OutputStream} are provided this way, 112 * they will be left open at the end of the function. 113 * 114 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 115 * @param stdout {@link OutputStream} where the std output will be redirected. Can be null. 116 * @param stderr {@link OutputStream} where the error output will be redirected. Can be null. 117 * @param command the specified system command and optionally arguments to exec 118 * @return a {@link CommandResult} containing result from command run 119 */ runTimedCmd( final long timeout, OutputStream stdout, OutputStream stderr, final String... command)120 public CommandResult runTimedCmd( 121 final long timeout, OutputStream stdout, OutputStream stderr, final String... command); 122 123 /** 124 * Helper method to execute a system command, and aborting if it takes longer than a specified 125 * time. 126 * 127 * @param timeout maximum time to wait in ms for each attempt 128 * @param command the specified system command and optionally arguments to exec 129 * @param retryInterval time to wait between command retries 130 * @param attempts the maximum number of attempts to try 131 * @return a {@link CommandResult} containing result from command run 132 */ runTimedCmdRetry(final long timeout, long retryInterval, int attempts, final String... command)133 public CommandResult runTimedCmdRetry(final long timeout, long retryInterval, 134 int attempts, final String... command); 135 136 /** 137 * Helper method to execute a system command, and aborting if it takes longer than a specified 138 * time. Similar to {@link #runTimedCmd(long, String...)}, but does not log any errors on 139 * exception. 140 * 141 * @param timeout maximum time to wait in ms 142 * @param command the specified system command and optionally arguments to exec 143 * @return a {@link CommandResult} containing result from command run 144 */ runTimedCmdSilently(final long timeout, final String... command)145 public CommandResult runTimedCmdSilently(final long timeout, final String... command); 146 147 /** 148 * Helper method to execute a system command, and aborting if it takes longer than a specified 149 * time. Similar to {@link #runTimedCmdRetry(long, long, int, String[])}, 150 * but does not log any errors on exception. 151 * 152 * @param timeout maximum time to wait in ms 153 * @param command the specified system command and optionally arguments to exec 154 * @param retryInterval time to wait between command retries 155 * @param attempts the maximum number of attempts to try 156 * @return a {@link CommandResult} containing result from command run 157 */ runTimedCmdSilentlyRetry(final long timeout, long retryInterval, int attempts, final String... command)158 public CommandResult runTimedCmdSilentlyRetry(final long timeout, long retryInterval, 159 int attempts, final String... command); 160 161 /** 162 * Helper method to execute a system command that requires stdin input, and aborting if it 163 * takes longer than a specified time. 164 * 165 * @param timeout maximum time to wait in ms 166 * @param input the stdin input to pass to process 167 * @param command the specified system command and optionally arguments to exec 168 * @return a {@link CommandResult} containing result from command run 169 */ runTimedCmdWithInput(long timeout, String input, String... command)170 CommandResult runTimedCmdWithInput(long timeout, String input, String... command); 171 172 /** 173 * Helper method to execute a system command that requires stdin input, and aborting if it 174 * takes longer than a specified time. 175 * 176 * @param timeout maximum time to wait in ms 177 * @param input the stdin input to pass to process 178 * @param command {@link List} containing the system command and optionally arguments to exec 179 * @return a {@link CommandResult} containing result from command run 180 */ runTimedCmdWithInput(long timeout, String input, List<String> command)181 CommandResult runTimedCmdWithInput(long timeout, String input, List<String> command); 182 183 /** 184 * Helper method to execute a system command that requires redirecting Stdin from a file, and 185 * aborting if it takes longer than a specified time. 186 * 187 * @param timeout maximum time to wait in ms 188 * @param inputRedirect the {@link File} to redirect as standard input using {@link 189 * ProcessBuilder#redirectInput()}. If null, stdin won't be redirected. 190 * @param command the specified system command and optionally arguments to exec 191 * @return a {@link CommandResult} containing result from command run 192 */ runTimedCmdWithInputRedirect( long timeout, @Nullable File inputRedirect, String... command)193 CommandResult runTimedCmdWithInputRedirect( 194 long timeout, @Nullable File inputRedirect, String... command); 195 196 /** 197 * Helper method to execute a system command asynchronously. 198 * 199 * <p>Will return immediately after launching command. 200 * 201 * @param command the specified system command and optionally arguments to exec 202 * @return the {@link Process} of the executed command 203 * @throws IOException if command failed to run 204 */ runCmdInBackground(String... command)205 public Process runCmdInBackground(String... command) throws IOException; 206 207 /** 208 * Helper method to execute a system command asynchronously. 209 * 210 * <p>Will return immediately after launching command. 211 * 212 * @param redirect The {@link Redirect} to apply to the {@link ProcessBuilder}. 213 * @param command the specified system command and optionally arguments to exec 214 * @return the {@link Process} of the executed command 215 * @throws IOException if command failed to run 216 */ runCmdInBackground(Redirect redirect, final String... command)217 public Process runCmdInBackground(Redirect redirect, final String... command) 218 throws IOException; 219 220 /** 221 * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments 222 * in {@link List} form. 223 * 224 * @param command the {@link List} containing specified system command and optionally arguments 225 * to exec 226 * @return the {@link Process} of the executed command 227 * @throws IOException if command failed to run 228 */ runCmdInBackground(List<String> command)229 public Process runCmdInBackground(List<String> command) throws IOException; 230 231 /** 232 * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments 233 * in {@link List} form. 234 * 235 * @param redirect The {@link Redirect} to apply to the {@link ProcessBuilder}. 236 * @param command the {@link List} containing specified system command and optionally arguments 237 * to exec 238 * @return the {@link Process} of the executed command 239 * @throws IOException if command failed to run 240 */ runCmdInBackground(Redirect redirect, List<String> command)241 public Process runCmdInBackground(Redirect redirect, List<String> command) throws IOException; 242 243 /** 244 * Running command with a {@link OutputStream} log the output of the command. 245 * Stdout and stderr are merged together. 246 * @param command the command to run 247 * @param output the OutputStream to save the output 248 * @return the {@link Process} running the command 249 * @throws IOException 250 */ runCmdInBackground(List<String> command, OutputStream output)251 public Process runCmdInBackground(List<String> command, OutputStream output) 252 throws IOException; 253 254 /** 255 * Block and executes an operation, aborting if it takes longer than a specified time. 256 * 257 * @param timeout maximum time to wait in ms 258 * @param runnable {@link IRunUtil.IRunnableResult} to execute 259 * @param logErrors log errors on exception or not. 260 * @return the {@link CommandStatus} result of operation. 261 */ runTimed(long timeout, IRunUtil.IRunnableResult runnable, boolean logErrors)262 public CommandStatus runTimed(long timeout, IRunUtil.IRunnableResult runnable, 263 boolean logErrors); 264 265 /** 266 * Block and executes an operation multiple times until it is successful. 267 * 268 * @param opTimeout maximum time to wait in ms for one operation attempt 269 * @param pollInterval time to wait between command retries 270 * @param attempts the maximum number of attempts to try 271 * @param runnable {@link IRunUtil.IRunnableResult} to execute 272 * @return <code>true</code> if operation completed successfully before attempts reached. 273 */ runTimedRetry(long opTimeout, long pollInterval, int attempts, IRunUtil.IRunnableResult runnable)274 public boolean runTimedRetry(long opTimeout, long pollInterval, int attempts, 275 IRunUtil.IRunnableResult runnable); 276 277 /** 278 * Block and executes an operation multiple times until it is successful. 279 * 280 * @param opTimeout maximum time to wait in ms for a single operation attempt 281 * @param pollInterval initial time to wait between operation attempts 282 * @param maxTime the total approximate maximum time to keep trying the operation 283 * @param runnable {@link IRunUtil.IRunnableResult} to execute 284 * @return <code>true</code> if operation completed successfully before maxTime expired 285 */ runFixedTimedRetry(final long opTimeout, final long pollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)286 public boolean runFixedTimedRetry(final long opTimeout, final long pollInterval, 287 final long maxTime, final IRunUtil.IRunnableResult runnable); 288 289 /** 290 * Block and executes an operation multiple times until it is successful. 291 * <p/> 292 * Exponentially increase the wait time between operation attempts. This is intended to be used 293 * when performing an operation such as polling a server, to give it time to recover in case it 294 * is temporarily down. 295 * 296 * @param opTimeout maximum time to wait in ms for a single operation attempt 297 * @param initialPollInterval initial time to wait between operation attempts 298 * @param maxPollInterval the max time to wait between operation attempts 299 * @param maxTime the total approximate maximum time to keep trying the operation 300 * @param runnable {@link IRunUtil.IRunnableResult} to execute 301 * @return <code>true</code> if operation completed successfully before maxTime expired 302 */ runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)303 public boolean runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, 304 final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult 305 runnable); 306 307 /** 308 * Helper method to sleep for given time, ignoring any exceptions. 309 * 310 * @param time ms to sleep. values less than or equal to 0 will be ignored 311 */ sleep(long time)312 public void sleep(long time); 313 314 /** 315 * Allows/disallows run interrupts on the current thread. If it is allowed, run operations of 316 * the current thread can be interrupted from other threads via {@link #interrupt} method. 317 * 318 * @param allow whether to allow run interrupts on the current thread. 319 */ allowInterrupt(boolean allow)320 public void allowInterrupt(boolean allow); 321 322 /** 323 * Give the interrupt status of the RunUtil. 324 * @return true if the Run can be interrupted, false otherwise. 325 */ isInterruptAllowed()326 public boolean isInterruptAllowed(); 327 328 /** 329 * Set as interruptible after some waiting time. 330 * {@link CommandScheduler#shutdownHard()} to enforce we terminate eventually. 331 * 332 * @param thread the thread that will become interruptible. 333 * @param timeMs time to wait before setting interruptible. 334 */ setInterruptibleInFuture(Thread thread, long timeMs)335 public void setInterruptibleInFuture(Thread thread, long timeMs); 336 337 /** 338 * Interrupts the ongoing/forthcoming run operations on the given thread. The run operations on 339 * the given thread will throw {@link RunInterruptedException}. 340 * 341 * @param thread 342 * @param message the message for {@link RunInterruptedException}. 343 */ interrupt(Thread thread, String message)344 public void interrupt(Thread thread, String message); 345 346 /** 347 * Decide whether or not when creating a process, unsetting environment variable is higher 348 * priority than setting them. 349 * By Default, unsetting is higher priority: meaning if an attempt to set a variable with the 350 * same name is made, it won't happen since the variable will be unset. 351 * Cannot be used on the default {@link IRunUtil} instance. 352 */ setEnvVariablePriority(EnvPriority priority)353 public void setEnvVariablePriority(EnvPriority priority); 354 355 /** 356 * Enum that defines whether setting or unsetting a particular env. variable has priority. 357 */ 358 public enum EnvPriority { 359 SET, 360 UNSET 361 } 362 } 363