import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
+import javax.annotation.Nullable;
import org.apache.aries.blueprint.NamespaceHandler;
import org.apache.aries.blueprint.services.BlueprintExtenderService;
import org.apache.aries.quiesce.participant.QuiesceParticipant;
@Override
public BlueprintExtenderService addingService(
final ServiceReference<BlueprintExtenderService> reference) {
- blueprintExtenderService = reference.getBundle().getBundleContext().getService(reference);
- bundleTracker.open();
-
- context.addBundleListener(BlueprintBundleTracker.this);
-
- LOG.debug("Got BlueprintExtenderService");
-
- restartService.setBlueprintExtenderService(blueprintExtenderService);
-
- blueprintContainerRestartReg = context.registerService(
- BlueprintContainerRestartService.class.getName(), restartService, new Hashtable<>());
-
- return blueprintExtenderService;
+ return onBlueprintExtenderServiceAdded(reference);
}
@Override
@Override
public QuiesceParticipant addingService(
final ServiceReference<QuiesceParticipant> reference) {
- quiesceParticipant = reference.getBundle().getBundleContext().getService(reference);
-
- LOG.debug("Got QuiesceParticipant");
-
- restartService.setQuiesceParticipant(quiesceParticipant);
-
- return quiesceParticipant;
+ return onQuiesceParticipantAdded(reference);
}
@Override
quiesceParticipantTracker.open();
}
+ private QuiesceParticipant onQuiesceParticipantAdded(final ServiceReference<QuiesceParticipant> reference) {
+ quiesceParticipant = reference.getBundle().getBundleContext().getService(reference);
+
+ LOG.debug("Got QuiesceParticipant");
+
+ restartService.setQuiesceParticipant(quiesceParticipant);
+
+ return quiesceParticipant;
+ }
+
+ private BlueprintExtenderService onBlueprintExtenderServiceAdded(
+ final ServiceReference<BlueprintExtenderService> reference) {
+ blueprintExtenderService = reference.getBundle().getBundleContext().getService(reference);
+ bundleTracker.open();
+
+ bundleContext.addBundleListener(BlueprintBundleTracker.this);
+
+ LOG.debug("Got BlueprintExtenderService");
+
+ restartService.setBlueprintExtenderService(blueprintExtenderService);
+
+ blueprintContainerRestartReg = bundleContext.registerService(
+ BlueprintContainerRestartService.class.getName(), restartService, new Hashtable<>());
+
+ return blueprintExtenderService;
+ }
+
private void registerNamespaceHandler(final BundleContext context) {
Dictionary<String, Object> props = new Hashtable<>();
props.put("osgi.service.blueprint.namespace", OpendaylightNamespaceHandler.NAMESPACE_1_0_0);
if (EventConstants.TOPIC_CREATED.equals(event.getTopic())) {
LOG.info("Blueprint container for bundle {} was successfully created",
event.getProperty(EventConstants.BUNDLE));
- } else if (EventConstants.TOPIC_FAILURE.equals(event.getTopic())) {
- // If the container timed out waiting for dependencies, we'll destroy it and start it again. This
- // is indicated via a non-null DEPENDENCIES property containing the missing dependencies. The
- // default timeout is 5 min and ideally we would set this to infinite but the timeout can only
- // be set at the bundle level in the manifest - there's no way to set it globally.
- if (event.getProperty(EventConstants.DEPENDENCIES) != null) {
- Bundle bundle = (Bundle) event.getProperty(EventConstants.BUNDLE);
-
- List<Object> paths = findBlueprintPaths(bundle);
- if (!paths.isEmpty()) {
- LOG.warn("Blueprint container for bundle {} timed out waiting for dependencies - restarting it",
- event.getProperty(EventConstants.BUNDLE));
-
- restartService.restartContainer(bundle, paths);
- }
+ return;
+ }
+
+ // If the container timed out waiting for dependencies, we'll destroy it and start it again. This
+ // is indicated via a non-null DEPENDENCIES property containing the missing dependencies. The
+ // default timeout is 5 min and ideally we would set this to infinite but the timeout can only
+ // be set at the bundle level in the manifest - there's no way to set it globally.
+ if (EventConstants.TOPIC_FAILURE.equals(event.getTopic())
+ && event.getProperty(EventConstants.DEPENDENCIES) != null) {
+ Bundle bundle = (Bundle) event.getProperty(EventConstants.BUNDLE);
+
+ List<Object> paths = findBlueprintPaths(bundle);
+ if (!paths.isEmpty()) {
+ LOG.warn("Blueprint container for bundle {} timed out waiting for dependencies - restarting it",
+ event.getProperty(EventConstants.BUNDLE));
+
+ restartService.restartContainer(bundle, paths);
}
}
}
// ID, we're picking the bundle that was (likely) started after all the others and thus
// is likely the safest to destroy at this point.
- ServiceReference<?> ref = null;
- for (Bundle bundle : containerBundles) {
- ServiceReference<?>[] references = bundle.getRegisteredServices();
- if (references == null) {
- continue;
- }
-
- for (ServiceReference<?> reference : references) {
- // We did check the service usage above but it's possible the usage has changed since
- // then,
- if (getServiceUsage(reference) == 0) {
- continue;
- }
-
- // Choose 'reference' if it has a lower service ranking or, if the rankings are equal
- // which is usually the case, if it has a higher service ID. For the latter the < 0
- // check looks backwards but that's how ServiceReference#compareTo is documented to work.
- if (ref == null || reference.compareTo(ref) < 0) {
- LOG.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
- ref = reference;
- }
- }
- }
-
- if (ref != null) {
- bundlesToDestroy.add(ref.getBundle());
+ Bundle bundle = findBundleWithHighestUsedServiceId(containerBundles);
+ if (bundle != null) {
+ bundlesToDestroy.add(bundle);
}
LOG.debug("Selected bundle {} for destroy (lowest ranking service or highest service ID)",
return bundlesToDestroy;
}
+ @Nullable
+ private Bundle findBundleWithHighestUsedServiceId(final Collection<Bundle> containerBundles) {
+ ServiceReference<?> highestServiceRef = null;
+ for (Bundle bundle : containerBundles) {
+ ServiceReference<?>[] references = bundle.getRegisteredServices();
+ if (references == null) {
+ continue;
+ }
+
+ for (ServiceReference<?> reference : references) {
+ // We did check the service usage previously but it's possible the usage has changed since then.
+ if (getServiceUsage(reference) == 0) {
+ continue;
+ }
+
+ // Choose 'reference' if it has a lower service ranking or, if the rankings are equal
+ // which is usually the case, if it has a higher service ID. For the latter the < 0
+ // check looks backwards but that's how ServiceReference#compareTo is documented to work.
+ if (highestServiceRef == null || reference.compareTo(highestServiceRef) < 0) {
+ LOG.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
+ highestServiceRef = reference;
+ }
+ }
+ }
+
+ return highestServiceRef == null ? null : highestServiceRef.getBundle();
+ }
+
private static int getServiceUsage(final ServiceReference<?> ref) {
Bundle[] usingBundles = ref.getUsingBundles();
return usingBundles != null ? usingBundles.length : 0;