/** * This is called after reloading the allocation configuration when the scheduler is reinitilized * * <p>Checks to see whether any non-runnable applications become runnable now that the max running * apps of given queue has been changed * * <p>Runs in O(n) where n is the number of apps that are non-runnable and in the queues that went * from having no slack to having slack. */ public void updateRunnabilityOnReload() { FSParentQueue rootQueue = scheduler.getQueueManager().getRootQueue(); List<List<FSAppAttempt>> appsNowMaybeRunnable = new ArrayList<List<FSAppAttempt>>(); gatherPossiblyRunnableAppLists(rootQueue, appsNowMaybeRunnable); updateAppsRunnability(appsNowMaybeRunnable, Integer.MAX_VALUE); }
/** * Traverses the queue hierarchy under the given queue to gather all lists of non-runnable * applications. */ private void gatherPossiblyRunnableAppLists(FSQueue queue, List<List<FSAppAttempt>> appLists) { if (queue.getNumRunnableApps() < scheduler.getAllocationConfiguration().getQueueMaxApps(queue.getName())) { if (queue instanceof FSLeafQueue) { appLists.add(((FSLeafQueue) queue).getCopyOfNonRunnableAppSchedulables()); } else { for (FSQueue child : queue.getChildQueues()) { gatherPossiblyRunnableAppLists(child, appLists); } } } }
/** * Checks to see whether any other applications runnable now that the given application has been * removed from the given queue. And makes them so. * * <p>Runs in O(n log(n)) where n is the number of queues that are under the highest queue that * went from having no slack to having slack. */ public void updateRunnabilityOnAppRemoval(FSAppAttempt app, FSLeafQueue queue) { AllocationConfiguration allocConf = scheduler.getAllocationConfiguration(); // childqueueX might have no pending apps itself, but if a queue higher up // in the hierarchy parentqueueY has a maxRunningApps set, an app completion // in childqueueX could allow an app in some other distant child of // parentqueueY to become runnable. // An app removal will only possibly allow another app to become runnable if // the queue was already at its max before the removal. // Thus we find the ancestor queue highest in the tree for which the app // that was at its maxRunningApps before the removal. FSQueue highestQueueWithAppsNowRunnable = (queue.getNumRunnableApps() == allocConf.getQueueMaxApps(queue.getName()) - 1) ? queue : null; FSParentQueue parent = queue.getParent(); while (parent != null) { if (parent.getNumRunnableApps() == allocConf.getQueueMaxApps(parent.getName()) - 1) { highestQueueWithAppsNowRunnable = parent; } parent = parent.getParent(); } List<List<FSAppAttempt>> appsNowMaybeRunnable = new ArrayList<List<FSAppAttempt>>(); // Compile lists of apps which may now be runnable // We gather lists instead of building a set of all non-runnable apps so // that this whole operation can be O(number of queues) instead of // O(number of apps) if (highestQueueWithAppsNowRunnable != null) { gatherPossiblyRunnableAppLists(highestQueueWithAppsNowRunnable, appsNowMaybeRunnable); } String user = app.getUser(); Integer userNumRunning = usersNumRunnableApps.get(user); if (userNumRunning == null) { userNumRunning = 0; } if (userNumRunning == allocConf.getUserMaxApps(user) - 1) { List<FSAppAttempt> userWaitingApps = usersNonRunnableApps.get(user); if (userWaitingApps != null) { appsNowMaybeRunnable.add(userWaitingApps); } } updateAppsRunnability(appsNowMaybeRunnable, appsNowMaybeRunnable.size()); }