if (LOG.isDebugEnabled()) {
LOG.debug("Scheduling task " + task);
}
final ExecutionVertex vertex = task.getTaskToExecute().getVertex();
synchronized (globalLock) {
// 1) === If the task has a slot sharing group, schedule with shared slots ===
SlotSharingGroup sharingUnit = task.getSlotSharingGroup();
if (sharingUnit != null) {
if (queueIfNoResource) {
throw new IllegalArgumentException("A task with a vertex sharing group was scheduled in a queued fashion.");
}
final SlotSharingGroupAssignment assignment = sharingUnit.getTaskAssignment();
final CoLocationConstraint constraint = task.getLocationConstraint();
// get a slot from the group, if the group has one for us (and can fulfill the constraint)
SubSlot slotFromGroup;
if (constraint == null) {
slotFromGroup = assignment.getSlotForTask(vertex);
}
else {
slotFromGroup = assignment.getSlotForTask(vertex, constraint);
}
AllocatedSlot newSlot = null;
// the following needs to make sure any allocated slot is released in case of an error
try {
// check whether the slot from the group is already what we want
if (slotFromGroup != null) {
// local (or unconstrained in the current group)
if (slotFromGroup.getLocality() != Locality.NON_LOCAL) {
updateLocalityCounters(slotFromGroup.getLocality());
return slotFromGroup;
}
}
final Iterable<Instance> locations = (constraint == null || constraint.isUnassigned()) ?
vertex.getPreferredLocations() : Collections.singleton(constraint.getLocation());
// get a new slot, since we could not place it into the group, or we could not place it locally
newSlot = getFreeSlotForTask(vertex, locations);
SubSlot toUse;
if (newSlot == null) {
if (slotFromGroup == null) {
// both null
if (constraint == null || constraint.isUnassigned()) {
throw new NoResourceAvailableException(getNumberOfAvailableInstances(), getTotalNumberOfSlots());
} else {
throw new NoResourceAvailableException("Could not allocate a slot on instance " +
constraint.getLocation() + ", as required by the co-location constraint.");
}
} else {
// got a non-local from the group, and no new one
toUse = slotFromGroup;
}
}
else if (slotFromGroup == null || newSlot.getLocality() == Locality.LOCAL) {
// new slot is preferable
if (slotFromGroup != null) {
slotFromGroup.releaseSlot();
}
if (constraint == null) {
toUse = assignment.addNewSlotWithTask(newSlot, vertex);
} else {
toUse = assignment.addNewSlotWithTask(newSlot, vertex, constraint);
}
}
else {
// both are available and usable. neither is local
newSlot.releaseSlot();
toUse = slotFromGroup;
}
// assign to the co-location hint, if we have one and it is unassigned
// if it was assigned before and the new one is not local, it is a fail
if (constraint != null) {
if (constraint.isUnassigned() || toUse.getLocality() == Locality.LOCAL) {
constraint.setSharedSlot(toUse.getSharedSlot());
} else {
// the fail
throw new NoResourceAvailableException("Could not allocate a slot on instance " +
constraint.getLocation() + ", as required by the co-location constraint.");
}
}
updateLocalityCounters(toUse.getLocality());
return toUse;
}
catch (NoResourceAvailableException e) {
throw e;
}
catch (Throwable t) {
if (slotFromGroup != null) {
slotFromGroup.releaseSlot();
}
if (newSlot != null) {
newSlot.releaseSlot();
}
ExceptionUtils.rethrow(t, "An error occurred while allocating a slot in a sharing group");
}
}
// 2) === schedule without hints and sharing ===
AllocatedSlot slot = getFreeSlotForTask(vertex, vertex.getPreferredLocations());
if (slot != null) {
updateLocalityCounters(slot.getLocality());
return slot;
}
else {