/* * 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 org.apache.brooklyn.core.mgmt.rebind; import java.util.Set; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.mgmt.ha.ManagementNodeState; import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler; import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister; import org.apache.brooklyn.core.BrooklynLogging; import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.mgmt.internal.BrooklynObjectManagementMode; import org.apache.brooklyn.core.mgmt.internal.EntityManagerInternal; import org.apache.brooklyn.core.mgmt.internal.LocationManagerInternal; import org.apache.brooklyn.core.mgmt.internal.ManagementTransitionMode; import org.apache.brooklyn.core.mgmt.persist.PersistenceActivityMetrics; import org.apache.brooklyn.util.text.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; /** * Does an un-bind (if necessary) and re-bind for a subset of items. */ public class InitialFullRebindIteration extends RebindIteration { private static final Logger LOG = LoggerFactory.getLogger(InitialFullRebindIteration.class); public InitialFullRebindIteration(RebindManagerImpl rebindManager, ManagementNodeState mode, ClassLoader classLoader, RebindExceptionHandler exceptionHandler, Semaphore rebindActive, AtomicInteger readOnlyRebindCount, PersistenceActivityMetrics rebindMetrics, BrooklynMementoPersister persistenceStoreAccess ) { super(rebindManager, mode, classLoader, exceptionHandler, rebindActive, readOnlyRebindCount, rebindMetrics, persistenceStoreAccess); } @Override protected boolean isRebindingActiveAgain() { return false; } @Override protected void doRun() throws Exception { LOG.debug("Rebinding ("+mode+ (readOnlyRebindCount.get()>Integer.MIN_VALUE ? ", iteration "+readOnlyRebindCount : "")+ ") from "+rebindManager.getPersister().getBackingStoreDescription()+"..."); super.doRun(); } @Override protected void loadManifestFiles() throws Exception { checkEnteringPhase(1); Preconditions.checkState(mementoRawData==null, "Memento raw data should not yet be set when calling this"); mementoRawData = persistenceStoreAccess.loadMementoRawData(exceptionHandler); preprocessManifestFiles(); if (!isEmpty) { if (!ManagementNodeState.isHotProxy(mode) || readOnlyRebindCount.get()==1) { LOG.info("Rebinding from "+getPersister().getBackingStoreDescription()+" for "+Strings.toLowerCase(Strings.toString(mode))+" "+managementContext.getManagementNodeId()+"..."); } } else { if (!ManagementNodeState.isHotProxy(mode)) { LOG.info("Rebind check: no existing state; will persist new items to "+getPersister().getBackingStoreDescription()); } } if (!ManagementNodeState.isHotProxy(mode)) { if (!managementContext.getEntityManager().getEntities().isEmpty() || !managementContext.getLocationManager().getLocations().isEmpty()) { // this is discouraged if we were already master Entity anEntity = Iterables.getFirst(managementContext.getEntityManager().getEntities(), null); if (anEntity!=null && !((EntityInternal)anEntity).getManagementSupport().isReadOnly()) { // NB: there is some complexity which can happen in this situation; "initial-full" rebind really expected everything is being // initially bound from persisted state, and completely so; "active-partial" is much more forgiving. // one big difference is in behaviour of management: it is recursive for most situations, and initial-full assumes recursive, // but primary-primary is *not* recursive; // as a result some "new" entities created during rebind might be left unmanaged; they should get GC'd, // but it's possible the new entity impl or even a new proxy could leak. // see HighAvailabilityManagerInMemoryTest.testLocationsStillManagedCorrectlyAfterDoublePromotion // (i've plugged the known such leaks, but still something to watch out for); -Alex 2015-02 overwritingMaster = true; LOG.warn("Rebind requested for "+mode+" node "+managementContext.getManagementNodeId()+" " + "when it already has active state; discouraged, " + "will likely overwrite: "+managementContext.getEntityManager().getEntities()+" and "+managementContext.getLocationManager().getLocations()+" and more"); } } } } @Override protected void cleanupOldLocations(Set<String> oldLocations) { LocationManagerInternal locationManager = (LocationManagerInternal)managementContext.getLocationManager(); 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.guessing( BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT)); } } @Override protected void cleanupOldEntities(Set<String> oldEntities) { EntityManagerInternal entityManager = (EntityManagerInternal)managementContext.getEntityManager(); 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.guessing( BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT)); } } }