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 import com.android.tradefed.cache.ICacheClient; 21 import com.android.tradefed.result.error.ErrorIdentifier; 22 23 import java.io.File; 24 import java.io.IOException; 25 import java.io.OutputStream; 26 import java.lang.ProcessBuilder.Redirect; 27 import java.util.List; 28 29 /** 30 * Interface for running timed operations and system commands. 31 */ 32 public interface IRunUtil { 33 34 /** 35 * An interface for asynchronously executing an operation that returns a boolean status. 36 */ 37 public static interface IRunnableResult { 38 /** 39 * Execute the operation. 40 * 41 * @return <code>true</code> if operation is performed successfully, <code>false</code> 42 * otherwise 43 * @throws Exception if operation terminated abnormally 44 */ run()45 public boolean run() throws Exception; 46 47 /** 48 * Cancel the operation. 49 */ cancel()50 public void cancel(); 51 52 /** Returns the command associated with the runnable. */ getCommand()53 public default List<String> getCommand() { 54 return null; 55 } 56 57 /** Returns the {@link CommandResult} associated with the command. */ getResult()58 public default CommandResult getResult() { 59 return null; 60 } 61 62 /** 63 * Checks if the currently running operation has made progress since the last check. 64 * 65 * @param idleOutputTimeout ms idle with no observed progress before beginning to assume no 66 * progress is being made. 67 * @return true if progress has been detected otherwise false. 68 */ checkOutputMonitor(Long idleOutputTimeout)69 public default boolean checkOutputMonitor(Long idleOutputTimeout) { 70 // Allow existing implementations not to implement this method. 71 throw new UnsupportedOperationException("checkOutputMonitor() has no implementation."); 72 } 73 } 74 75 /** 76 * Sets the working directory for system commands. 77 * 78 * @param dir the working directory 79 * 80 * @see ProcessBuilder#directory(File) 81 */ setWorkingDir(File dir)82 public void setWorkingDir(File dir); 83 84 /** 85 * Sets a environment variable to be used when running system commands. 86 * 87 * @param key the variable name 88 * @param value the variable value 89 * 90 * @see ProcessBuilder#environment() 91 * 92 */ setEnvVariable(String key, String value)93 public void setEnvVariable(String key, String value); 94 95 /** 96 * Unsets an environment variable, so the system commands run without this environment variable. 97 * 98 * @param key the variable name 99 * 100 * @see ProcessBuilder#environment() 101 */ unsetEnvVariable(String key)102 public void unsetEnvVariable(String key); 103 104 /** 105 * Set the standard error stream to redirect to the standard output stream when running system 106 * commands. Initial value is false. 107 * 108 * @param redirect new value for whether or not to redirect 109 * @see ProcessBuilder#redirectErrorStream(boolean) 110 */ setRedirectStderrToStdout(boolean redirect)111 public void setRedirectStderrToStdout(boolean redirect); 112 113 /** 114 * Helper method to execute a system command, and aborting if it takes longer than a specified 115 * time. 116 * 117 * @param timeout maximum time to wait in ms. 0 means no timeout. 118 * @param command the specified system command and optionally arguments to exec 119 * @return a {@link CommandResult} containing result from command run 120 */ runTimedCmd(final long timeout, final String... command)121 public CommandResult runTimedCmd(final long timeout, final String... command); 122 123 /** 124 * Helper method to execute a system command, and aborting if it takes longer than a specified 125 * time. Also monitors the output streams for activity, aborting if no stream activity is 126 * observed for a specified time. If the idleOutputTimeout is set to zero, no stream monitoring 127 * will occur. 128 * 129 * @param timeout maximum time to wait in ms. 0 means no timeout. 130 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 131 * @param command the specified system command and optionally arguments to exec 132 * @return a {@link CommandResult} containing result from command run 133 */ runTimedCmdWithOutputMonitor( final long timeout, final long idleOutputTimeout, final String... command)134 public CommandResult runTimedCmdWithOutputMonitor( 135 final long timeout, final long idleOutputTimeout, final String... command); 136 137 /** 138 * Helper method to execute a system command, abort if it takes longer than a specified time, 139 * and redirect output to files if specified. When {@link OutputStream} are provided this way, 140 * they will be left open at the end of the function. 141 * 142 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 143 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 144 * @param stdout {@link OutputStream} where the std output will be redirected. Can be null. 145 * @param stderr {@link OutputStream} where the error output will be redirected. Can be null. 146 * @param command the specified system command and optionally arguments to exec 147 * @return a {@link CommandResult} containing result from command run 148 */ runTimedCmdWithOutputMonitor( final long timeout, final long idleOutputTimeout, OutputStream stdout, OutputStream stderr, final String... command)149 public CommandResult runTimedCmdWithOutputMonitor( 150 final long timeout, 151 final long idleOutputTimeout, 152 OutputStream stdout, 153 OutputStream stderr, 154 final String... command); 155 156 /** 157 * Helper method to execute a system command with caching. 158 * 159 * <p>If {@code cacheClient} is specified, the caching will be enabled. If the cache is 160 * available, the cached result will be returned. Otherwise, {@link 161 * IRunUtil#runTimedCmdWithOutputMonitor( long, long, OutputStream, OutputStream, String...)} 162 * will be used to execute the command and the result will be uploaded for caching. 163 * 164 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 165 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams. 166 * @param stdout {@link OutputStream} where the std output will be redirected. Can be null. 167 * @param stderr {@link OutputStream} where the error output will be redirected. Can be null. 168 * @param cacheClient an instance of {@link ICacheClient} used to handle caching. 169 * @param command the specified system command and optionally arguments to exec. 170 * @return a {@link CommandResult} containing result from command run. 171 */ runTimedCmdWithOutputMonitor( final long timeout, final long idleOutputTimeout, OutputStream stdout, OutputStream stderr, ICacheClient cacheClient, final String... command)172 public CommandResult runTimedCmdWithOutputMonitor( 173 final long timeout, 174 final long idleOutputTimeout, 175 OutputStream stdout, 176 OutputStream stderr, 177 ICacheClient cacheClient, 178 final String... command); 179 180 /** 181 * Helper method to execute a system command, abort if it takes longer than a specified time, 182 * and redirect output to files if specified. When {@link OutputStream} are provided this way, 183 * they will be left open at the end of the function. 184 * 185 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 186 * @param stdout {@link OutputStream} where the std output will be redirected. Can be null. 187 * @param stderr {@link OutputStream} where the error output will be redirected. Can be null. 188 * @param command the specified system command and optionally arguments to exec 189 * @return a {@link CommandResult} containing result from command run 190 */ runTimedCmd( final long timeout, OutputStream stdout, OutputStream stderr, final String... command)191 public CommandResult runTimedCmd( 192 final long timeout, OutputStream stdout, OutputStream stderr, final String... command); 193 194 /** 195 * Helper method to execute a system command, and aborting if it takes longer than a specified 196 * time. 197 * 198 * @param timeout maximum time to wait in ms for each attempt 199 * @param command the specified system command and optionally arguments to exec 200 * @param retryInterval time to wait between command retries 201 * @param attempts the maximum number of attempts to try 202 * @return a {@link CommandResult} containing result from command run 203 */ runTimedCmdRetry(final long timeout, long retryInterval, int attempts, final String... command)204 public CommandResult runTimedCmdRetry(final long timeout, long retryInterval, 205 int attempts, final String... command); 206 207 /** 208 * Helper method to execute a system command, and aborting if it takes longer than a specified 209 * time. Also monitors the output streams for activity, aborting if no stream activity is 210 * observed for a specified time. If the idleOutputTimeout is set to zero, no stream monitoring 211 * will occur. 212 * 213 * @param timeout maximum time to wait in ms for each attempt 214 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 215 * @param command the specified system command and optionally arguments to exec 216 * @param retryInterval time to wait between command retries 217 * @param attempts the maximum number of attempts to try 218 * @return a {@link CommandResult} containing result from command run 219 */ runTimedCmdRetryWithOutputMonitor( final long timeout, final long idleOutputTimeout, long retryInterval, int attempts, final String... command)220 public CommandResult runTimedCmdRetryWithOutputMonitor( 221 final long timeout, 222 final long idleOutputTimeout, 223 long retryInterval, 224 int attempts, 225 final String... command); 226 227 /** 228 * Helper method to execute a system command, and aborting if it takes longer than a specified 229 * time. Similar to {@link #runTimedCmd(long, String...)}, but does not log any errors on 230 * exception. 231 * 232 * @param timeout maximum time to wait in ms 233 * @param command the specified system command and optionally arguments to exec 234 * @return a {@link CommandResult} containing result from command run 235 */ runTimedCmdSilently(final long timeout, final String... command)236 public CommandResult runTimedCmdSilently(final long timeout, final String... command); 237 238 /** 239 * Helper method to execute a system command, and aborting if it takes longer than a specified 240 * time. Similar to {@link #runTimedCmdRetry(long, long, int, String[])}, 241 * but does not log any errors on exception. 242 * 243 * @param timeout maximum time to wait in ms 244 * @param command the specified system command and optionally arguments to exec 245 * @param retryInterval time to wait between command retries 246 * @param attempts the maximum number of attempts to try 247 * @return a {@link CommandResult} containing result from command run 248 */ runTimedCmdSilentlyRetry(final long timeout, long retryInterval, int attempts, final String... command)249 public CommandResult runTimedCmdSilentlyRetry(final long timeout, long retryInterval, 250 int attempts, final String... command); 251 252 /** 253 * Helper method to execute a system command that requires stdin input, and aborting if it 254 * takes longer than a specified time. 255 * 256 * @param timeout maximum time to wait in ms 257 * @param input the stdin input to pass to process 258 * @param command the specified system command and optionally arguments to exec 259 * @return a {@link CommandResult} containing result from command run 260 */ runTimedCmdWithInput(long timeout, String input, String... command)261 CommandResult runTimedCmdWithInput(long timeout, String input, String... command); 262 263 /** 264 * Helper method to execute a system command that requires stdin input, and aborting if it 265 * takes longer than a specified time. 266 * 267 * @param timeout maximum time to wait in ms 268 * @param input the stdin input to pass to process 269 * @param command {@link List} containing the system command and optionally arguments to exec 270 * @return a {@link CommandResult} containing result from command run 271 */ runTimedCmdWithInput(long timeout, String input, List<String> command)272 CommandResult runTimedCmdWithInput(long timeout, String input, List<String> command); 273 274 /** 275 * Helper method to execute a system command, abort if it takes longer than a specified time, 276 * and redirect output to files if specified. 277 * 278 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 279 * @param input the stdin input to pass to process 280 * @param command the specified system command and optionally arguments to exec 281 * @param stdoutFile {@link File} where the std output will be redirected. Can be null. 282 * @param stderrFile {@link File} where the error output will be redirected. Can be null. 283 * @return a {@link CommandResult} containing result from command run 284 */ runTimedCmdWithInput( long timeout, String input, File stdoutFile, File stderrFile, final String... command)285 public CommandResult runTimedCmdWithInput( 286 long timeout, String input, File stdoutFile, File stderrFile, final String... command); 287 288 /** 289 * Helper method to execute a system command that requires redirecting Stdin from a file, and 290 * aborting if it takes longer than a specified time. 291 * 292 * @param timeout maximum time to wait in ms 293 * @param inputRedirect the {@link File} to redirect as standard input using {@link 294 * ProcessBuilder#redirectInput()}. If null, stdin won't be redirected. 295 * @param command the specified system command and optionally arguments to exec 296 * @return a {@link CommandResult} containing result from command run 297 */ runTimedCmdWithInputRedirect( long timeout, @Nullable File inputRedirect, String... command)298 CommandResult runTimedCmdWithInputRedirect( 299 long timeout, @Nullable File inputRedirect, String... command); 300 301 /** 302 * Helper method to execute a system command asynchronously. 303 * 304 * <p>Will return immediately after launching command. 305 * 306 * @param command the specified system command and optionally arguments to exec 307 * @return the {@link Process} of the executed command 308 * @throws IOException if command failed to run 309 */ runCmdInBackground(String... command)310 public Process runCmdInBackground(String... command) throws IOException; 311 312 /** 313 * Helper method to execute a system command asynchronously. 314 * 315 * <p>Will return immediately after launching command. 316 * 317 * @param redirect The {@link Redirect} to apply to the {@link ProcessBuilder}. 318 * @param command the specified system command and optionally arguments to exec 319 * @return the {@link Process} of the executed command 320 * @throws IOException if command failed to run 321 */ runCmdInBackground(Redirect redirect, final String... command)322 public Process runCmdInBackground(Redirect redirect, final String... command) 323 throws IOException; 324 325 /** 326 * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments 327 * in {@link List} form. 328 * 329 * @param command the {@link List} containing specified system command and optionally arguments 330 * to exec 331 * @return the {@link Process} of the executed command 332 * @throws IOException if command failed to run 333 */ runCmdInBackground(List<String> command)334 public Process runCmdInBackground(List<String> command) throws IOException; 335 336 /** 337 * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments 338 * in {@link List} form. 339 * 340 * @param redirect The {@link Redirect} to apply to the {@link ProcessBuilder}. 341 * @param command the {@link List} containing specified system command and optionally arguments 342 * to exec 343 * @return the {@link Process} of the executed command 344 * @throws IOException if command failed to run 345 */ runCmdInBackground(Redirect redirect, List<String> command)346 public Process runCmdInBackground(Redirect redirect, List<String> command) throws IOException; 347 348 /** 349 * Running command with a {@link OutputStream} log the output of the command. 350 * Stdout and stderr are merged together. 351 * @param command the command to run 352 * @param output the OutputStream to save the output 353 * @return the {@link Process} running the command 354 * @throws IOException 355 */ runCmdInBackground(List<String> command, OutputStream output)356 public Process runCmdInBackground(List<String> command, OutputStream output) 357 throws IOException; 358 359 /** 360 * Block and executes an operation, aborting if it takes longer than a specified time. 361 * 362 * @param timeout maximum time to wait in ms 363 * @param runnable {@link IRunUtil.IRunnableResult} to execute 364 * @param logErrors log errors on exception or not. 365 * @return the {@link CommandStatus} result of operation. 366 */ runTimed(long timeout, IRunUtil.IRunnableResult runnable, boolean logErrors)367 public CommandStatus runTimed(long timeout, IRunUtil.IRunnableResult runnable, 368 boolean logErrors); 369 370 /** 371 * Block and executes an operation, aborting if it takes longer than a specified time. Also 372 * monitors the output streams for activity, aborting if no stream activity is observed for a 373 * specified time. If the idleOutputTimeout is set to zero, no stream monitoring will occur. 374 * 375 * @param timeout maximum time to wait in ms 376 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 377 * @param runnable {@link IRunUtil.IRunnableResult} to execute 378 * @param logErrors log errors on exception or not. 379 * @return the {@link CommandStatus} result of operation. 380 */ runTimedWithOutputMonitor( final long timeout, final long idleOutputTimeout, IRunUtil.IRunnableResult runnable, boolean logErrors)381 public CommandStatus runTimedWithOutputMonitor( 382 final long timeout, 383 final long idleOutputTimeout, 384 IRunUtil.IRunnableResult runnable, 385 boolean logErrors); 386 387 /** 388 * Block and executes an operation multiple times until it is successful. 389 * 390 * @param opTimeout maximum time to wait in ms for one operation attempt 391 * @param pollInterval time to wait between command retries 392 * @param attempts the maximum number of attempts to try 393 * @param runnable {@link IRunUtil.IRunnableResult} to execute 394 * @return <code>true</code> if operation completed successfully before attempts reached. 395 */ runTimedRetry(long opTimeout, long pollInterval, int attempts, IRunUtil.IRunnableResult runnable)396 public boolean runTimedRetry(long opTimeout, long pollInterval, int attempts, 397 IRunUtil.IRunnableResult runnable); 398 399 /** 400 * Block and executes an operation multiple times until it is successful. Also monitors the 401 * output streams for activity, aborting if no stream activity is observed for a specified time. 402 * If the idleOutputTimeout is set to zero, no stream monitoring will occur. 403 * 404 * @param opTimeout maximum time to wait in ms for one operation attempt 405 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 406 * @param pollInterval time to wait between command retries 407 * @param attempts the maximum number of attempts to try 408 * @param runnable {@link IRunUtil.IRunnableResult} to execute 409 * @return <code>true</code> if operation completed successfully before attempts reached. 410 */ runTimedRetryWithOutputMonitor( final long opTimeout, final long idleOutputTimeout, long pollInterval, int attempts, IRunUtil.IRunnableResult runnable)411 public boolean runTimedRetryWithOutputMonitor( 412 final long opTimeout, 413 final long idleOutputTimeout, 414 long pollInterval, 415 int attempts, 416 IRunUtil.IRunnableResult runnable); 417 418 /** 419 * Block and executes an operation multiple times until it is successful. 420 * 421 * @param opTimeout maximum time to wait in ms for a single operation attempt 422 * @param pollInterval initial time to wait between operation attempts 423 * @param maxTime the total approximate maximum time to keep trying the operation 424 * @param runnable {@link IRunUtil.IRunnableResult} to execute 425 * @return <code>true</code> if operation completed successfully before maxTime expired 426 */ runFixedTimedRetry(final long opTimeout, final long pollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)427 public boolean runFixedTimedRetry(final long opTimeout, final long pollInterval, 428 final long maxTime, final IRunUtil.IRunnableResult runnable); 429 430 /** 431 * Block and executes an operation multiple times until it is successful. Also monitors the 432 * output streams for activity, aborting if no stream activity is observed for a specified time. 433 * If the idleOutputTimeout is set to zero, no stream monitoring will occur. 434 * 435 * @param opTimeout maximum time to wait in ms for a single operation attempt 436 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 437 * @param pollInterval initial time to wait between operation attempts 438 * @param maxTime the total approximate maximum time to keep trying the operation 439 * @param runnable {@link IRunUtil.IRunnableResult} to execute 440 * @return <code>true</code> if operation completed successfully before maxTime expired 441 */ runFixedTimedRetryWithOutputMonitor( final long opTimeout, final long idleOutputTimeout, final long pollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)442 public boolean runFixedTimedRetryWithOutputMonitor( 443 final long opTimeout, 444 final long idleOutputTimeout, 445 final long pollInterval, 446 final long maxTime, 447 final IRunUtil.IRunnableResult runnable); 448 449 /** 450 * Block and executes an operation multiple times until it is successful. 451 * <p/> 452 * Exponentially increase the wait time between operation attempts. This is intended to be used 453 * when performing an operation such as polling a server, to give it time to recover in case it 454 * is temporarily down. 455 * 456 * @param opTimeout maximum time to wait in ms for a single operation attempt 457 * @param initialPollInterval initial time to wait between operation attempts 458 * @param maxPollInterval the max time to wait between operation attempts 459 * @param maxTime the total approximate maximum time to keep trying the operation 460 * @param runnable {@link IRunUtil.IRunnableResult} to execute 461 * @return <code>true</code> if operation completed successfully before maxTime expired 462 */ runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)463 public boolean runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, 464 final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult 465 runnable); 466 467 /** 468 * Helper method to sleep for given time, ignoring any exceptions. 469 * 470 * @param time ms to sleep. values less than or equal to 0 will be ignored 471 */ sleep(long time)472 public void sleep(long time); 473 474 /** 475 * Allows/disallows run interrupts on the current thread. If it is allowed, run operations of 476 * the current thread can be interrupted from other threads via {@link #interrupt} method. 477 * 478 * @param allow whether to allow run interrupts on the current thread. 479 */ allowInterrupt(boolean allow)480 public void allowInterrupt(boolean allow); 481 482 /** 483 * Give the interrupt status of the RunUtil. 484 * @return true if the Run can be interrupted, false otherwise. 485 */ isInterruptAllowed()486 public boolean isInterruptAllowed(); 487 488 /** 489 * Set as interruptible after some waiting time. 490 * {@link CommandScheduler#shutdownHard()} to enforce we terminate eventually. 491 * 492 * @param thread the thread that will become interruptible. 493 * @param timeMs time to wait before setting interruptible. 494 */ setInterruptibleInFuture(Thread thread, long timeMs)495 public void setInterruptibleInFuture(Thread thread, long timeMs); 496 497 /** 498 * Interrupts the ongoing/forthcoming run operations on the given thread. The run operations on 499 * the given thread will throw {@link RunInterruptedException}. 500 * 501 * @param thread 502 * @param message the message for {@link RunInterruptedException}. 503 */ interrupt(Thread thread, String message)504 public void interrupt(Thread thread, String message); 505 506 /** 507 * Interrupts the ongoing/forthcoming run operations on the given thread. The run operations on 508 * the given thread will throw {@link RunInterruptedException}. 509 * 510 * @param thread 511 * @param message the message for {@link RunInterruptedException}. 512 * @param errorId Representing the cause of the interruption when known. 513 */ interrupt(Thread thread, String message, ErrorIdentifier errorId)514 public void interrupt(Thread thread, String message, ErrorIdentifier errorId); 515 516 /** 517 * Decide whether or not when creating a process, unsetting environment variable is higher 518 * priority than setting them. 519 * By Default, unsetting is higher priority: meaning if an attempt to set a variable with the 520 * same name is made, it won't happen since the variable will be unset. 521 * Cannot be used on the default {@link IRunUtil} instance. 522 */ setEnvVariablePriority(EnvPriority priority)523 public void setEnvVariablePriority(EnvPriority priority); 524 525 /** 526 * Allow to use linux 'kill' interruption on process running through #runTimed methods when it 527 * reaches a timeout. 528 * 529 * Cannot be used on the default {@link IRunUtil} instance. 530 */ setLinuxInterruptProcess(boolean interrupt)531 public void setLinuxInterruptProcess(boolean interrupt); 532 533 /** 534 * Enum that defines whether setting or unsetting a particular env. variable has priority. 535 */ 536 public enum EnvPriority { 537 SET, 538 UNSET 539 } 540 } 541