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
Showing
2 changed files
with
41 additions
and
38 deletions
... | @@ -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); | ... | ... |
-
Please register or login to post a comment