|
21 | 21 |
|
22 | 22 | import com.google.cloud.tools.eclipse.test.util.reflection.ReflectionUtil; |
23 | 23 | import com.google.common.base.Joiner; |
| 24 | +import com.google.common.base.Preconditions; |
24 | 25 | import com.google.common.base.Stopwatch; |
| 26 | +import com.google.common.collect.ComparisonChain; |
| 27 | +import com.google.common.collect.Ordering; |
25 | 28 | import java.io.File; |
26 | 29 | import java.io.IOException; |
27 | 30 | import java.net.URL; |
28 | 31 | import java.util.ArrayList; |
| 32 | +import java.util.Arrays; |
29 | 33 | import java.util.Collection; |
30 | 34 | import java.util.Collections; |
31 | 35 | import java.util.Enumeration; |
|
38 | 42 | import java.util.concurrent.TimeUnit; |
39 | 43 | import java.util.zip.ZipEntry; |
40 | 44 | import java.util.zip.ZipFile; |
| 45 | +import org.eclipse.core.internal.jobs.InternalJob; |
41 | 46 | import org.eclipse.core.resources.IMarker; |
42 | 47 | import org.eclipse.core.resources.IProject; |
43 | 48 | import org.eclipse.core.resources.IProjectDescription; |
@@ -283,30 +288,94 @@ public static void waitForProjects(Runnable delayTactic, IProject... projects) { |
283 | 288 | buildErrorsChanging = !previousBuildErrors.equals(currentBuildErrors); |
284 | 289 | previousBuildErrors = currentBuildErrors; |
285 | 290 |
|
286 | | - if (DEBUG || timer.elapsed(TimeUnit.SECONDS) > 10) { |
287 | | - if (!jobs.isEmpty()) { |
| 291 | + if (DEBUG || timer.elapsed(TimeUnit.SECONDS) > 5) { |
| 292 | + if (timer.elapsed(TimeUnit.SECONDS) > 10) { |
| 293 | + dumpJobsState(timer); |
| 294 | + } else if (!jobs.isEmpty()) { |
288 | 295 | System.err.printf("ProjectUtils#waitForProjects[%s]: waiting for %d jobs: %s\n", timer, |
289 | 296 | jobs.size(), jobs); |
290 | 297 | } |
291 | 298 | if (buildErrorsChanging) { |
292 | 299 | System.err.printf("ProjectUtils#waitForProjects[%s]: waiting for %d build errors\n", |
293 | 300 | timer, currentBuildErrors.size()); |
294 | 301 | } |
295 | | - // Uncomment if tests are failing to identify any other build-related jobs. |
296 | | - // Job[] otherJobs = Job.getJobManager().find(null); |
297 | | - // if (otherJobs.length > 0) { |
298 | | - // System.err.printf("Ignoring %d unrelated jobs:\n", otherJobs.length); |
299 | | - // for (Job job : otherJobs) { |
300 | | - // System.err.printf(" %s: %s\n", job.getClass().getName(), job); |
301 | | - // } |
302 | | - // } |
303 | 302 | } |
304 | 303 | } while (!jobs.isEmpty() || buildErrorsChanging); |
305 | 304 | } catch (CoreException | InterruptedException ex) { |
306 | 305 | throw new RuntimeException(ex); |
307 | 306 | } |
308 | 307 | } |
309 | 308 |
|
| 309 | + private static void dumpJobsState(Stopwatch timer) { |
| 310 | + Job[] otherJobs = Job.getJobManager().find(null); |
| 311 | + if (otherJobs.length == 0) { |
| 312 | + System.err.printf("ProjectUtils#dumpJobsState[%s]: no jobs\n", timer); |
| 313 | + return; |
| 314 | + } |
| 315 | + |
| 316 | + Arrays.sort(otherJobs, new Ordering<Job>() { |
| 317 | + @Override |
| 318 | + public int compare(Job j1, Job j2) { |
| 319 | + Preconditions.checkNotNull(j1); |
| 320 | + Preconditions.checkNotNull(j2); |
| 321 | + //@formatter:off |
| 322 | + return ComparisonChain.start() |
| 323 | + .compareTrueFirst(j1.isBlocking(), j2.isBlocking()) |
| 324 | + .compare(j2.getState(), j1.getState()) // descending order so RUNNING is first |
| 325 | + .compare(j1.getPriority(), j2.getPriority()) |
| 326 | + .compareTrueFirst(j1.isUser(), j2.isUser()) |
| 327 | + .compareTrueFirst(j1.isSystem(), j2.isSystem()) |
| 328 | + .compare(j1.getRule(), j2.getRule(), Ordering.usingToString().nullsLast()) |
| 329 | + .result(); |
| 330 | + //@formatter:on |
| 331 | + } |
| 332 | + }); |
| 333 | + |
| 334 | + System.err.printf("ProjectUtils#dumpJobsState[%s]: %d jobs:\n", timer, otherJobs.length); |
| 335 | + for (Job job : otherJobs) { |
| 336 | + String status; |
| 337 | + switch (job.getState()) { |
| 338 | + case Job.RUNNING: |
| 339 | + status = "RUNNING"; |
| 340 | + break; |
| 341 | + case Job.WAITING: |
| 342 | + status = "WAITING"; |
| 343 | + break; |
| 344 | + case Job.SLEEPING: |
| 345 | + status = "SLEEPING"; |
| 346 | + break; |
| 347 | + case Job.NONE: |
| 348 | + status = "NONE"; |
| 349 | + break; |
| 350 | + default: |
| 351 | + status = "UNKNOWN(" + job.getState() + ")"; |
| 352 | + break; |
| 353 | + } |
| 354 | + Object blockingJob = null; |
| 355 | + try { |
| 356 | + blockingJob = ReflectionUtil.invoke(Job.getJobManager(), "findBlockingJob", |
| 357 | + new Class<?>[] {InternalJob.class}, InternalJob.class, job); |
| 358 | + } catch (Exception ex) { |
| 359 | + System.err.println("Unable to fetch blocking-job: " + ex); |
| 360 | + } |
| 361 | + //@formatter:off |
| 362 | + System.err.printf(" + %s%s{pri=%d%s%s%s%s} %s (%s)\n", |
| 363 | + status, |
| 364 | + (job.isBlocking() ? "<BLOCKING>" : ""), |
| 365 | + job.getPriority(), |
| 366 | + (job.getRule() != null ? ",rule=" + job.getRule() : ""), |
| 367 | + (job.isSystem() ? ",system" : ""), |
| 368 | + (job.isUser() ? ",user" : ""), |
| 369 | + (job.getThread() != null ? ",thr=" + job.getThread() : ""), |
| 370 | + job, |
| 371 | + job.getClass().getName()); |
| 372 | + //@formatter:on |
| 373 | + if (blockingJob != null) { |
| 374 | + System.err.println(" - blocked by: " + blockingJob); |
| 375 | + } |
| 376 | + } |
| 377 | + } |
| 378 | + |
310 | 379 | /** Identify all jobs that we know of that are related to building. */ |
311 | 380 | private static Collection<Job> findPendingBuildJobs(IProject... projects) { |
312 | 381 | Set<Job> jobs = new HashSet<>(); |
|
0 commit comments