/** * Schedules an execution of a task. * * @since 1.311 * @return null if this task is already in the queue and therefore the add operation was no-op. * Otherwise indicates the {@link WaitingItem} object added, although the nature of the queue * is that such {@link Item} only captures the state of the item at a particular moment, and * by the time you inspect the object, some of its information can be already stale. * <p>That said, one can still look at {@link WaitingItem#future}, {@link WaitingItem#id}, * etc. */ private synchronized WaitingItem scheduleInternal(Task p, int quietPeriod, List<Action> actions) { WaitingItem added = null; List<Item> items = getItems(p); Calendar due = new GregorianCalendar(); due.add(Calendar.SECOND, quietPeriod); List<Item> duplicatesInQueue = new ArrayList<Item>(); for (Item item : items) { boolean shouldScheduleItem = false; for (Action action : item.getActions()) { if (action instanceof QueueAction) shouldScheduleItem |= ((QueueAction) action).shouldSchedule(actions); } for (Action action : actions) { if (action instanceof QueueAction) { shouldScheduleItem |= ((QueueAction) action).shouldSchedule(item.getActions()); } } if (!shouldScheduleItem) { duplicatesInQueue.add(item); } } if (duplicatesInQueue.size() == 0) { LOGGER.fine(p.getFullDisplayName() + " added to queue"); // put the item in the queue waitingList.add(added = new WaitingItem(due, p, actions)); } else { // the requested build is already queued, so will not be added List<WaitingItem> waitingDuplicates = new ArrayList<WaitingItem>(); for (Item item : duplicatesInQueue) { for (Action a : actions) { if (a instanceof FoldableAction) { ((FoldableAction) a).foldIntoExisting(item.task, item.getActions()); } } if ((item instanceof WaitingItem)) waitingDuplicates.add((WaitingItem) item); } if (duplicatesInQueue.size() == 0) { // all duplicates in the queue are already in the blocked or // buildable stage no need to requeue return null; } // TODO: avoid calling scheduleMaintenance() if none of the waiting items // actually change for (WaitingItem wi : waitingDuplicates) { if (quietPeriod <= 0) { // the user really wants to build now, and they mean NOW. // so let's pull in the timestamp if we can. if (wi.timestamp.before(due)) continue; } else { // otherwise we do the normal quiet period implementation if (wi.timestamp.after(due)) continue; // quiet period timer reset. start the period over again } // waitingList is sorted, so when we change a timestamp we need to maintain order waitingList.remove(wi); wi.timestamp = due; waitingList.add(wi); } } scheduleMaintenance(); // let an executor know that a new item is in the queue. return added; }
protected Item(Item item) { this(item.task, item.getActions(), item.id, item.future); }