Bug 2019: Have FeatureConfigPusher retry installedFeature check 96/11496/1
authorEd Warnicke <eaw@cisco.com>
Tue, 23 Sep 2014 17:08:42 +0000 (12:08 -0500)
committerEd Warnicke <eaw@cisco.com>
Tue, 23 Sep 2014 17:23:45 +0000 (12:23 -0500)
until it succeeds (or 100ms pass).

Karaf reports FeatureEvents before it marks the features
installed.  It also only guarantees complete info about
the features when you read the installed ones.  This
is causing a race condition that is at the root of 2019.

So this patch retries at 1ms intervals until we see

Change-Id: I67080475fc4b2dc2f053a286424f676f89164b6e
Signed-off-by: Ed Warnicke <eaw@cisco.com>
opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/ConfigFeaturesListener.java
opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/FeatureConfigPusher.java

index f5f1b85..b8f1896 100644 (file)
@@ -20,7 +20,7 @@ import org.slf4j.LoggerFactory;
 
 public class ConfigFeaturesListener implements  FeaturesListener,  AutoCloseable {
     private static final Logger logger = LoggerFactory.getLogger(ConfigFeaturesListener.class);
-    private static final int QUEUE_SIZE = 100;
+    private static final int QUEUE_SIZE = 1000;
     private BlockingQueue<FeatureEvent> queue = new LinkedBlockingQueue<FeatureEvent>(QUEUE_SIZE);
     Thread pushingThread = null;
 
index 57052f9..17099f9 100644 (file)
@@ -27,6 +27,7 @@ import com.google.common.collect.LinkedHashMultimap;
 public class FeatureConfigPusher {
     private static final Logger logger = LoggerFactory.getLogger(FeatureConfigPusher.class);
     private static final int MAX_RETRIES=100;
+    private static final int RETRY_PAUSE_MILLIS=1;
     private FeaturesService featuresService = null;
     private ConfigPusher pusher = null;
     /*
@@ -83,30 +84,30 @@ public class FeatureConfigPusher {
     }
 
     private boolean isInstalled(Feature feature) {
-        List<Feature> installedFeatures= null;
-        boolean cont = true;
-        int retries = 0;
-        while(cont) {
+        for(int retries=0;retries<MAX_RETRIES;retries++) {
             try {
-                installedFeatures = Arrays.asList(featuresService.listInstalledFeatures());
-                break;
+                List<Feature> installedFeatures = Arrays.asList(featuresService.listInstalledFeatures());
+                if(installedFeatures.contains(feature)) {
+                    return true;
+                } else {
+                    logger.warn("Karaf featuresService.listInstalledFeatures() has not yet finished installing feature (retry {}) {} {}",retries,feature.getName(),feature.getVersion());
+                }
             } catch (Exception e) {
                 if(retries < MAX_RETRIES) {
                     logger.warn("Karaf featuresService.listInstalledFeatures() has thrown an exception, retry {}, Exception {}", retries,e);
-                    try {
-                        Thread.sleep(1);
-                    } catch (InterruptedException e1) {
-                        throw new IllegalStateException(e1);
-                    }
-                    retries++;
-                    continue;
                 } else {
                     logger.error("Giving up on Karaf featuresService.listInstalledFeatures() which has thrown an exception, retry {}, Exception {}", retries,e);
                     throw e;
                 }
             }
+            try {
+                Thread.sleep(RETRY_PAUSE_MILLIS);
+            } catch (InterruptedException e1) {
+                throw new IllegalStateException(e1);
+            }
         }
-        return installedFeatures.contains(feature);
+        logger.error("Giving up (after {} retries) on Karaf featuresService.listInstalledFeatures() which has not yet finished installing feature {} {}",MAX_RETRIES,feature.getName(),feature.getVersion());
+        return false;
     }
 
     private LinkedHashSet<FeatureConfigSnapshotHolder> pushConfig(LinkedHashSet<FeatureConfigSnapshotHolder> configs) throws InterruptedException {