X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fblueprint%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fblueprint%2Fext%2FAbstractDependentComponentFactoryMetadata.java;h=81b374d9fa43420af3a4f2fa670e702d0280d314;hb=12e42f62ff55faf841cc4f18759b5e08a26f104f;hp=bdcc1ee86d261d6c05e9c4c2cc60f0875988ea68;hpb=ef7700c56ee56a5c79444c95199f5b016de22de9;p=controller.git diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/AbstractDependentComponentFactoryMetadata.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/AbstractDependentComponentFactoryMetadata.java index bdcc1ee86d..81b374d9fa 100644 --- a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/AbstractDependentComponentFactoryMetadata.java +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/AbstractDependentComponentFactoryMetadata.java @@ -13,30 +13,41 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; import org.apache.aries.blueprint.di.AbstractRecipe; import org.apache.aries.blueprint.di.ExecutionContext; import org.apache.aries.blueprint.di.Recipe; import org.apache.aries.blueprint.ext.DependentComponentFactoryMetadata; import org.apache.aries.blueprint.services.ExtendedBlueprintContainer; +import org.opendaylight.controller.blueprint.BlueprintContainerRestartService; +import org.osgi.framework.ServiceReference; import org.osgi.service.blueprint.container.ComponentDefinitionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** + * Abstract base class for a DependentComponentFactoryMetadata implementation. + * * @author Thomas Pantelis */ abstract class AbstractDependentComponentFactoryMetadata implements DependentComponentFactoryMetadata { - private final Logger log = LoggerFactory.getLogger(getClass()); + final Logger log = LoggerFactory.getLogger(getClass()); private final String id; private final AtomicBoolean started = new AtomicBoolean(); private final AtomicBoolean satisfied = new AtomicBoolean(); + private final AtomicBoolean restarting = new AtomicBoolean(); + @GuardedBy("serviceRecipes") private final List serviceRecipes = new ArrayList<>(); private volatile ExtendedBlueprintContainer container; private volatile SatisfactionCallback satisfactionCallback; private volatile String failureMessage; - private volatile String dependendencyDesc; + private volatile Throwable failureCause; + private volatile String dependencyDesc; + @GuardedBy("serviceRecipes") + private boolean stoppedServiceRecipes; - protected AbstractDependentComponentFactoryMetadata(String id) { + protected AbstractDependentComponentFactoryMetadata(final String id) { this.id = Preconditions.checkNotNull(id); } @@ -57,7 +68,7 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom @Override public String getDependencyDescriptor() { - return dependendencyDesc; + return dependencyDesc; } @Override @@ -65,14 +76,17 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom return satisfied.get(); } - protected abstract void startTracking(); + protected void setFailureMessage(final String failureMessage) { + setFailure(failureMessage, null); + } - protected void setFailureMessage(String failureMessage) { + protected void setFailure(final String failureMessage, final Throwable failureCause) { this.failureMessage = failureMessage; + this.failureCause = failureCause; } - protected void setDependendencyDesc(String dependendencyDesc) { - this.dependendencyDesc = dependendencyDesc; + protected void setDependencyDesc(final String dependencyDesc) { + this.dependencyDesc = dependencyDesc; } protected final ExtendedBlueprintContainer container() { @@ -80,34 +94,46 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom } protected void setSatisfied() { - satisfied.set(true); - satisfactionCallback.notifyChanged(); + if (satisfied.compareAndSet(false, true)) { + satisfactionCallback.notifyChanged(); + } } - protected void retrieveService(String name, Class interfaceClass, Consumer onServiceRetrieved) { - StaticServiceReferenceRecipe recipe = new StaticServiceReferenceRecipe(getId() + "-" + name, - container, interfaceClass.getName()); - setDependendencyDesc(recipe.getOsgiFilter()); - serviceRecipes.add(recipe); + protected void retrieveService(final String name, final Class interfaceClass, + final Consumer onServiceRetrieved) { + retrieveService(name, interfaceClass.getName(), onServiceRetrieved); + } - recipe.startTracking(onServiceRetrieved); + protected void retrieveService(final String name, final String interfaceName, + final Consumer onServiceRetrieved) { + synchronized (serviceRecipes) { + if (stoppedServiceRecipes) { + return; + } + + StaticServiceReferenceRecipe recipe = new StaticServiceReferenceRecipe(getId() + "-" + name, + container, interfaceName); + setDependencyDesc(recipe.getOsgiFilter()); + serviceRecipes.add(recipe); + + recipe.startTracking(onServiceRetrieved); + } } protected final String logName() { - return (container != null ? container.getBundleContext().getBundle().getSymbolicName() : "") + - " (" + id + ")"; + return (container != null ? container.getBundleContext().getBundle().getSymbolicName() : "") + " (" + id + ")"; } @Override - public void init(ExtendedBlueprintContainer container) { - this.container = container; + public void init(final ExtendedBlueprintContainer newContainer) { + this.container = newContainer; log.debug("{}: In init", logName()); } protected void onCreate() throws ComponentDefinitionException { - if(failureMessage != null) { - throw new ComponentDefinitionException(failureMessage); + if (failureMessage != null) { + throw new ComponentDefinitionException(failureMessage, failureCause); } // The following code is a bit odd so requires some explanation. A little background... If a bean @@ -137,7 +163,7 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom executionContext.removePartialObject(id); Recipe myRecipe = executionContext.getRecipe(id); - if(myRecipe instanceof AbstractRecipe) { + if (myRecipe instanceof AbstractRecipe) { log.debug("{}: setPrototype to false", logName()); ((AbstractRecipe)myRecipe).setPrototype(false); } else { @@ -145,15 +171,17 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom } } + protected abstract void startTracking(); + @Override - public final void startTracking(final SatisfactionCallback satisfactionCallback) { - if(!started.compareAndSet(false, true)) { + public final void startTracking(final SatisfactionCallback newSatisfactionCallback) { + if (!started.compareAndSet(false, true)) { return; } log.debug("{}: In startTracking", logName()); - this.satisfactionCallback = satisfactionCallback; + this.satisfactionCallback = newSatisfactionCallback; startTracking(); } @@ -166,17 +194,57 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom } @Override - public void destroy(Object instance) { + public void destroy(final Object instance) { log.debug("{}: In destroy", logName()); stopServiceRecipes(); } private void stopServiceRecipes() { - for(StaticServiceReferenceRecipe recipe: serviceRecipes) { - recipe.stop(); + synchronized (serviceRecipes) { + stoppedServiceRecipes = true; + for (StaticServiceReferenceRecipe recipe: serviceRecipes) { + recipe.stop(); + } + + serviceRecipes.clear(); + } + } + + protected void restartContainer() { + if (restarting.compareAndSet(false, true)) { + BlueprintContainerRestartService restartService = getOSGiService(BlueprintContainerRestartService.class); + if (restartService != null) { + log.debug("{}: Restarting container", logName()); + restartService.restartContainerAndDependents(container().getBundleContext().getBundle()); + } + } + } + + @SuppressWarnings("unchecked") + @Nullable + protected T getOSGiService(final Class serviceInterface) { + try { + ServiceReference serviceReference = + container().getBundleContext().getServiceReference(serviceInterface); + if (serviceReference == null) { + log.warn("{}: {} reference not found", logName(), serviceInterface.getSimpleName()); + return null; + } + + T service = (T)container().getService(serviceReference); + if (service == null) { + // This could happen on shutdown if the service was already unregistered so we log as debug. + log.debug("{}: {} was not found", logName(), serviceInterface.getSimpleName()); + } + + return service; + } catch (final IllegalStateException e) { + // This is thrown if the BundleContext is no longer valid which is possible on shutdown so we + // log as debug. + log.debug("{}: Error obtaining {}", logName(), serviceInterface.getSimpleName(), e); } - serviceRecipes.clear(); + return null; } }