Partial rebind - using new explicit BrooklynObjectManagementMode
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/3f7d7508 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/3f7d7508 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/3f7d7508 Branch: refs/heads/master Commit: 3f7d7508e125d751933dc40914d72441ce27381e Parents: 0fb0c63 Author: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Authored: Tue Feb 3 12:48:22 2015 +0000 Committer: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Committed: Fri Feb 6 22:12:13 2015 +0000 ---------------------------------------------------------------------- .../rebind/InitialFullRebindIteration.java | 7 +- .../brooklyn/entity/rebind/RebindIteration.java | 75 ++++++++++- .../entity/rebind/RebindManagerImpl.java | 44 ------- .../ha/HighAvailabilityManagerImpl.java | 8 +- .../internal/BrooklynObjectManagerInternal.java | 37 ++++++ .../internal/EntityManagementSupport.java | 2 +- .../internal/EntityManagerInternal.java | 15 +-- .../management/internal/LocalEntityManager.java | 41 +++--- .../internal/LocalLocationManager.java | 49 ++++--- .../internal/LocationManagerInternal.java | 14 +- .../internal/ManagementTransitionInfo.java | 131 +++++++++++++++---- 11 files changed, 275 insertions(+), 148 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java index 9b08392..e416bbc 100644 --- a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java +++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java @@ -33,6 +33,7 @@ import brooklyn.management.ha.ManagementNodeState; import brooklyn.management.internal.EntityManagerInternal; import brooklyn.management.internal.LocationManagerInternal; import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; +import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode; import brooklyn.mementos.BrooklynMementoPersister; import brooklyn.util.text.Strings; @@ -113,7 +114,8 @@ public class InitialFullRebindIteration extends RebindIteration { if (!oldLocations.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, "Destroying unused locations on rebind: "+oldLocations); for (String oldLocationId: oldLocations) { - locationManager.unmanage(locationManager.getLocation(oldLocationId), ManagementTransitionMode.REBINDING_DESTROYED); + locationManager.unmanage(locationManager.getLocation(oldLocationId), ManagementTransitionMode.guessing( + BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT)); } } @@ -123,7 +125,8 @@ public class InitialFullRebindIteration extends RebindIteration { if (!oldEntities.isEmpty()) BrooklynLogging.log(LOG, overwritingMaster ? BrooklynLogging.LoggingLevel.WARN : BrooklynLogging.LoggingLevel.DEBUG, "Destroying unused entities on rebind: "+oldEntities); for (String oldEntityId: oldEntities) { - entityManager.unmanage(entityManager.getEntity(oldEntityId), ManagementTransitionMode.REBINDING_DESTROYED); + entityManager.unmanage(entityManager.getEntity(oldEntityId), ManagementTransitionMode.guessing( + BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT)); } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java index b4288c7..d786571 100644 --- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java +++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java @@ -63,10 +63,12 @@ import brooklyn.location.basic.AbstractLocation; import brooklyn.location.basic.LocationInternal; import brooklyn.management.classloading.BrooklynClassLoadingContext; import brooklyn.management.ha.ManagementNodeState; +import brooklyn.management.internal.BrooklynObjectManagerInternal; import brooklyn.management.internal.EntityManagerInternal; import brooklyn.management.internal.LocationManagerInternal; import brooklyn.management.internal.ManagementContextInternal; import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; +import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode; import brooklyn.mementos.BrooklynMemento; import brooklyn.mementos.BrooklynMementoManifest; import brooklyn.mementos.BrooklynMementoManifest.EntityMementoManifest; @@ -600,8 +602,7 @@ public abstract class RebindIteration { LocationManagerInternal locationManager = (LocationManagerInternal)managementContext.getLocationManager(); Set<String> oldLocations = Sets.newLinkedHashSet(locationManager.getLocationIds()); for (Location location: rebindContext.getLocations()) { - ManagementTransitionMode oldMode = locationManager.getLastManagementTransitionMode(location.getId()); - locationManager.setManagementTransitionMode(location, RebindManagerImpl.computeMode(managementContext, location, oldMode, rebindContext.isReadOnly(location), isRebindingActiveAgain()) ); + ManagementTransitionMode oldMode = updateTransitionMode(locationManager, location); if (oldMode!=null) oldLocations.remove(location.getId()); } @@ -623,8 +624,7 @@ public abstract class RebindIteration { EntityManagerInternal entityManager = (EntityManagerInternal)managementContext.getEntityManager(); Set<String> oldEntities = Sets.newLinkedHashSet(entityManager.getEntityIds()); for (Entity entity: rebindContext.getEntities()) { - ManagementTransitionMode oldMode = entityManager.getLastManagementTransitionMode(entity.getId()); - entityManager.setManagementTransitionMode(entity, RebindManagerImpl.computeMode(managementContext, entity, oldMode, rebindContext.isReadOnly(entity), isRebindingActiveAgain()) ); + ManagementTransitionMode oldMode = updateTransitionMode(entityManager, entity); if (oldMode!=null) oldEntities.remove(entity.getId()); } @@ -649,6 +649,73 @@ public abstract class RebindIteration { this.applications = apps; } + private <T extends BrooklynObject> ManagementTransitionMode updateTransitionMode(BrooklynObjectManagerInternal<T> boManager, T bo) { + ManagementTransitionMode oldTransitionMode = boManager.getLastManagementTransitionMode(bo.getId()); + +// boManager.setManagementTransitionMode(bo, +// RebindManagerImpl.computeMode(managementContext, bo, oldMode, rebindContext.isReadOnly(bo), isRebindingActiveAgain()) ); + +// isRebindingActiveAgain(); + + ManagementTransitionMode newTransitionMode; + Boolean isNowReadOnly = rebindContext.isReadOnly(bo); + BrooklynObjectManagementMode modeBefore, modeAfter; + if (oldTransitionMode==null) { + modeBefore = BrooklynObjectManagementMode.UNMANAGED_PERSISTED; +// // not previously known +// if (Boolean.TRUE.equals(isNowReadOnly)) { +// newMode = ManagementTransitionMode.REBINDING_READONLY; +// } else { +// // TODO is this needed? +// return ManagementTransitionMode.REBINDING_CREATING; +// } + } else { + modeBefore = oldTransitionMode.getModeAfter(); + } + + if (isRebindingActiveAgain()) { + Preconditions.checkState(!Boolean.FALSE.equals(isNowReadOnly)); + Preconditions.checkState(modeBefore==BrooklynObjectManagementMode.MANAGED_PRIMARY); + modeAfter = BrooklynObjectManagementMode.MANAGED_PRIMARY; + } else if (isNowReadOnly) { + modeAfter = BrooklynObjectManagementMode.LOADED_READ_ONLY; + } else { + modeAfter = BrooklynObjectManagementMode.MANAGED_PRIMARY; + } + newTransitionMode = ManagementTransitionMode.transitioning(modeBefore, modeAfter); + + boManager.setManagementTransitionMode(bo, newTransitionMode); + + // XXX old logic, from RebindManagerImpl.computeMode, for reference: +// if (wasReadOnly==null) { +// // not known +// if (Boolean.TRUE.equals(isNowReadOnly)) return ManagementTransitionMode.REBINDING_READONLY; +// else { +// // TODO is this needed? +// return ManagementTransitionMode.REBINDING_CREATING; +// } +// } else { +// if (isRebindingActiveAgain) { +// if (wasReadOnly || isNowReadOnly) +// throw new IllegalStateException("Cannot be rebinding again to something where read-only before/after is "+wasReadOnly+"/"+isNowReadOnly); +// return ManagementTransitionMode.REBINDING_ACTIVE_AGAIN; +// } else if (wasReadOnly && isNowReadOnly) +// return ManagementTransitionMode.REBINDING_READONLY; +// else if (wasReadOnly) +// return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY; +// else if (isNowReadOnly) +// return ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY; +// else { +// if (isRebindingActiveAgain) +// // for the most part we handle this correctly, although there may be leaks; see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion +// LOG.warn("Node "+(mgmt!=null ? mgmt.getManagementNodeId() : null)+" rebinding as master when already master (discouraged, may have stale references); for: "+item); +// return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY; +// } +// } + + return oldTransitionMode; + } + protected abstract boolean isRebindingActiveAgain(); protected Collection<String> getMementoRootEntities() { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java index 608f75c..9e30f7e 100644 --- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java +++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java @@ -45,13 +45,11 @@ import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMod import brooklyn.entity.rebind.persister.PersistenceActivityMetrics; import brooklyn.internal.BrooklynFeatureEnablement; import brooklyn.management.ExecutionContext; -import brooklyn.management.ManagementContext; import brooklyn.management.Task; import brooklyn.management.ha.HighAvailabilityManagerImpl; import brooklyn.management.ha.ManagementNodeState; import brooklyn.management.ha.MementoCopyMode; import brooklyn.management.internal.ManagementContextInternal; -import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; import brooklyn.mementos.BrooklynMementoPersister; import brooklyn.mementos.BrooklynMementoRawData; import brooklyn.mementos.TreeNode; @@ -533,48 +531,6 @@ public class RebindManagerImpl implements RebindManager { return iteration.getApplications(); } - @Deprecated /** @deprecated since 0.7.0, use method with more args */ - static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, ManagementTransitionMode oldMode, boolean isNowReadOnly) { - return computeMode(mgmt, item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly, false); - } - - @Deprecated /** @deprecated since 0.7.0, use method with more args */ - static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, Boolean wasReadOnly, boolean isNowReadOnly) { - return computeMode(mgmt, item, wasReadOnly, isNowReadOnly, false); - } - - static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, ManagementTransitionMode oldMode, boolean isNowReadOnly, boolean isRebindingActiveAgain) { - return computeMode(mgmt, item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly, isRebindingActiveAgain); - } - - static ManagementTransitionMode computeMode(ManagementContext mgmt, BrooklynObject item, Boolean wasReadOnly, boolean isNowReadOnly, boolean isRebindingActiveAgain) { - if (wasReadOnly==null) { - // not known - if (Boolean.TRUE.equals(isNowReadOnly)) return ManagementTransitionMode.REBINDING_READONLY; - else { - // TODO is this needed? - return ManagementTransitionMode.REBINDING_CREATING; - } - } else { - if (isRebindingActiveAgain) { - if (wasReadOnly || isNowReadOnly) - throw new IllegalStateException("Cannot be rebinding again to something where read-only before/after is "+wasReadOnly+"/"+isNowReadOnly); - return ManagementTransitionMode.REBINDING_ACTIVE_AGAIN; - } else if (wasReadOnly && isNowReadOnly) - return ManagementTransitionMode.REBINDING_READONLY; - else if (wasReadOnly) - return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY; - else if (isNowReadOnly) - return ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY; - else { - if (isRebindingActiveAgain) - // for the most part we handle this correctly, although there may be leaks; see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion - LOG.warn("Node "+(mgmt!=null ? mgmt.getManagementNodeId() : null)+" rebinding as master when already master (discouraged, may have stale references); for: "+item); - return ManagementTransitionMode.REBINDING_BECOMING_PRIMARY; - } - } - } - /** * Sorts the map of nodes, so that a node's parent is guaranteed to come before that node * (unless the parent is missing). http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java index dda9e19..bf8c390 100644 --- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java +++ b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java @@ -58,6 +58,7 @@ import brooklyn.management.internal.LocalEntityManager; import brooklyn.management.internal.LocationManagerInternal; import brooklyn.management.internal.ManagementContextInternal; import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; +import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode; import brooklyn.util.collections.MutableList; import brooklyn.util.collections.MutableMap; import brooklyn.util.exceptions.Exceptions; @@ -499,7 +500,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager { // could perhaps promote standby items on some transitions; but for now we stop the old read-only and re-load them // TODO ideally there'd be an incremental rebind as well as an incremental persist managementContext.getRebindManager().stopReadOnly(); - clearManagedItems(ManagementTransitionMode.REBINDING_DESTROYED); + clearManagedItems(ManagementTransitionMode.transitioning(BrooklynObjectManagementMode.LOADED_READ_ONLY, BrooklynObjectManagementMode.UNMANAGED_PERSISTED)); } } @@ -841,7 +842,10 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager { } boolean wasMaster = (getInternalNodeState() == ManagementNodeState.MASTER); if (wasMaster) backupOnDemotionIfNeeded(); - ManagementTransitionMode mode = (wasMaster ? ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY : ManagementTransitionMode.REBINDING_DESTROYED); + // TODO target may be RO ? + ManagementTransitionMode mode = ManagementTransitionMode.transitioning( + wasMaster ? BrooklynObjectManagementMode.MANAGED_PRIMARY : BrooklynObjectManagementMode.LOADED_READ_ONLY, + BrooklynObjectManagementMode.UNMANAGED_PERSISTED); nodeStateTransitionComplete = false; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java new file mode 100644 index 0000000..912e84b --- /dev/null +++ b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package brooklyn.management.internal; + +import brooklyn.basic.BrooklynObject; +import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; + +public interface BrooklynObjectManagerInternal<T extends BrooklynObject> { + + ManagementTransitionMode getLastManagementTransitionMode(String itemId); + void setManagementTransitionMode(T item, ManagementTransitionMode mode); + + /** + * Begins management for the given rebinded root, recursively; + * if rebinding as a read-only copy, {@link #setReadOnly(T, boolean)} should be called prior to this. + */ + void manageRebindedRoot(T item); + + void unmanage(final T e, final ManagementTransitionMode info); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java index fa5de94..4bea56e 100644 --- a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java +++ b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java @@ -296,7 +296,7 @@ public class EntityManagementSupport { // TODO framework stopping events - no more sensors, executions, etc // (elaborate or remove ^^^ ? -AH, Sept 2014) - if (!isReadOnly()) { + if (!isReadOnly() && info.getMode().isDestroying()) { // if we support remote parent of local child, the following call will need to be properly remoted if (entity.getParent()!=null) entity.getParent().removeChild(entity.getProxyIfAvailable()); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java b/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java index e134b23..d3a619b 100644 --- a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java +++ b/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java @@ -20,26 +20,13 @@ package brooklyn.management.internal; import brooklyn.entity.Application; import brooklyn.entity.Entity; -import brooklyn.location.Location; import brooklyn.management.EntityManager; -import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; -public interface EntityManagerInternal extends EntityManager { +public interface EntityManagerInternal extends EntityManager, BrooklynObjectManagerInternal<Entity> { /** gets all entities currently known to the application, including entities that are not yet managed */ Iterable<Entity> getAllEntitiesInApplication(Application application); public Iterable<String> getEntityIds(); - ManagementTransitionMode getLastManagementTransitionMode(String itemId); - void setManagementTransitionMode(Entity item, ManagementTransitionMode mode); - - /** - * Begins management for the given rebinded root, recursively; - * if rebinding as a read-only copy, {@link #setReadOnly(Location, boolean)} should be called prior to this. - */ - void manageRebindedRoot(Entity item); - - void unmanage(final Entity e, final ManagementTransitionMode info); - } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java index 87d8a3a..aada104 100644 --- a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java +++ b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java @@ -55,6 +55,7 @@ import brooklyn.internal.storage.BrooklynStorage; import brooklyn.management.AccessController; import brooklyn.management.Task; import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; +import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode; import brooklyn.policy.Enricher; import brooklyn.policy.EnricherSpec; import brooklyn.policy.Policy; @@ -269,7 +270,7 @@ public class LocalEntityManager implements EntityManagerInternal { new Exception("source of duplicate management of "+e)); return; } - manageRecursive(e, ManagementTransitionMode.CREATING); + manageRecursive(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY)); } @Override @@ -306,7 +307,7 @@ public class LocalEntityManager implements EntityManagerInternal { } if (it.getManagementSupport().isDeployed()) { - if (mode==ManagementTransitionMode.CREATING) { + if (mode.wasNotLoaded()) { // silently bail out return false; } else { @@ -341,7 +342,7 @@ public class LocalEntityManager implements EntityManagerInternal { @Override public void unmanage(final Entity e) { - unmanage(e, ManagementTransitionMode.DESTROYING); + unmanage(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT)); } public void unmanage(final Entity e, final ManagementTransitionMode mode) { @@ -354,23 +355,23 @@ public class LocalEntityManager implements EntityManagerInternal { if (hasBeenReplaced) { // we are unmanaging an old instance after having replaced it - // (called from manage(...) + // don't unmanage or even clear its fields, because there might be references to it - if (mode==ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY) { - // when migrating away, these all need to be called + if (mode.wasReadOnly()) { + // if coming *from* read only; nothing needed + } else { + if (!mode.wasPrimary()) { + log.warn("Unexpected mode "+mode+" for unmanage-replace "+e+" (applying anyway)"); + } + // migrating away or in-place active partial rebind: ((EntityInternal)e).getManagementSupport().onManagementStopping(info); stopTasks(e); ((EntityInternal)e).getManagementSupport().onManagementStopped(info); - } else { - // should be coming *from* read only; nothing needed - if (!mode.wasReadOnly()) { - log.warn("Should not be unmanaging "+e+" in mode "+mode+"; ignoring"); - } } // do not remove from maps below, bail out now return; - } else if (mode==ManagementTransitionMode.REBINDING_DESTROYED) { + } else if (mode.wasReadOnly() && mode.isDestroying()) { // we are unmanaging an instance (secondary) for which the primary has been destroyed elsewhere ((EntityInternal)e).getManagementSupport().onManagementStopping(info); unmanageNonRecursive(e); @@ -379,7 +380,7 @@ public class LocalEntityManager implements EntityManagerInternal { managementContext.getRebindManager().getChangeListener().onUnmanaged(e); if (managementContext.getGarbageCollector() != null) managementContext.getGarbageCollector().onUnmanaged(e); - } else if (mode==ManagementTransitionMode.DESTROYING) { + } else if (mode.wasPrimary() && mode.isDestroying()) { // we are unmanaging an instance either because it is being destroyed (primary), // or due to an explicit call (shutting down all things, read-only and primary); // in either case, should be recursive @@ -545,11 +546,11 @@ public class LocalEntityManager implements EntityManagerInternal { Object old = preManagedEntitiesById.put(e.getId(), realE); preRegisteredEntitiesById.remove(e.getId()); - if (old!=null && mode==ManagementTransitionMode.CREATING) { + if (old!=null && mode.wasNotLoaded()) { if (old.equals(e)) { - log.warn("{} redundant call to pre-start management of entity {}; ignoring", this, e); + log.warn("{} redundant call to pre-start management of entity {}, mode {}; ignoring", new Object[] { this, e, mode }); } else { - throw new IllegalStateException("call to pre-manage entity "+e+" but different entity "+old+" already known under that id at "+this); + throw new IllegalStateException("call to pre-manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this); } return false; } else { @@ -567,11 +568,11 @@ public class LocalEntityManager implements EntityManagerInternal { private synchronized boolean manageNonRecursive(Entity e, ManagementTransitionMode mode) { Entity old = entitiesById.get(e.getId()); - if (old!=null && mode==ManagementTransitionMode.CREATING) { + if (old!=null && mode.wasNotLoaded()) { if (old.equals(e)) { log.warn("{} redundant call to start management of entity {}; ignoring", this, e); } else { - throw new IllegalStateException("call to manage entity "+e+" but different entity "+old+" already known under that id at "+this); + throw new IllegalStateException("call to manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this); } return false; } @@ -583,8 +584,8 @@ public class LocalEntityManager implements EntityManagerInternal { Entity oldProxy = entityProxiesById.get(e.getId()); Entity proxyE; if (oldProxy!=null) { - if (mode==ManagementTransitionMode.CREATING) { - throw new IllegalStateException("call to manage entity "+e+" but already had proxy "+oldProxy+" already known under that id at "+this); + if (mode.wasNotLoaded()) { + throw new IllegalStateException("call to manage entity "+e+" from unloaded state ("+mode+") but already had proxy "+oldProxy+" already known under that id at "+this); } // make the old proxy point at this new delegate // (some other tricks done in the call below) http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java b/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java index b873363..fec09f4 100644 --- a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java +++ b/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java @@ -43,6 +43,7 @@ import brooklyn.location.basic.LocationInternal; import brooklyn.management.AccessController; import brooklyn.management.entitlement.Entitlements; import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; +import brooklyn.management.internal.ManagementTransitionInfo.BrooklynObjectManagementMode; import brooklyn.util.config.ConfigBag; import brooklyn.util.exceptions.Exceptions; import brooklyn.util.exceptions.RuntimeInterruptedException; @@ -194,7 +195,7 @@ public class LocalLocationManager implements LocationManagerInternal { log.warn("Parent location "+parent+" of "+loc+" is not managed; attempting to manage it (in future this may be disallowed)"); return manage(parent); } else { - return manageRecursive(loc, ManagementTransitionMode.CREATING); + return manageRecursive(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY)); } } @@ -214,7 +215,7 @@ public class LocalLocationManager implements LocationManagerInternal { long count = LOCATION_CNT.incrementAndGet(); if (log.isDebugEnabled()) { String msg = "Managing location " + loc + " ("+initialMode+"), from " + Tasks.current()+" / "+Entitlements.getEntitlementContext(); - LoggingLevel level = (initialMode==ManagementTransitionMode.REBINDING_READONLY ? LoggingLevel.TRACE : LoggingLevel.DEBUG); + LoggingLevel level = (!initialMode.wasNotLoaded() || initialMode.isReadOnly() ? LoggingLevel.TRACE : LoggingLevel.DEBUG); if (count % 100 == 0) { // include trace periodically in case we get leaks or too much location management BrooklynLogging.log(log, level, @@ -231,7 +232,7 @@ public class LocalLocationManager implements LocationManagerInternal { } if (it.isManaged()) { - if (mode==ManagementTransitionMode.CREATING) { + if (mode.wasNotLoaded()) { // silently bail out return false; } else { @@ -242,9 +243,9 @@ public class LocalLocationManager implements LocationManagerInternal { boolean result = manageNonRecursive(it, mode); if (result) { it.setManagementContext(managementContext); - if (!mode.isReadOnly()) { + if (mode.isPrimary()) { it.onManagementStarted(); - if (!mode.wasReadOnly() && !mode.isRebinding()) { + if (mode.isCreating()) { // Never record event on rebind; this isn't the location (e.g. the VM) being "created" // so don't tell listeners that. // TODO The location-event history should be persisted; currently it is lost on @@ -261,7 +262,7 @@ public class LocalLocationManager implements LocationManagerInternal { @Override public void unmanage(final Location loc) { - unmanage(loc, ManagementTransitionMode.DESTROYING); + unmanage(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT)); } public void unmanage(final Location loc, final ManagementTransitionMode mode) { @@ -274,26 +275,34 @@ public class LocalLocationManager implements LocationManagerInternal { if (hasBeenReplaced) { // we are unmanaging an old instance after having replaced it; // don't unmanage or even clear its fields, because there might be references to it - if (mode==ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY) { - // when migrating away, these all need to be called + + if (mode.wasReadOnly()) { + // if coming *from* read only; nothing needed + } else { + if (!mode.wasPrimary()) { + log.warn("Unexpected mode "+mode+" for unmanage-replace "+loc+" (applying anyway)"); + } + // migrating away or in-place active partial rebind: managementContext.getRebindManager().getChangeListener().onUnmanaged(loc); if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc); - } else { - // should be coming *from* read only; nothing needed - if (!mode.wasReadOnly()) - log.warn("Should not be unmanaging "+loc+" in mode "+mode+"; ignoring"); } // do not remove from maps below, bail out now return; - } else if (mode==ManagementTransitionMode.REBINDING_DESTROYED || mode==ManagementTransitionMode.REBINDING_NO_LONGER_PRIMARY) { + } else if ((mode.isReadOnly() && mode.wasPrimary()) || (mode.isDestroying() && mode.wasReadOnly())) { + if (mode.isReadOnly() && mode.wasPrimary()) { + // TODO shouldn't this fall into "hasBeenReplaced" above? + log.debug("Unmanaging on demotion: "+loc+" ("+mode+")"); + } // we are unmanaging an instance whose primary management is elsewhere (either we were secondary, or we are being demoted) unmanageNonRecursiveRemoveFromRecords(loc, mode); managementContext.getRebindManager().getChangeListener().onUnmanaged(loc); if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc); unmanageNonRecursiveClearItsFields(loc, mode); + } else if (mode.isDestroying()) { + + // TODO isUnloading??? - } else if (mode==ManagementTransitionMode.DESTROYING) { // we are unmanaging an instance either because it is being destroyed (primary), // or due to an explicit call (shutting down all things, read-only and primary); // in either case, should be recursive @@ -307,11 +316,11 @@ public class LocalLocationManager implements LocationManagerInternal { if (mode==null) { // ad hoc creation e.g. tests log.debug("Missing transition mode for "+it+" when unmanaging; assuming primary/destroying"); - mode = ManagementTransitionMode.DESTROYING; + mode = ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT); } - if (!mode.isReadOnly()) it.onManagementStopped(); + if (mode.wasPrimary()) it.onManagementStopped(); managementContext.getRebindManager().getChangeListener().onUnmanaged(it); - if (!mode.isReadOnly()) recordLocationEvent(it, Lifecycle.DESTROYED); + if (mode.isDestroying()) recordLocationEvent(it, Lifecycle.DESTROYED); if (managementContext.gc != null) managementContext.gc.onUnmanaged(it); } unmanageNonRecursiveClearItsFields(loc, mode); @@ -319,6 +328,8 @@ public class LocalLocationManager implements LocationManagerInternal { } }); } else { + // what about to unmanaged_persisted? + log.warn("Invalid mode for unmanage: "+mode+" on "+loc+" (ignoring)"); } @@ -367,7 +378,7 @@ public class LocalLocationManager implements LocationManagerInternal { locationTypes.put(loc.getId(), loc.getClass().getName()); - if (old!=null && mode==ManagementTransitionMode.CREATING) { + if (old!=null && mode.wasNotLoaded()) { if (old.equals(loc)) { log.warn("{} redundant call to start management of location {}", this, loc); } else { @@ -386,7 +397,7 @@ public class LocalLocationManager implements LocationManagerInternal { @SuppressWarnings({ "rawtypes", "unchecked" }) private synchronized void unmanageNonRecursiveClearItsFields(Location loc, ManagementTransitionMode mode) { - if (mode==ManagementTransitionMode.DESTROYING) { + if (mode.isDestroying()) { ((AbstractLocation)loc).setParent(null, true); Location parent = ((AbstractLocation)loc).getParent(); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java b/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java index 96e2ff3..4b0d959 100644 --- a/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java +++ b/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java @@ -20,21 +20,9 @@ package brooklyn.management.internal; import brooklyn.location.Location; import brooklyn.management.LocationManager; -import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode; -public interface LocationManagerInternal extends LocationManager { +public interface LocationManagerInternal extends LocationManager, BrooklynObjectManagerInternal<Location> { public Iterable<String> getLocationIds(); - ManagementTransitionMode getLastManagementTransitionMode(String itemId); - void setManagementTransitionMode(Location item, ManagementTransitionMode mode); - - /** - * Begins management for the given rebinded root, recursively; - * if rebinding as a read-only copy, {@link #setReadOnly(Location, boolean)} should be called prior to this. - */ - void manageRebindedRoot(Location item); - - void unmanage(final Location item, final ManagementTransitionMode info); - } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3f7d7508/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java index 6d27fed..6ce714a 100644 --- a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java +++ b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java @@ -20,46 +20,119 @@ package brooklyn.management.internal; import brooklyn.management.ManagementContext; +import com.google.common.base.Preconditions; + public class ManagementTransitionInfo { final ManagementContext mgmtContext; - final ManagementTransitionMode mode; - /** true if this transition is an entity whose mastering is migrating from one node to another; - * false if the brooklyn mgmt plane is just starting managing of this entity for the very first time - */ + public enum BrooklynObjectManagementMode { + /** item does not exist, not in memory, nor persisted (e.g. creating for first time, or finally destroying) */ + NONEXISTENT, + /** item exists or existed elsewhere, i.e. there is persisted state, but is not loaded here */ + UNMANAGED_PERSISTED, + + @Deprecated /** @deprecated marking places where we aren't sure */ + /** either nonexistent or persisted by unmanaged */ + ITEM_UNKNOWN, + + /** item is loaded but read-only (ie not actively managed here) */ + LOADED_READ_ONLY, + /** item is actively managed here */ + MANAGED_PRIMARY + } + + public static class ManagementTransitionMode { - public enum ManagementTransitionMode { - /** Item is being created fresh, for the first time */ - CREATING(false, false, false), - /** Item is being destroyed / stopping permanently */ - DESTROYING(false, false, false), + // XXX +//- CREATING(false, false, false), +//- DESTROYING(false, false, false), +//- REBINDING_READONLY(true, true, true), +//- REBINDING_NO_LONGER_PRIMARY(false, true, true), +//- REBINDING_BECOMING_PRIMARY(true, false, true), +//- REBINDING_DESTROYED(true, true, true), +//- REBINDING_CREATING(false, false, true); +//- +//- private final boolean wasReadOnly; +//- private final boolean isReadOnly; +//- private final boolean isRebinding; + +// /** Item is being created fresh, for the first time */ +// CREATING(NONEXISTENT, MANAGED_PRIMARY), +// /** Item is being destroyed / stopping permanently */ +// DESTROYING(MANAGED_PRIMARY, NONEXISTENT), +// +// /** Item is being mirrored (refreshed or created) here from a serialized/specified state */ +// REBINDING_READONLY(LOADED_READ_ONLY, LOADED_READ_ONLY), +// /** Item management is stopping here, going elsewhere */ +// REBINDING_NO_LONGER_PRIMARY(MANAGED_PRIMARY, LOADED_READ_ONLY), +// /** Item management is starting here, having previously been running elsewhere */ +// REBINDING_BECOMING_PRIMARY(LOADED_READ_ONLY, MANAGED_PRIMARY), +// /** Item has been managed here, and is being re-read for management again (e.g. applying a transform) */ +// REBINDING_ACTIVE_AGAIN(MANAGED_PRIMARY, MANAGED_PRIMARY), +// /** Item was being mirrored but has now been destroyed */ +// REBINDING_DESTROYED(LOADED_READ_ONLY, NONEXISTENT), +// +// /** Item management is starting here, from persisted state */ +// REBINDING_CREATING(NodeManagementMode.UNMANAGED_PERSISTED, NodeManagementMode.MANAGED_PRIMARY); - /** Item is being mirrored (or refreshed) here from a serialized/specified state */ - REBINDING_READONLY(true, true, true), - /** Item management is stopping here, going elsewhere */ - REBINDING_NO_LONGER_PRIMARY(false, true, true), - /** Item management is starting here, having previously been running elsewhere */ - REBINDING_BECOMING_PRIMARY(true, false, true), - /** Item was being mirrored but has now been destroyed */ - REBINDING_DESTROYED(true, true, true), - /** Item management is starting here, where not sure what previous running state was */ - REBINDING_CREATING(false, false, true); +// private final static ManagementTransitionTargetMode NONE = ManagementTransitionTargetMode.NONE; + private final BrooklynObjectManagementMode modeBefore, modeAfter; + + private ManagementTransitionMode(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) { + this.modeBefore = modeBefore; + this.modeAfter = modeAfter; + } - private final boolean wasReadOnly; - private final boolean isReadOnly; - private final boolean isRebinding; + public static ManagementTransitionMode transitioning(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) { + return new ManagementTransitionMode(Preconditions.checkNotNull(modeBefore, "modeBefore"), Preconditions.checkNotNull(modeAfter, "modeAfter")); + } + + @Deprecated /** @deprecated marking places where we aren't sure */ + public static ManagementTransitionMode guessing(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) { + return transitioning(modeBefore, modeAfter); + } + + public BrooklynObjectManagementMode getModeBefore() { + return modeBefore; + } - ManagementTransitionMode(boolean wasReadOnly, boolean isReadOnly, boolean isRebinding) { - this.wasReadOnly = wasReadOnly; - this.isReadOnly = isReadOnly; - this.isRebinding = isRebinding; + public BrooklynObjectManagementMode getModeAfter() { + return modeAfter; } - public boolean wasReadOnly() { return wasReadOnly; } - public boolean isReadOnly() { return isReadOnly; } - public boolean isRebinding() { return isRebinding; } + public boolean wasNotLoaded() { + return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT || getModeBefore()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED || getModeBefore()==BrooklynObjectManagementMode.ITEM_UNKNOWN; + } + + public boolean isNoLongerLoaded() { + return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT || getModeAfter()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED || getModeAfter()==BrooklynObjectManagementMode.ITEM_UNKNOWN; + } + + public boolean wasPrimary() { + return getModeBefore()==BrooklynObjectManagementMode.MANAGED_PRIMARY; + } + + public boolean isPrimary() { + return getModeAfter()==BrooklynObjectManagementMode.MANAGED_PRIMARY; + } + + public boolean wasReadOnly() { + return getModeBefore()==BrooklynObjectManagementMode.LOADED_READ_ONLY; + } + + public boolean isReadOnly() { + return getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY; + } + + public boolean isDestroying() { + return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT; + } + + public boolean isCreating() { + return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT; + } } public ManagementTransitionInfo(ManagementContext mgmtContext, ManagementTransitionMode mode) {