11package bloop .engine .tasks
22
3+ import java .nio .file .Path
34import java .util .Optional
5+ import java .util .concurrent .ConcurrentLinkedQueue
6+ import java .util .concurrent .atomic .AtomicInteger
7+
48import scala .collection .mutable
59import scala .concurrent .Promise
10+
611import bloop .CompileBackgroundTasks
712import bloop .CompileInputs
813import bloop .CompileOutPaths
@@ -35,17 +40,18 @@ import bloop.reporter.ReporterInputs
3540import bloop .task .Task
3641import bloop .tracing .BraveTracer
3742import bloop .util .BestEffortUtils .BestEffortProducts
43+
3844import monix .execution .CancelableFuture
3945import monix .reactive .MulticastStrategy
4046import monix .reactive .Observable
4147import xsbti .compile .CompileAnalysis
4248import xsbti .compile .MiniSetup
4349import xsbti .compile .PreviousResult
4450
45- import java .nio .file .Path
46-
4751object CompileTask {
4852 private implicit val logContext : DebugFilter = DebugFilter .Compilation
53+ private val compilationCounter = new AtomicInteger (0 )
54+ private val cleanUpTasks = new ConcurrentLinkedQueue [AbsolutePath ]()
4955
5056 def compile [UseSiteLogger <: Logger ](
5157 state : State ,
@@ -57,6 +63,8 @@ object CompileTask {
5763 store : CompileClientStore ,
5864 rawLogger : UseSiteLogger
5965 ): Task [State ] = Task .defer {
66+ compilationCounter.incrementAndGet()
67+
6068 import bloop .data .ClientInfo
6169 import bloop .internal .build .BuildInfo
6270 val originUri = state.build.origin
@@ -335,16 +343,15 @@ object CompileTask {
335343 o
336344 )
337345 }
338-
339346 val client = state.client
340347 CompileGraph
341348 .traverse(dag, client, store, bestEffortAllowed, setup, compile, tracer)
342349 .flatMap { pdag =>
343350 val partialResults = Dag .dfs(pdag, mode = Dag .PreOrder )
344351 val finalResults = partialResults.map(r => PartialCompileResult .toFinalResult(r))
345352 Task .gatherUnordered(finalResults).map(_.flatten).flatMap { results =>
346- val cleanUpTasksToRunInBackground =
347- markUnusedClassesDirAndCollectCleanUpTasks (results, state, tracer, rawLogger)
353+ val makrUnusedDirectoriesTask =
354+ markUnusedClassesDir (results, state, tracer, rawLogger)
348355
349356 val failures = results.flatMap {
350357 case FinalNormalCompileResult (p, results) =>
@@ -389,7 +396,14 @@ object CompileTask {
389396 }
390397
391398 // Schedule to run clean-up tasks in the background
392- runIOTasksInParallel(cleanUpTasksToRunInBackground)
399+ runIOTasksInParallel(
400+ makrUnusedDirectoriesTask,
401+ runOnFinish = cleanupIfNoCompilationRunningTask(
402+ compilationCounter.decrementAndGet(),
403+ tracer,
404+ rawLogger
405+ )
406+ )
393407
394408 val runningTasksRequiredForCorrectness = Task .sequence {
395409 results.flatMap {
@@ -409,6 +423,7 @@ object CompileTask {
409423 }
410424 }
411425 }
426+
412427 }
413428
414429 case class ConfiguredCompilation (scalacOptions : List [String ])
@@ -445,14 +460,14 @@ object CompileTask {
445460 }
446461 }
447462
448- private def markUnusedClassesDirAndCollectCleanUpTasks (
463+ private def markUnusedClassesDir (
449464 results : List [FinalCompileResult ],
450465 previousState : State ,
451466 tracer : BraveTracer ,
452467 logger : Logger
453468 ): List [Task [Unit ]] =
454469 tracer.trace(" markUnusedClassesDirAndCollectCleanUpTasks" ) { _ =>
455- val cleanUpTasksToSpawnInBackground = mutable.ListBuffer [Task [Unit ]]()
470+ val markDeleteTasks = mutable.ListBuffer [Task [Unit ]]()
456471 results.foreach { finalResult =>
457472 val resultBundle = finalResult.result
458473 val newSuccessful = resultBundle.successful
@@ -464,36 +479,40 @@ object CompileTask {
464479 case _ => None
465480 }
466481 val populateNewProductsTask = newSuccessful.map(_.populatingProducts).getOrElse(Task .unit)
467- val cleanUpPreviousLastSuccessful = resultBundle.previous match {
482+ val markDeletePreviousLastSuccessful = resultBundle.previous match {
468483 case None => populateNewProductsTask
469484 case Some (previousSuccessful) =>
470485 for {
471486 _ <- previousSuccessful.populatingProducts
472487 _ <- populateNewProductsTask
473- _ <- cleanUpPreviousResult (
488+ toDelete = previousDirectoriesToCleanup (
474489 previousSuccessful,
475490 previousResult,
476491 compilerResult,
477492 tracer,
478493 logger
479494 )
495+ _ = toDelete.foreach(cleanUpTasks.add)
480496 } yield ()
481497 }
482498
483- cleanUpTasksToSpawnInBackground .+= (cleanUpPreviousLastSuccessful )
499+ markDeleteTasks .+= (markDeletePreviousLastSuccessful )
484500 }
485501
486- cleanUpTasksToSpawnInBackground .toList
502+ markDeleteTasks .toList
487503 }
488504
489505 def runIOTasksInParallel [T ](
490506 tasks : Traversable [Task [T ]],
491- parallelUnits : Int = Runtime .getRuntime().availableProcessors()
507+ parallelUnits : Int = Runtime .getRuntime().availableProcessors(),
508+ runOnFinish : Task [Unit ]
492509 ): Unit = {
493510 val aggregatedTask = Task .sequence(
494511 tasks.toList.grouped(parallelUnits).map(group => Task .gatherUnordered(group)).toList
495512 )
496- aggregatedTask.map(_ => ()).runAsync(ExecutionContext .ioScheduler)
513+ aggregatedTask
514+ .flatMap(_ => runOnFinish)
515+ .runAsync(ExecutionContext .ioScheduler)
497516 ()
498517 }
499518
@@ -514,15 +533,14 @@ object CompileTask {
514533 * superseeded by the new classes directory generated during a successful
515534 * compile.
516535 */
517- private def cleanUpPreviousResult (
536+ private def previousDirectoriesToCleanup (
518537 previousSuccessful : LastSuccessfulResult ,
519538 previousResult : Option [Compiler .Result ],
520539 compilerResult : Compiler .Result ,
521540 tracer : BraveTracer ,
522541 logger : Logger
523- ): Task [ Unit ] = tracer.trace(" clean up previous result" ) { implicit tracer =>
542+ ): List [ AbsolutePath ] = tracer.trace(" clean up previous result" ) { _ =>
524543 val previousClassesDir = previousSuccessful.classesDir
525- val currentlyUsedCounter = previousSuccessful.counterForClassesDir.decrementAndGet(1 )
526544
527545 val previousReadOnlyToDelete = compilerResult match {
528546 case Success (_, products, _, _, isNoOp, _, _) =>
@@ -532,11 +550,6 @@ object CompileTask {
532550 } else if (CompileOutPaths .hasEmptyClassesDir(previousClassesDir)) {
533551 logger.debug(s " Skipping delete of empty classes dir ${previousClassesDir}" )
534552 None
535- } else if (currentlyUsedCounter != 0 ) {
536- logger.debug(
537- s " Skipping delete of $previousClassesDir, counter is $currentlyUsedCounter"
538- )
539- None
540553 } else {
541554 val newClassesDir = products.newClassesDir
542555 logger.debug(s " Scheduling to delete ${previousClassesDir} superseded by $newClassesDir" )
@@ -566,28 +579,36 @@ object CompileTask {
566579 case _ => None
567580 }
568581
569- def deleteOrphanDir (orphanDir : Option [AbsolutePath ])(implicit
570- tracer : BraveTracer
571- ): Task [Unit ] = {
572- tracer.trace(" delete orphan dir" ) { _ =>
573- orphanDir match {
574- case None => Task .unit
575- case Some (classesDir) =>
576- Task .eval {
577- logger.debug(s " Deleting contents of orphan dir $classesDir" )
578- BloopPaths .delete(classesDir)
579- }.asyncBoundary
582+ List (
583+ previousReadOnlyToDelete,
584+ previousBestEffortToDelete
585+ ).flatten
586+
587+ }
588+
589+ def cleanupIfNoCompilationRunningTask (
590+ counter : Int ,
591+ tracer : BraveTracer ,
592+ logger : Logger
593+ ): Task [Unit ] = {
594+ Task {
595+ if (counter == 0 ) {
596+ tracer.trace(" delete orphan directories" ) { _ =>
597+ val allDeleteDirectories = new mutable.ListBuffer [AbsolutePath ]()
598+ while (cleanUpTasks.size() > 0 ) allDeleteDirectories += cleanUpTasks.poll()
599+ val allDeleteTasks = allDeleteDirectories
600+ .result()
601+ .map(classesDir => {
602+ Task .eval {
603+ logger.debug(s " Deleting contents of orphan dir $classesDir : ${classesDir.exists}" )
604+ BloopPaths .delete(classesDir)
605+ }.asyncBoundary
606+ })
607+ Task .gatherUnordered(allDeleteTasks).map(_ => ())
580608 }
609+ } else {
610+ Task .unit
581611 }
582- }
583-
584- Task
585- .gatherUnordered(
586- List (
587- deleteOrphanDir(previousReadOnlyToDelete),
588- deleteOrphanDir(previousBestEffortToDelete)
589- )
590- )
591- .map(_ => ())
612+ }.flatten
592613 }
593614}
0 commit comments