Thomas Vachuska
Committed by Gerrit Code Review

Added a temporary fix for out-of-order app activation event delivery.

Cleaning up app subsystem code a tiny bit as well.

Change-Id: I5df7d4c6d62d122653331474fb079648e779d595
...@@ -80,8 +80,6 @@ public class ApplicationManager ...@@ -80,8 +80,6 @@ public class ApplicationManager
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected FeaturesService featuresService; 81 protected FeaturesService featuresService;
82 82
83 - private boolean initializing;
84 -
85 // Application supplied hooks for pre-activation processing. 83 // Application supplied hooks for pre-activation processing.
86 private final Multimap<String, Runnable> deactivateHooks = HashMultimap.create(); 84 private final Multimap<String, Runnable> deactivateHooks = HashMultimap.create();
87 private final Cache<ApplicationId, CountDownLatch> pendingOperations = 85 private final Cache<ApplicationId, CountDownLatch> pendingOperations =
...@@ -92,11 +90,7 @@ public class ApplicationManager ...@@ -92,11 +90,7 @@ public class ApplicationManager
92 @Activate 90 @Activate
93 public void activate() { 91 public void activate() {
94 eventDispatcher.addSink(ApplicationEvent.class, listenerRegistry); 92 eventDispatcher.addSink(ApplicationEvent.class, listenerRegistry);
95 -
96 - initializing = true;
97 store.setDelegate(delegate); 93 store.setDelegate(delegate);
98 - initializing = false;
99 -
100 log.info("Started"); 94 log.info("Started");
101 } 95 }
102 96
......
...@@ -30,6 +30,7 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -30,6 +30,7 @@ import org.apache.felix.scr.annotations.Deactivate;
30 import org.apache.felix.scr.annotations.Reference; 30 import org.apache.felix.scr.annotations.Reference;
31 import org.apache.felix.scr.annotations.ReferenceCardinality; 31 import org.apache.felix.scr.annotations.ReferenceCardinality;
32 import org.apache.felix.scr.annotations.Service; 32 import org.apache.felix.scr.annotations.Service;
33 +import org.onlab.util.Tools;
33 import org.onosproject.app.ApplicationDescription; 34 import org.onosproject.app.ApplicationDescription;
34 import org.onosproject.app.ApplicationEvent; 35 import org.onosproject.app.ApplicationEvent;
35 import org.onosproject.app.ApplicationException; 36 import org.onosproject.app.ApplicationException;
...@@ -89,11 +90,14 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -89,11 +90,14 @@ import static org.slf4j.LoggerFactory.getLogger;
89 * Manages inventory of applications in a distributed data store providing 90 * Manages inventory of applications in a distributed data store providing
90 * stronger consistency guarantees. 91 * stronger consistency guarantees.
91 */ 92 */
92 -@Component(immediate = true, enabled = true) 93 +@Component(immediate = true)
93 @Service 94 @Service
94 public class DistributedApplicationStore extends ApplicationArchive 95 public class DistributedApplicationStore extends ApplicationArchive
95 implements ApplicationStore { 96 implements ApplicationStore {
96 97
98 + // FIXME: eliminate the need for this
99 + private static final int FIXME_ACTIVATION_DELAY = 500;
100 +
97 private final Logger log = getLogger(getClass()); 101 private final Logger log = getLogger(getClass());
98 102
99 private static final MessageSubject APP_BITS_REQUEST = new MessageSubject("app-bits-request"); 103 private static final MessageSubject APP_BITS_REQUEST = new MessageSubject("app-bits-request");
...@@ -144,24 +148,24 @@ public class DistributedApplicationStore extends ApplicationArchive ...@@ -144,24 +148,24 @@ public class DistributedApplicationStore extends ApplicationArchive
144 public void activate() { 148 public void activate() {
145 messageHandlingExecutor = Executors.newSingleThreadExecutor( 149 messageHandlingExecutor = Executors.newSingleThreadExecutor(
146 groupedThreads("onos/store/app", "message-handler", log)); 150 groupedThreads("onos/store/app", "message-handler", log));
147 - clusterCommunicator.<String, byte[]>addSubscriber(APP_BITS_REQUEST, 151 + clusterCommunicator.addSubscriber(APP_BITS_REQUEST,
148 - bytes -> new String(bytes, Charsets.UTF_8), 152 + bytes -> new String(bytes, Charsets.UTF_8),
149 - name -> { 153 + name -> {
150 - try { 154 + try {
151 - return toByteArray(getApplicationInputStream(name)); 155 + return toByteArray(getApplicationInputStream(name));
152 - } catch (IOException e) { 156 + } catch (IOException e) {
153 - throw new StorageException(e); 157 + throw new StorageException(e);
154 - } 158 + }
155 - }, 159 + },
156 - Function.identity(), 160 + Function.identity(),
157 - messageHandlingExecutor); 161 + messageHandlingExecutor);
158 162
159 apps = storageService.<ApplicationId, InternalApplicationHolder>consistentMapBuilder() 163 apps = storageService.<ApplicationId, InternalApplicationHolder>consistentMapBuilder()
160 .withName("onos-apps") 164 .withName("onos-apps")
161 .withRelaxedReadConsistency() 165 .withRelaxedReadConsistency()
162 .withSerializer(Serializer.using(KryoNamespaces.API, 166 .withSerializer(Serializer.using(KryoNamespaces.API,
163 - InternalApplicationHolder.class, 167 + InternalApplicationHolder.class,
164 - InternalState.class)) 168 + InternalState.class))
165 .build(); 169 .build();
166 170
167 executor = newSingleThreadScheduledExecutor(groupedThreads("onos/app", "store", log)); 171 executor = newSingleThreadScheduledExecutor(groupedThreads("onos/app", "store", log));
...@@ -180,7 +184,7 @@ public class DistributedApplicationStore extends ApplicationArchive ...@@ -180,7 +184,7 @@ public class DistributedApplicationStore extends ApplicationArchive
180 * Processes existing applications from the distributed map. This is done to 184 * Processes existing applications from the distributed map. This is done to
181 * account for events that this instance may be have missed due to a staggered start. 185 * account for events that this instance may be have missed due to a staggered start.
182 */ 186 */
183 - void bootstrapExistingApplications() { 187 + private void bootstrapExistingApplications() {
184 apps.asJavaMap().forEach((appId, holder) -> setupApplicationAndNotify(appId, holder.app(), holder.state())); 188 apps.asJavaMap().forEach((appId, holder) -> setupApplicationAndNotify(appId, holder.app(), holder.state()));
185 189
186 } 190 }
...@@ -253,7 +257,7 @@ public class DistributedApplicationStore extends ApplicationArchive ...@@ -253,7 +257,7 @@ public class DistributedApplicationStore extends ApplicationArchive
253 public void setDelegate(ApplicationStoreDelegate delegate) { 257 public void setDelegate(ApplicationStoreDelegate delegate) {
254 super.setDelegate(delegate); 258 super.setDelegate(delegate);
255 executor.execute(this::bootstrapExistingApplications); 259 executor.execute(this::bootstrapExistingApplications);
256 - executor.schedule(() -> loadFromDisk(), APP_LOAD_DELAY_MS, TimeUnit.MILLISECONDS); 260 + executor.schedule((Runnable) this::loadFromDisk, APP_LOAD_DELAY_MS, TimeUnit.MILLISECONDS);
257 } 261 }
258 262
259 @Override 263 @Override
...@@ -296,7 +300,7 @@ public class DistributedApplicationStore extends ApplicationArchive ...@@ -296,7 +300,7 @@ public class DistributedApplicationStore extends ApplicationArchive
296 } 300 }
297 301
298 private boolean hasPrerequisites(ApplicationDescription app) { 302 private boolean hasPrerequisites(ApplicationDescription app) {
299 - return !app.requiredApps().stream().map(n -> getId(n)) 303 + return !app.requiredApps().stream().map(this::getId)
300 .anyMatch(id -> id == null || getApplication(id) == null); 304 .anyMatch(id -> id == null || getApplication(id) == null);
301 } 305 }
302 306
...@@ -342,6 +346,11 @@ public class DistributedApplicationStore extends ApplicationArchive ...@@ -342,6 +346,11 @@ public class DistributedApplicationStore extends ApplicationArchive
342 } 346 }
343 activateRequiredApps(vAppHolder.value().app()); 347 activateRequiredApps(vAppHolder.value().app());
344 348
349 + // FIXME: Take a breath before the post-order operation to allow required app
350 + // activation events to fully propagate. There appears to be an out-of-order
351 + // event delivery issue that needs to be fixed.
352 + Tools.delay(FIXME_ACTIVATION_DELAY);
353 +
345 apps.computeIf(appId, v -> v != null && v.state() != ACTIVATED, 354 apps.computeIf(appId, v -> v != null && v.state() != ACTIVATED,
346 (k, v) -> new InternalApplicationHolder( 355 (k, v) -> new InternalApplicationHolder(
347 v.app(), ACTIVATED, v.permissions())); 356 v.app(), ACTIVATED, v.permissions()));
...@@ -539,25 +548,25 @@ public class DistributedApplicationStore extends ApplicationArchive ...@@ -539,25 +548,25 @@ public class DistributedApplicationStore extends ApplicationArchive
539 private Application registerApp(ApplicationDescription appDesc) { 548 private Application registerApp(ApplicationDescription appDesc) {
540 ApplicationId appId = idStore.registerApplication(appDesc.name()); 549 ApplicationId appId = idStore.registerApplication(appDesc.name());
541 return new DefaultApplication(appId, 550 return new DefaultApplication(appId,
542 - appDesc.version(), 551 + appDesc.version(),
543 - appDesc.title(), 552 + appDesc.title(),
544 - appDesc.description(), 553 + appDesc.description(),
545 - appDesc.origin(), 554 + appDesc.origin(),
546 - appDesc.category(), 555 + appDesc.category(),
547 - appDesc.url(), 556 + appDesc.url(),
548 - appDesc.readme(), 557 + appDesc.readme(),
549 - appDesc.icon(), 558 + appDesc.icon(),
550 - appDesc.role(), 559 + appDesc.role(),
551 - appDesc.permissions(), 560 + appDesc.permissions(),
552 - appDesc.featuresRepo(), 561 + appDesc.featuresRepo(),
553 - appDesc.features(), 562 + appDesc.features(),
554 - appDesc.requiredApps()); 563 + appDesc.requiredApps());
555 } 564 }
556 565
557 /** 566 /**
558 * Internal class for holding app information. 567 * Internal class for holding app information.
559 */ 568 */
560 - private static class InternalApplicationHolder { 569 + private static final class InternalApplicationHolder {
561 private final Application app; 570 private final Application app;
562 private final InternalState state; 571 private final InternalState state;
563 private final Set<Permission> permissions; 572 private final Set<Permission> permissions;
...@@ -569,7 +578,7 @@ public class DistributedApplicationStore extends ApplicationArchive ...@@ -569,7 +578,7 @@ public class DistributedApplicationStore extends ApplicationArchive
569 permissions = null; 578 permissions = null;
570 } 579 }
571 580
572 - public InternalApplicationHolder(Application app, InternalState state, Set<Permission> permissions) { 581 + private InternalApplicationHolder(Application app, InternalState state, Set<Permission> permissions) {
573 this.app = Preconditions.checkNotNull(app); 582 this.app = Preconditions.checkNotNull(app);
574 this.state = state; 583 this.state = state;
575 this.permissions = permissions == null ? null : ImmutableSet.copyOf(permissions); 584 this.permissions = permissions == null ? null : ImmutableSet.copyOf(permissions);
......