You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2020/06/29 13:51:00 UTC

[karaf-cellar] branch master updated: Synchronizer map (#67)

This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf-cellar.git


The following commit(s) were added to refs/heads/master by this push:
     new 3396c2a  Synchronizer map (#67)
3396c2a is described below

commit 3396c2aa20e2227de7c21ed01bae81c488dd22b2
Author: Thomas Draier <td...@jahia.com>
AuthorDate: Mon Jun 29 15:50:55 2020 +0200

    Synchronizer map (#67)
    
    Synchronize access to map
---
 .../karaf/cellar/bundle/BundleSynchronizer.java    |  5 +-
 .../cellar/config/ConfigurationSynchronizer.java   |  4 +-
 .../apache/karaf/cellar/core/CellarSupport.java    |  4 ++
 .../karaf/cellar/core/utils/CellarUtils.java       | 57 ++++++++++++++++++++++
 .../cellar/features/FeaturesSynchronizer.java      | 11 ++++-
 5 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
index 6e18cfd..51a7bb2 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
@@ -19,6 +19,7 @@ import org.apache.karaf.cellar.core.Synchronizer;
 import org.apache.karaf.cellar.core.control.SwitchStatus;
 import org.apache.karaf.cellar.core.event.EventProducer;
 import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.utils.CellarUtils;
 import org.apache.karaf.features.BootFinished;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -198,12 +199,13 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
                 }
 
                 // cleanup the local bundles not present on the cluster if the node is not the first one in the cluster group
-                if (clusterManager.listNodesByGroup(group).size() > 1) {
+                if (CellarUtils.doCleanupResourcesNotPresentInCluster(configurationAdmin) && getSynchronizerMap().containsKey(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName)) {
                     for (Bundle bundle : bundleContext.getBundles()) {
                         String id = getId(bundle);
                         if (!clusterBundles.containsKey(id) && isAllowed(group, Constants.CATEGORY, bundle.getLocation(), EventType.INBOUND)) {
                             // the bundle is not present on the cluster, so it has to be uninstalled locally
                             try {
+                                LOGGER.debug("CELLAR BUNDLE: uninstalling local bundle {} which is not present in cluster", id);
                                 bundle.uninstall();
                             } catch (Exception e) {
                                 LOGGER.warn("Can't uninstall {}", id, e);
@@ -315,6 +317,7 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
                         }
                     }
                 }
+                getSynchronizerMap().putIfAbsent(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName, true);
             } finally {
                 Thread.currentThread().setContextClassLoader(originalClassLoader);
             }
diff --git a/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java b/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
index e02040c..613ce4c 100644
--- a/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
+++ b/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
@@ -19,6 +19,7 @@ import org.apache.karaf.cellar.core.Synchronizer;
 import org.apache.karaf.cellar.core.control.SwitchStatus;
 import org.apache.karaf.cellar.core.event.EventProducer;
 import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.utils.CellarUtils;
 import org.apache.karaf.features.BootFinished;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
@@ -148,7 +149,7 @@ public class ConfigurationSynchronizer extends ConfigurationSupport implements S
                     } else  LOGGER.trace("CELLAR CONFIG: configuration with PID {} is marked BLOCKED INBOUND for cluster group {}", pid, groupName);
                 }
                 // cleanup the local configurations not present on the cluster if the node is not the first one in the cluster
-                if (clusterManager.listNodesByGroup(group).size() > 1) {
+                if (CellarUtils.doCleanupResourcesNotPresentInCluster(configurationAdmin) && getSynchronizerMap().containsKey(Constants.CONFIGURATION_MAP + Configurations.SEPARATOR + groupName)) {
                     try {
                         Set<String> filenames = new HashSet();
                         for (Properties configuration : clusterConfigurations.values()) {
@@ -241,6 +242,7 @@ public class ConfigurationSynchronizer extends ConfigurationSupport implements S
                             }
                         }
                     }
+                    getSynchronizerMap().putIfAbsent(Constants.CONFIGURATION_MAP + Configurations.SEPARATOR + groupName, true);
                 } catch (IOException ex) {
                     LOGGER.error("CELLAR CONFIG: failed to read configuration (IO error)", ex);
                 } catch (InvalidSyntaxException ex) {
diff --git a/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java b/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
index 8904cea..a1d0f3c 100644
--- a/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
+++ b/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
@@ -248,4 +248,8 @@ public class CellarSupport {
         this.groupManager = groupManager;
     }
 
+    @SuppressWarnings("unchecked")
+    protected Map<String, Boolean> getSynchronizerMap() {
+        return clusterManager.getMap("org.apache.karaf.cellar.synchronizers");
+    }
 }
diff --git a/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java b/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java
index 28e57d7..8ba5973 100644
--- a/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java
+++ b/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java
@@ -13,13 +13,21 @@
  */
 package org.apache.karaf.cellar.core.utils;
 
+import java.io.IOException;
 import java.util.Collection;
+import java.util.Dictionary;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.karaf.cellar.core.Configurations;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * Generic Cellar utils class.
  */
@@ -29,6 +37,8 @@ public class CellarUtils {
         MERGA
     }
 
+    private static final transient Logger LOGGER = LoggerFactory.getLogger(CellarUtils.class);
+
     public static final String MERGABLE = "MERGABLE[%s]";
     public static final String MERGABLE_REGEX = "MERGABLE\\[([^\\s]+[\\,]*[\\s]*)*\\]";
 
@@ -129,4 +139,51 @@ public class CellarUtils {
             return true;
         }
     }
+
+    /**
+     * Retrieves the value of the configuration property from the specified configuration. If the property is not found or there is an error
+     * retrieving it, return the provided default value.
+     *
+     * @param configurationAdmin
+     *            the config admin service instance
+     * @param configurationId
+     *            the configuration PID to be retrieved
+     * @param propertyKey
+     *            the key of the property entry to look up
+     * @param defaultValue
+     *            a value to be returned, if the property is not present in the configuration or there is an error retrieving it
+     * @return the value of the configuration property from the specified configuration. If the property is not found or there is an error
+     *         retrieving it, return the provided default value
+     */
+    public static String getConfigurationProperty(ConfigurationAdmin configurationAdmin, String configurationId,
+            String propertyKey, String defaultValue) {
+        String propertyValue = null;
+        try {
+            Configuration configuration = configurationAdmin.getConfiguration(configurationId, null);
+            Dictionary<String, Object> properties = configuration.getProperties();
+            if (properties != null) {
+                propertyValue = (String) properties.get(propertyKey);
+            }
+        } catch (IOException e) {
+            LOGGER.warn("Error while retrieving the " + propertyKey + " entry from coonfiguration " + configurationId,
+                    e);
+        }
+
+        return propertyValue != null ? propertyValue : defaultValue;
+    }
+
+    /**
+     * Returns the flag value, indicating if the resources (bundles, configuration, features), not present on cluster, should be uninstalled
+     * on cluster sync by corresponding synchronizers.
+     * 
+     * @param configurationAdmin
+     *            the config admin service instance
+     * @return the flag value, indicating if the resources (bundles, configuration, features), not present on cluster, should be uninstalled
+     *         on cluster sync by corresponding synchronizers
+     */
+    public static boolean doCleanupResourcesNotPresentInCluster(ConfigurationAdmin configurationAdmin) {
+        return Boolean.parseBoolean(getConfigurationProperty(configurationAdmin, Configurations.NODE,
+                "org.apache.karaf.cellar.cleanupResourcesNotPresentInCluster", "true"));
+    }
+
 }
diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
index 487b780..daf8961 100644
--- a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
+++ b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
@@ -19,6 +19,7 @@ import org.apache.karaf.cellar.core.Synchronizer;
 import org.apache.karaf.cellar.core.control.SwitchStatus;
 import org.apache.karaf.cellar.core.event.EventProducer;
 import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.utils.CellarUtils;
 import org.apache.karaf.features.*;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.cm.Configuration;
@@ -122,6 +123,7 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
 
                 Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
                 Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
+                Map<String, Boolean> synchronizers = getSynchronizerMap();
 
                 if (clusterRepositories != null && !clusterRepositories.isEmpty()) {
                     // get the features repositories from the cluster to update locally
@@ -138,7 +140,8 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
                         }
                     }
                     // cleanup the local features repositories not present on the cluster if the node is not the first one in the cluster group
-                    if (clusterManager.listNodesByGroup(group).size() > 1) {
+
+                    if (synchronizers.containsKey(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName)) {
                         try {
                             for (Repository repository : featuresService.listRepositories()) {
                                 URI uri = repository.getURI();
@@ -161,6 +164,7 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
                 }
 
                 if (clusterFeatures != null && !clusterFeatures.isEmpty()) {
+                    boolean doUninstallFeaturesNotPresentInCluster = CellarUtils.doCleanupResourcesNotPresentInCluster(configurationAdmin) && synchronizers.containsKey(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
                     // get the features from the cluster group and update locally
                     for (FeatureState state : clusterFeatures.values()) {
                         String name = state.getName();
@@ -187,7 +191,7 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
                                 }
                             }
                             // if feature has to be uninstalled locally (and node is not the first one in the cluster group)
-                            if (clusterManager.listNodesByGroup(group).size() > 1 && !clusterInstalled && locallyInstalled) {
+                            if (doUninstallFeaturesNotPresentInCluster && !clusterInstalled && locallyInstalled) {
                                 try {
                                     LOGGER.debug("CELLAR FEATURE: uninstalling feature {}/{}", state.getName(), state.getVersion());
                                     featuresService.uninstallFeature(state.getName(), state.getVersion());
@@ -227,6 +231,7 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
 
                 Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
                 Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
+                Map<String, Boolean> synchronizers = getSynchronizerMap();
 
                 Repository[] repositoryList = new Repository[0];
                 Feature[] featuresList = new Feature[0];
@@ -260,6 +265,7 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
                         }
                     }
                 }
+                synchronizers.put(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName, true);
 
                 // push features to the cluster group
                 if (featuresList != null && featuresList.length > 0) {
@@ -312,6 +318,7 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
                         }
                     }
                 }
+                synchronizers.put(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName, true);
             } finally {
                 Thread.currentThread().setContextClassLoader(originalClassLoader);
             }