@@ -252,6 +252,11 @@ dbNotLocked db = do
252252 check =<< readTVar (databaseValuesLock db)
253253
254254
255+ shakeGetDatabase :: ShakeDatabase -> Database
256+ shakeGetDatabase (ShakeDatabase _ _ db) = db
257+
258+ shakeGetScheduler :: ShakeDatabase -> SchedulerState
259+ shakeGetScheduler (ShakeDatabase _ _ db) = databaseScheduler db
255260
256261getShakeQueue :: ShakeDatabase -> DBQue
257262getShakeQueue (ShakeDatabase _ _ db) = databaseQueue db
@@ -292,43 +297,9 @@ data SchedulerState = SchedulerState
292297 -- ^ Keys that are ready to run
293298 , schedulerRunningPending :: SMap. Map Key Int
294299 -- ^ Keys that are pending because they are waiting for dependencies to complete
300+ , schedulerRunningOrigins :: TVar [Key ]
295301 }
296302
297- -- dump scheduler state
298- dumpSchedulerState :: SchedulerState -> IO String
299- dumpSchedulerState SchedulerState {.. } = atomically $ do
300- -- Snapshot queues (drain then restore) to avoid side effects
301- ups <- flushTQueue schedulerUpsweepQueue
302- mapM_ (writeTQueue schedulerUpsweepQueue) ups
303-
304- ready <- flushTQueue schedulerRunningReady
305- mapM_ (writeTQueue schedulerRunningReady) ready
306-
307- -- Snapshot sets and pending map
308- dirties <- readTVar schedulerRunningDirties
309- blocked <- readTVar schedulerRunningBlocked
310- pendingPairs <- ListT. toList (SMap. listT schedulerRunningPending)
311-
312- let ppKey k = PP. pretty k
313- ppKeys ks = if null ks then PP. brackets mempty else PP. vsep (map (\ k -> PP. hsep [PP. pretty (" -" :: String ), ppKey k]) ks)
314- ppPairs xs = if null xs then PP. brackets mempty else PP. vsep (map (\ (k,c) -> PP. hsep [PP. pretty (" -" :: String ), ppKey k, PP. pretty (" :" :: String ), PP. pretty c]) xs)
315-
316- doc = PP. vsep
317- [ PP. pretty (" SchedulerState" :: String )
318- , PP. indent 2 $ PP. vsep
319- [ PP. pretty (" upsweep:" :: String ) <> PP. pretty (length ups)
320- , PP. indent 2 (ppKeys ups)
321- , PP. pretty (" ready:" :: String ) <> PP. pretty (length ready)
322- , PP. indent 2 (ppKeys ready)
323- , PP. pretty (" pending:" :: String ) <> PP. pretty (length pendingPairs)
324- , PP. indent 2 (ppPairs pendingPairs)
325- , PP. pretty (" running:" :: String ) <> PP. pretty (length (toListKeySet dirties))
326- , PP. indent 2 (ppKeys (toListKeySet dirties))
327- , PP. pretty (" blocked:" :: String ) <> PP. pretty (length (toListKeySet blocked))
328- , PP. indent 2 (ppKeys (toListKeySet blocked))
329- ]
330- ]
331- pure $ renderString (PP. layoutPretty PP. defaultLayoutOptions doc)
332303
333304
334305
@@ -487,12 +458,68 @@ instance Exception AsyncParentKill where
487458 toException = asyncExceptionToException
488459 fromException = asyncExceptionFromException
489460
461+
462+ getBlockedBy :: Key -> Database -> STM [Key ]
463+ getBlockedBy k Database {.. } = do
464+ -- Determine the last known direct dependencies of k from its stored Result
465+ mKd <- SMap. lookup k databaseValues
466+ let deps = case mKd of
467+ Nothing -> mempty
468+ Just KeyDetails {keyStatus = st} ->
469+ let mRes = getResult st
470+ in maybe mempty (getResultDepsDefault mempty . resultDeps) mRes
471+ depList = filter (/= k) (toListKeySet deps)
472+ depStatuses <- forM depList $ \ d -> SMap. lookup d databaseValues
473+ let isCleanDep = \ case
474+ Just KeyDetails {keyStatus = Clean _} -> True
475+ _ -> False
476+ blocked = (filter (not . isCleanDep . snd ) $ zip depList depStatuses)
477+ return $ fst <$> blocked
478+
479+ -- dump scheduler state
480+ dumpSchedulerState :: Database -> IO String
481+ dumpSchedulerState db@ Database {.. } = atomically $ do
482+ let SchedulerState {.. } = databaseScheduler
483+ -- Snapshot queues (drain then restore) to avoid side effects
484+ ups <- flushTQueue schedulerUpsweepQueue
485+ ready <- flushTQueue schedulerRunningReady
486+ -- Snapshot sets and pending map
487+ dirties <- readTVar schedulerRunningDirties
488+ blocked <- readTVar schedulerRunningBlocked
489+ pendingPairs <- ListT. toList (SMap. listT schedulerRunningPending)
490+ origins <- readTVar schedulerRunningOrigins
491+ runningUnblocked <- mapM (\ x ->
492+ do
493+ b <- getBlockedBy x db
494+ return (x, b)) $ toListKeySet $ dirties `differenceKeySet` blocked
495+
496+ let ppKey k = PP. pretty k
497+ ppKeys ks = if null ks then PP. brackets mempty else PP. vsep (map (\ k -> PP. hsep [PP. pretty (" -" :: String ), ppKey k]) ks)
498+ ppKeysWithDeps ks = if null ks then PP. brackets mempty else PP. vsep (map (\ (k,bs) -> PP. hsep [PP. pretty (" -" :: String ), ppKey k, PP. pretty (" blocked by:" :: String ), PP. pretty (bs)]) ks)
499+ ppPairs xs = if null xs then PP. brackets mempty else PP. vsep (map (\ (k,c) -> PP. hsep [PP. pretty (" -" :: String ), ppKey k, PP. pretty (" :" :: String ), PP. pretty c]) xs)
500+
501+ doc = PP. vsep
502+ [ PP. pretty (" SchedulerState" :: String )
503+ , PP. indent 2 $ PP. vsep
504+ [ PP. pretty (" upsweep:" :: String ) <> PP. pretty (length ups)
505+ , PP. indent 2 (ppKeys ups)
506+ , PP. pretty (" ready:" :: String ) <> PP. pretty (length ready)
507+ , PP. indent 2 (ppKeys ready)
508+ , PP. pretty (" pending:" :: String ) <> PP. pretty (length pendingPairs)
509+ , PP. indent 2 (ppPairs pendingPairs)
510+ , PP. pretty (" running:" :: String ) <> PP. pretty (length runningUnblocked)
511+ , PP. indent 2 (ppKeysWithDeps (runningUnblocked))
512+ , PP. pretty (" blocked:" :: String ) <> PP. pretty (length (toListKeySet blocked))
513+ , PP. indent 2 (ppKeys (toListKeySet $ blocked))
514+ , PP. pretty (" origins:" :: String ) <> PP. pretty (length origins)
515+ , PP. indent 2 (ppKeys origins)
516+ ]
517+ ]
518+ pure $ renderString (PP. layoutPretty PP. defaultLayoutOptions doc)
519+
490520shutDatabase :: Set (Async () ) -> Database -> IO ()
491521shutDatabase preserve db@ Database {.. } = uninterruptibleMask $ \ unmask -> do
492522 -- Dump scheduler state on shutdown for diagnostics
493- let dumpPath = " scheduler.dump"
494- dump <- dumpSchedulerState databaseScheduler
495- writeFile dumpPath dump
496523 -- wait for all threads to finish
497524 asyncs <- readTVarIO databaseThreads
498525 step <- readTVarIO databaseStep
0 commit comments