add overridable doStart to DynamicClusterImpl to facilitate custom logic to happen before expected state is RUNNING; add a service problem-indicator rather than setting expected state ON_FIRE, and wait for queued tasks to complete before setting expected state RUNNING
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f51710de Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f51710de Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f51710de Branch: refs/heads/master Commit: f51710de18fad107810670d569cbe6efc68aa56f Parents: df971f5 Author: Alex Heneveld <[email protected]> Authored: Thu Aug 28 22:32:12 2014 -0400 Committer: Alex Heneveld <[email protected]> Committed: Mon Sep 1 17:07:01 2014 +0100 ---------------------------------------------------------------------- .../entity/group/DynamicClusterImpl.java | 126 ++++++++++--------- 1 file changed, 67 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f51710de/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java index 553d453..647ddaa 100644 --- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java +++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java @@ -36,12 +36,12 @@ import org.slf4j.LoggerFactory; import brooklyn.entity.Entity; import brooklyn.entity.basic.AbstractGroupImpl; -import brooklyn.entity.basic.Attributes; import brooklyn.entity.basic.Entities; import brooklyn.entity.basic.EntityFactory; import brooklyn.entity.basic.EntityFactoryForLocation; import brooklyn.entity.basic.Lifecycle; import brooklyn.entity.basic.QuorumCheck.QuorumChecks; +import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic; import brooklyn.entity.basic.ServiceStateLogic; import brooklyn.entity.effector.Effectors; import brooklyn.entity.proxying.EntitySpec; @@ -260,71 +260,79 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus } ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); + ServiceProblemsLogic.clearProblemsIndicator(this, START); try { - if (isQuarantineEnabled()) { - QuarantineGroup quarantineGroup = getAttribute(QUARANTINE_GROUP); - if (quarantineGroup==null || !Entities.isManaged(quarantineGroup)) { - quarantineGroup = addChild(EntitySpec.create(QuarantineGroup.class).displayName("quarantine")); - Entities.manage(quarantineGroup); - setAttribute(QUARANTINE_GROUP, quarantineGroup); - } - } - - int initialSize = getConfig(INITIAL_SIZE).intValue(); - int initialQuorumSize = getInitialQuorumSize(); + doStart(); + DynamicTasks.waitForLast(); + + } catch (Exception e) { + ServiceProblemsLogic.updateProblemsIndicator(this, START, "start failed with error: "+e); + throw Exceptions.propagate(e); + } finally { + ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); + } + } - try { - resize(initialSize); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - // apart from logging, ignore problems here; we extract them below - LOG.debug("Error resizing "+this+" to size "+initialSize+" (collecting and handling): "+e, e); + protected void doStart() { + if (isQuarantineEnabled()) { + QuarantineGroup quarantineGroup = getAttribute(QUARANTINE_GROUP); + if (quarantineGroup==null || !Entities.isManaged(quarantineGroup)) { + quarantineGroup = addChild(EntitySpec.create(QuarantineGroup.class).displayName("quarantine")); + Entities.manage(quarantineGroup); + setAttribute(QUARANTINE_GROUP, quarantineGroup); } + } - Iterable<Task<?>> failed = Tasks.failed(Tasks.children(Tasks.current())); - Iterator<Task<?>> fi = failed.iterator(); - boolean noFailed=true, severalFailed=false; - if (fi.hasNext()) { - noFailed = false; - fi.next(); - if (fi.hasNext()) - severalFailed = true; - } + int initialSize = getConfig(INITIAL_SIZE).intValue(); + int initialQuorumSize = getInitialQuorumSize(); - int currentSize = getCurrentSize().intValue(); - if (currentSize < initialQuorumSize) { - String message; - if (currentSize == 0 && !noFailed) { - if (severalFailed) - message = "All nodes in cluster "+this+" failed"; - else - message = "Node in cluster "+this+" failed"; - } else { - message = "On start of cluster " + this + ", failed to get to initial size of " + initialSize - + "; size is " + getCurrentSize() - + (initialQuorumSize != initialSize ? " (initial quorum size is " + initialQuorumSize + ")" : ""); - } - Throwable firstError = Tasks.getError(Maybe.next(failed.iterator()).orNull()); - if (firstError!=null) { - if (severalFailed) - message += "; first failure is: "+Exceptions.collapseText(firstError); - else - message += ": "+Exceptions.collapseText(firstError); - } - throw new IllegalStateException(message, firstError); - } else if (currentSize < initialSize) { - LOG.warn( - "On start of cluster {}, size {} reached initial minimum quorum size of {} but did not reach desired size {}; continuing", - new Object[] { this, currentSize, initialQuorumSize, initialSize }); + try { + resize(initialSize); + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + // apart from logging, ignore problems here; we extract them below + LOG.debug("Error resizing "+this+" to size "+initialSize+" (collecting and handling): "+e, e); + } + + Iterable<Task<?>> failed = Tasks.failed(Tasks.children(Tasks.current())); + Iterator<Task<?>> fi = failed.iterator(); + boolean noFailed=true, severalFailed=false; + if (fi.hasNext()) { + noFailed = false; + fi.next(); + if (fi.hasNext()) + severalFailed = true; + } + + int currentSize = getCurrentSize().intValue(); + if (currentSize < initialQuorumSize) { + String message; + if (currentSize == 0 && !noFailed) { + if (severalFailed) + message = "All nodes in cluster "+this+" failed"; + else + message = "Node in cluster "+this+" failed"; + } else { + message = "On start of cluster " + this + ", failed to get to initial size of " + initialSize + + "; size is " + getCurrentSize() + + (initialQuorumSize != initialSize ? " (initial quorum size is " + initialQuorumSize + ")" : ""); } - - for (Policy it : getPolicies()) { - it.resume(); + Throwable firstError = Tasks.getError(Maybe.next(failed.iterator()).orNull()); + if (firstError!=null) { + if (severalFailed) + message += "; first failure is: "+Exceptions.collapseText(firstError); + else + message += ": "+Exceptions.collapseText(firstError); } - ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); - } catch (Exception e) { - ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); - throw Exceptions.propagate(e); + throw new IllegalStateException(message, firstError); + } else if (currentSize < initialSize) { + LOG.warn( + "On start of cluster {}, size {} reached initial minimum quorum size of {} but did not reach desired size {}; continuing", + new Object[] { this, currentSize, initialQuorumSize, initialSize }); + } + + for (Policy it : getPolicies()) { + it.resume(); } }
