protected void setActualState()

in policy/src/main/java/org/apache/brooklyn/policy/ha/ServiceFailureDetector.java [177:281]


    protected void setActualState(Maybe<Lifecycle> state) {
        long now = System.currentTimeMillis();

        synchronized (mutex) {
            if (state.orNull() == Lifecycle.ON_FIRE) {
                if (config().get(LAST_PUBLISHED) == LastPublished.FAILED) {
                    if (currentRecoveryStartTime != null) {
                        if (LOG.isDebugEnabled()) LOG.debug("{} health-check for {}, component was recovering, now failing: {}", new Object[] {this, entity, getExplanation(state)});
                        currentRecoveryStartTime = null;
                        publishEntityRecoveredTime = null;
                    } else {
                        if (LOG.isTraceEnabled()) LOG.trace("{} health-check for {}, component still failed: {}", new Object[] {this, entity, getExplanation(state)});
                    }
                } else {
                    if (firstUpTime == null && getConfig(ENTITY_FAILED_ONLY_IF_PREVIOUSLY_UP)) {
                        // suppress; won't publish
                    } else if (currentFailureStartTime == null) {
                        if (LOG.isDebugEnabled()) LOG.debug("{} health-check for {}, component now failing: {}", new Object[] {this, entity, getExplanation(state)});
                        currentFailureStartTime = now;
                        publishEntityFailedTime = currentFailureStartTime + getConfig(ENTITY_FAILED_STABILIZATION_DELAY).toMilliseconds();
                    } else {
                        if (LOG.isTraceEnabled()) LOG.trace("{} health-check for {}, component continuing failing: {}", new Object[] {this, entity, getExplanation(state)});
                    }
                }
                if (setEntityOnFireTime == null) {
                    setEntityOnFireTime = now + getConfig(SERVICE_ON_FIRE_STABILIZATION_DELAY).toMilliseconds();
                }
                currentRecoveryStartTime = null;
                publishEntityRecoveredTime = null;
                
            } else if (state.orNull() == Lifecycle.RUNNING) {
                if (config().get(LAST_PUBLISHED) == LastPublished.FAILED) {
                    if (currentRecoveryStartTime == null) {
                        if (LOG.isDebugEnabled()) LOG.debug("{} health-check for {}, component now recovering: {}", new Object[] {this, entity, getExplanation(state)});
                        currentRecoveryStartTime = now;
                        publishEntityRecoveredTime = currentRecoveryStartTime + getConfig(ENTITY_RECOVERED_STABILIZATION_DELAY).toMilliseconds();
                    } else {
                        if (LOG.isTraceEnabled()) LOG.trace("{} health-check for {}, component continuing recovering: {}", new Object[] {this, entity, getExplanation(state)});
                    }
                } else {
                    if (currentFailureStartTime != null) {
                        if (LOG.isDebugEnabled()) LOG.debug("{} health-check for {}, component was failing, now healthy: {}", new Object[] {this, entity, getExplanation(state)});
                    } else {
                        if (LOG.isTraceEnabled()) LOG.trace("{} health-check for {}, component still healthy: {}", new Object[] {this, entity, getExplanation(state)});
                    }
                }
                currentFailureStartTime = null;
                publishEntityFailedTime = null;
                setEntityOnFireTime = null;
                
            } else {
                if (LOG.isTraceEnabled()) LOG.trace("{} health-check for {}, in unconfirmed sate: {}", new Object[] {this, entity, getExplanation(state)});
            }

            long recomputeIn = Long.MAX_VALUE; // For whether to call recomputeAfterDelay
            
            if (publishEntityFailedTime != null) {
                long delayBeforeCheck = publishEntityFailedTime - now;
                if (delayBeforeCheck<=0) {
                    if (LOG.isDebugEnabled()) LOG.debug("{} publishing failed (state={}; currentFailureStartTime={}; now={}", 
                            new Object[] {this, state, Time.makeDateString(currentFailureStartTime), Time.makeDateString(now)});
                    Duration republishDelay = getConfig(ENTITY_FAILED_REPUBLISH_TIME);
                    if (republishDelay == null) {
                        publishEntityFailedTime = null;
                    } else {
                        publishEntityFailedTime = now + republishDelay.toMilliseconds();
                        recomputeIn = Math.min(recomputeIn, republishDelay.toMilliseconds());
                    }
                    emit(HASensors.ENTITY_FAILED, new HASensors.FailureDescriptor(entity, getFailureDescription(now)));
                    config().set(LAST_PUBLISHED, LastPublished.FAILED);
                } else {
                    recomputeIn = Math.min(recomputeIn, delayBeforeCheck);
                }
            } else if (publishEntityRecoveredTime != null) {
                long delayBeforeCheck = publishEntityRecoveredTime - now;
                if (delayBeforeCheck<=0) {
                    if (LOG.isDebugEnabled()) LOG.debug("{} publishing recovered (state={}; currentRecoveryStartTime={}; now={}", 
                            new Object[] {this, state, Time.makeDateString(currentRecoveryStartTime), Time.makeDateString(now)});
                    publishEntityRecoveredTime = null;
                    emit(HASensors.ENTITY_RECOVERED, new HASensors.FailureDescriptor(entity, null));
                    config().set(LAST_PUBLISHED, LastPublished.RECOVERED);
                } else {
                    recomputeIn = Math.min(recomputeIn, delayBeforeCheck);
                }
            }
            
            if (setEntityOnFireTime != null) {
                long delayBeforeCheck = setEntityOnFireTime - now;
                if (delayBeforeCheck<=0) {
                    if (LOG.isDebugEnabled()) LOG.debug("{} setting on-fire, now that deferred period has passed (state={})", 
                            new Object[] {this, state});
                    setEntityOnFireTime = null;
                    super.setActualState(state);
                } else {
                    recomputeIn = Math.min(recomputeIn, delayBeforeCheck);
                }
            } else {
                super.setActualState(state);
            }
            
            if (recomputeIn < Long.MAX_VALUE) {
                recomputeAfterDelay(recomputeIn);
            }
        }
    }