}
}
}
// find out what the avail was the last time we checked it. this may be null
Availability previous = this.inventoryManager.getAvailabilityIfKnown(resource);
AvailabilityType previousType = (null == previous) ? UNKNOWN : previous.getAvailabilityType();
AvailabilityType current = null;
// If the resource's parent is DOWN, the rules are that the resource and all of the parent's other
// descendants, must also be DOWN. So, there's no need to even ask the resource component
// for its current availability - its current avail is set to the parent avail type and that's that.
// Otherwise, checkAvail as needed.
if (deferToParent || (DOWN == parentAvailType)) {
current = parentAvailType;
++scan.numDeferToParent;
// For the DOWN parent case it's unclear to me whether we should push out the avail check time of
// the child. For now, we'll leave it alone and let the next check happen according to the
// schedule already established.
if (traceEnabled) {
LOG.trace("Gave parent availability " + parentAvailType + " to " + resource);
}
} else {
// regardless of whether the avail schedule is met, we still must check avail if isForce is true or if
// it's a full report and we don't yet have an avail for the resource.
if (!checkAvail && (isForced || (scan.isFull && null == previous))) {
checkAvail = true;
}
if (checkAvail) {
if (traceEnabled) {
LOG.trace("Now checking availability for " + resource);
}
try {
++scan.numGetAvailabilityCalls;
// if the component is started, ask what its current availability is as of right now;
// if it's not started, then assume it's down, and the next time we check,
// we'll see if it's started and check for real then - otherwise, keep assuming it's
// down (this is for the case when a plugin component can't start for whatever reason
// or is just slow to start)
if (resourceContainer.getResourceComponentState() == ResourceComponentState.STARTED) {
current = translate(resourceAvailabilityProxy.getAvailability(), previousType);
} else {
// try to start the component and then perform the avail check
this.inventoryManager.activateResource(resource, resourceContainer, false);
if (resourceContainer.getResourceComponentState() == ResourceComponentState.STARTED) {
current = translate(resourceAvailabilityProxy.getAvailability(), previousType);
} else {
current = DOWN;
}
}
if (traceEnabled) {
LOG.trace("Current availability is " + current + " for " + resource);
}
} catch (Throwable t) {
ResourceError resourceError = new ResourceError(resource, ResourceErrorType.AVAILABILITY_CHECK,
t.getLocalizedMessage(), ThrowableUtil.getStackAsString(t), System.currentTimeMillis());
this.inventoryManager.sendResourceErrorToServer(resourceError);
LOG.warn("Availability collection failed with exception on " + resource
+ ", availability will be reported as " + DOWN.name() + ", reason=" + t.getMessage());
current = DOWN;
}
} else {
current = previousType;
}
}
// Add the availability to the report if it changed from its previous state or if this is a full report.
// Update the resource container only if the avail has changed.
boolean availChanged = (UNKNOWN != current && current != previousType);
if (availChanged || scan.isFull) {
Availability availability;
if (availChanged) {
if (traceEnabled) {
LOG.trace("Availability changed for " + resource);
}
++scan.numAvailabilityChanges;
availability = this.inventoryManager.updateAvailability(resource, current);
// if the resource avail changed to UP then we must perform avail checks for all
// children, to ensure their avails are up to date. Note that if it changed to NOT UP
// then the children will just get the parent avail type and there is no avail check anyway.
if (!isForced && (UP == current)) {
if (traceEnabled) {
LOG.trace("Forcing availability check for children of " + resource);
}
isForced = true;
}
} else {
// avoid the overhead of updating the resource container, the avail type did not change
availability = new Availability(resource, current);
}
// update the report
availabilityReport.addAvailability(availability);
}