The GlobalBundleScanningSchemaServiceImpl uses a BundleTracker to get
all RESOLVED bundles. When BundleTracker#open() is called
on start(), the BundleTracker will notify addingBundles of all current
bundles that pass the state mask. The OSGi container must resolve all
bundles before activating on startup. So after open() is called we
should have all the current bundles that have yang models and a complete
SchemaContext on startup based on the installed bundles from he last run.
However I was seeing some bundles notified during open() but others notified
later. This why CDS and other components may not see a complete
SchemaContext on startup.
The problem is that GlobalBundleScanningSchemaServiceImpl is passing the
wrong state mask constants. It's referencing constants defined in
BundleEvent but the BundleTracker checks bundle.getState() which
corresponds to constants defined in Bundle. The 2 have slightly
different constants and the values differ. When I change it to use
Bundle constants, it works as expected, ie all current bundles are
notified during open() and we have a complete SchemaContext after start().
I really don't see how this worked before at all using the wrong constants.
I also noticed that start() is being called twice, once in
GlobalBundleScanningSchemaServiceImpl#createInstance and then also in
the Activator after it calls createInstance. So 2 instances of
BundleTracker were being created resulting in double the notifications.
I removed the call to start() in the Activator.
Change-Id: I8c8330f75dd1a779af186688aae4cfaee89bd43b
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
(cherry picked from commit
cd0eea4a97a6279b801074061dd64f6663e8b837)
public void start() {
checkState(context != null);
+ LOG.debug("start() starting");
listenerTracker = new ServiceTracker<>(context, SchemaContextListener.class, GlobalBundleScanningSchemaServiceImpl.this);
- bundleTracker = new BundleTracker<>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
+ bundleTracker = new BundleTracker<>(context, Bundle.RESOLVED | Bundle.STARTING |
+ Bundle.STOPPING | Bundle.ACTIVE, scanner);
bundleTracker.open();
+
+ LOG.debug("BundleTracker.open() complete");
+
listenerTracker.open();
starting = false;
tryToUpdateSchemaContext();
+
+ LOG.debug("start() complete");
}
@Override
}
if (!urls.isEmpty()) {
- LOG.debug("Loaded {} new URLs, rebuilding schema context", urls.size());
+ LOG.debug("Loaded {} new URLs from bundle {}, attempting to rebuild schema context",
+ urls.size(), bundle.getSymbolicName());
tryToUpdateSchemaContext();
}
@Override
public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Iterable<Registration> object) {
- LOG.debug("Modified bundle {} {} {}", bundle, event, object);
}
/**
}
Optional<SchemaContext> schema = contextResolver.getSchemaContext();
if(schema.isPresent()) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("Got new SchemaContext: # of modules {}", schema.get().getAllModuleIdentifiers().size());
+ }
+
updateContext(schema.get());
}
}
package org.opendaylight.controller.sal.dom.broker.osgi;
import java.util.Hashtable;
-
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl;
import org.osgi.framework.BundleActivator;
@Override
public void start(final BundleContext context) {
schemaService = GlobalBundleScanningSchemaServiceImpl.createInstance(context);
- schemaService.start();
schemaServiceReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String,String>());
}