Committed by
Gerrit Code Review
Ensure ApplicationService::uninstall returns only after the features have been uninstalled
Change-Id: Iff9c1c0196bc8616858589c67ce4c876e99a8120
Showing
1 changed file
with
22 additions
and
1 deletions
... | @@ -15,8 +15,12 @@ | ... | @@ -15,8 +15,12 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.app.impl; | 16 | package org.onosproject.app.impl; |
17 | 17 | ||
18 | +import com.google.common.cache.Cache; | ||
19 | +import com.google.common.cache.CacheBuilder; | ||
18 | import com.google.common.collect.HashMultimap; | 20 | import com.google.common.collect.HashMultimap; |
19 | import com.google.common.collect.Multimap; | 21 | import com.google.common.collect.Multimap; |
22 | +import com.google.common.util.concurrent.Uninterruptibles; | ||
23 | + | ||
20 | import org.apache.felix.scr.annotations.Activate; | 24 | import org.apache.felix.scr.annotations.Activate; |
21 | import org.apache.felix.scr.annotations.Component; | 25 | import org.apache.felix.scr.annotations.Component; |
22 | import org.apache.felix.scr.annotations.Deactivate; | 26 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -41,6 +45,8 @@ import org.slf4j.Logger; | ... | @@ -41,6 +45,8 @@ import org.slf4j.Logger; |
41 | 45 | ||
42 | import java.io.InputStream; | 46 | import java.io.InputStream; |
43 | import java.util.Set; | 47 | import java.util.Set; |
48 | +import java.util.concurrent.CountDownLatch; | ||
49 | +import java.util.concurrent.TimeUnit; | ||
44 | 50 | ||
45 | import static com.google.common.base.Preconditions.checkNotNull; | 51 | import static com.google.common.base.Preconditions.checkNotNull; |
46 | import static org.onosproject.app.ApplicationEvent.Type.APP_ACTIVATED; | 52 | import static org.onosproject.app.ApplicationEvent.Type.APP_ACTIVATED; |
... | @@ -63,6 +69,7 @@ public class ApplicationManager | ... | @@ -63,6 +69,7 @@ public class ApplicationManager |
63 | private final Logger log = getLogger(getClass()); | 69 | private final Logger log = getLogger(getClass()); |
64 | 70 | ||
65 | private static final String APP_ID_NULL = "Application ID cannot be null"; | 71 | private static final String APP_ID_NULL = "Application ID cannot be null"; |
72 | + private static final long DEFAULT_OPERATION_TIMEOUT_MILLIS = 2000; | ||
66 | 73 | ||
67 | private final ApplicationStoreDelegate delegate = new InternalStoreDelegate(); | 74 | private final ApplicationStoreDelegate delegate = new InternalStoreDelegate(); |
68 | 75 | ||
... | @@ -76,6 +83,10 @@ public class ApplicationManager | ... | @@ -76,6 +83,10 @@ public class ApplicationManager |
76 | 83 | ||
77 | // Application supplied hooks for pre-activation processing. | 84 | // Application supplied hooks for pre-activation processing. |
78 | private final Multimap<String, Runnable> deactivateHooks = HashMultimap.create(); | 85 | private final Multimap<String, Runnable> deactivateHooks = HashMultimap.create(); |
86 | + private final Cache<ApplicationId, CountDownLatch> pendingUninstalls = | ||
87 | + CacheBuilder.newBuilder() | ||
88 | + .expireAfterWrite(DEFAULT_OPERATION_TIMEOUT_MILLIS * 2, TimeUnit.MILLISECONDS) | ||
89 | + .build(); | ||
79 | 90 | ||
80 | @Activate | 91 | @Activate |
81 | public void activate() { | 92 | public void activate() { |
... | @@ -148,11 +159,16 @@ public class ApplicationManager | ... | @@ -148,11 +159,16 @@ public class ApplicationManager |
148 | @Override | 159 | @Override |
149 | public void uninstall(ApplicationId appId) { | 160 | public void uninstall(ApplicationId appId) { |
150 | checkNotNull(appId, APP_ID_NULL); | 161 | checkNotNull(appId, APP_ID_NULL); |
162 | + CountDownLatch latch = new CountDownLatch(1); | ||
151 | try { | 163 | try { |
164 | + pendingUninstalls.put(appId, latch); | ||
152 | store.remove(appId); | 165 | store.remove(appId); |
153 | } catch (Exception e) { | 166 | } catch (Exception e) { |
167 | + pendingUninstalls.invalidate(appId); | ||
168 | + latch.countDown(); | ||
154 | log.warn("Unable to purge application directory for {}", appId.name()); | 169 | log.warn("Unable to purge application directory for {}", appId.name()); |
155 | } | 170 | } |
171 | + Uninterruptibles.awaitUninterruptibly(latch, DEFAULT_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); | ||
156 | } | 172 | } |
157 | 173 | ||
158 | @Override | 174 | @Override |
... | @@ -182,6 +198,7 @@ public class ApplicationManager | ... | @@ -182,6 +198,7 @@ public class ApplicationManager |
182 | public void notify(ApplicationEvent event) { | 198 | public void notify(ApplicationEvent event) { |
183 | ApplicationEvent.Type type = event.type(); | 199 | ApplicationEvent.Type type = event.type(); |
184 | Application app = event.subject(); | 200 | Application app = event.subject(); |
201 | + CountDownLatch latch = pendingUninstalls.getIfPresent(app.id()); | ||
185 | try { | 202 | try { |
186 | if (type == APP_ACTIVATED) { | 203 | if (type == APP_ACTIVATED) { |
187 | if (installAppFeatures(app)) { | 204 | if (installAppFeatures(app)) { |
... | @@ -205,9 +222,13 @@ public class ApplicationManager | ... | @@ -205,9 +222,13 @@ public class ApplicationManager |
205 | 222 | ||
206 | } | 223 | } |
207 | post(event); | 224 | post(event); |
208 | - | ||
209 | } catch (Exception e) { | 225 | } catch (Exception e) { |
210 | log.warn("Unable to perform operation on application " + app.id().name(), e); | 226 | log.warn("Unable to perform operation on application " + app.id().name(), e); |
227 | + } finally { | ||
228 | + if (latch != null) { | ||
229 | + latch.countDown(); | ||
230 | + pendingUninstalls.invalidate(app.id()); | ||
231 | + } | ||
211 | } | 232 | } |
212 | } | 233 | } |
213 | } | 234 | } | ... | ... |
-
Please register or login to post a comment