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