Andrea Campanella
Committed by Gerrit Code Review

Detect circular app dependency

Change-Id: Ib3e2d802dfe3675ef5c8ef8818c1127ed145adf1
...@@ -17,6 +17,7 @@ package org.onosproject.store.app; ...@@ -17,6 +17,7 @@ package org.onosproject.store.app;
17 17
18 import com.google.common.base.Charsets; 18 import com.google.common.base.Charsets;
19 import com.google.common.collect.ImmutableSet; 19 import com.google.common.collect.ImmutableSet;
20 +import com.google.common.collect.Lists;
20 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
21 import com.google.common.collect.Multimap; 22 import com.google.common.collect.Multimap;
22 import com.google.common.collect.Sets; 23 import com.google.common.collect.Sets;
...@@ -57,6 +58,8 @@ import org.slf4j.Logger; ...@@ -57,6 +58,8 @@ import org.slf4j.Logger;
57 import java.io.ByteArrayInputStream; 58 import java.io.ByteArrayInputStream;
58 import java.io.IOException; 59 import java.io.IOException;
59 import java.io.InputStream; 60 import java.io.InputStream;
61 +import java.util.List;
62 +import java.util.Optional;
60 import java.util.Set; 63 import java.util.Set;
61 import java.util.concurrent.CountDownLatch; 64 import java.util.concurrent.CountDownLatch;
62 import java.util.concurrent.ExecutorService; 65 import java.util.concurrent.ExecutorService;
...@@ -98,6 +101,8 @@ public class GossipApplicationStore extends ApplicationArchive ...@@ -98,6 +101,8 @@ public class GossipApplicationStore extends ApplicationArchive
98 101
99 private static final int APP_LOAD_DELAY_MS = 500; 102 private static final int APP_LOAD_DELAY_MS = 500;
100 103
104 + private static List<String> pendingApps = Lists.newArrayList();
105 +
101 public enum InternalState { 106 public enum InternalState {
102 INSTALLED, ACTIVATED, DEACTIVATED 107 INSTALLED, ACTIVATED, DEACTIVATED
103 } 108 }
...@@ -197,6 +202,8 @@ public class GossipApplicationStore extends ApplicationArchive ...@@ -197,6 +202,8 @@ public class GossipApplicationStore extends ApplicationArchive
197 } 202 }
198 203
199 private Application loadFromDisk(String appName) { 204 private Application loadFromDisk(String appName) {
205 + pendingApps.add(appName);
206 +
200 for (int i = 0; i < MAX_LOAD_RETRIES; i++) { 207 for (int i = 0; i < MAX_LOAD_RETRIES; i++) {
201 try { 208 try {
202 // Directly return if app already exists 209 // Directly return if app already exists
...@@ -204,19 +211,33 @@ public class GossipApplicationStore extends ApplicationArchive ...@@ -204,19 +211,33 @@ public class GossipApplicationStore extends ApplicationArchive
204 if (appId != null) { 211 if (appId != null) {
205 Application application = getApplication(appId); 212 Application application = getApplication(appId);
206 if (application != null) { 213 if (application != null) {
214 + pendingApps.remove(appName);
207 return application; 215 return application;
208 } 216 }
209 } 217 }
210 218
211 ApplicationDescription appDesc = getApplicationDescription(appName); 219 ApplicationDescription appDesc = getApplicationDescription(appName);
220 +
221 + Optional<String> loop = appDesc.requiredApps().stream()
222 + .filter(app -> pendingApps.contains(app)).findAny();
223 + if (loop.isPresent()) {
224 + log.error("Circular app dependency detected: {} -> {}", pendingApps, loop.get());
225 + pendingApps.remove(appName);
226 + return null;
227 + }
228 +
212 boolean success = appDesc.requiredApps().stream() 229 boolean success = appDesc.requiredApps().stream()
213 .noneMatch(requiredApp -> loadFromDisk(requiredApp) == null); 230 .noneMatch(requiredApp -> loadFromDisk(requiredApp) == null);
231 + pendingApps.remove(appName);
232 +
214 return success ? create(appDesc, false) : null; 233 return success ? create(appDesc, false) : null;
234 +
215 } catch (Exception e) { 235 } catch (Exception e) {
216 log.warn("Unable to load application {} from disk; retrying", appName); 236 log.warn("Unable to load application {} from disk; retrying", appName);
217 randomDelay(RETRY_DELAY_MS); //FIXME: This is a deliberate hack; fix in Falcon 237 randomDelay(RETRY_DELAY_MS); //FIXME: This is a deliberate hack; fix in Falcon
218 } 238 }
219 } 239 }
240 + pendingApps.remove(appName);
220 return null; 241 return null;
221 } 242 }
222 243
......