You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2016/12/06 22:09:30 UTC

geode git commit: potential changes

Repository: geode
Updated Branches:
  refs/heads/cluster-config [created] 34ddd5e0a


potential changes


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/34ddd5e0
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/34ddd5e0
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/34ddd5e0

Branch: refs/heads/cluster-config
Commit: 34ddd5e0a3760bd784d430db9e5f3acb956d8847
Parents: 4876c78
Author: Jinmei Liao <ji...@pivotal.io>
Authored: Mon Dec 5 08:54:05 2016 -0800
Committer: Jinmei Liao <ji...@pivotal.io>
Committed: Tue Dec 6 08:45:46 2016 -0800

----------------------------------------------------------------------
 .../internal/SharedConfiguration.java           | 120 +++++++------------
 .../internal/cli/commands/DeployCommands.java   |  19 ++-
 ...ExportImportSharedConfigurationCommands.java |  63 ++++------
 .../ExportSharedConfigurationFunction.java      |   8 +-
 ...ortSharedConfigurationArtifactsFunction.java |  13 +-
 .../SharedConfigurationWriter.java              |  17 ++-
 .../callbacks/ConfigurationChangeListener.java  |  16 ++-
 .../configuration/ClusterConfigDUnitTest.java   |  41 +++++++
 .../ClusterConfigIntegrationTest.java           |  37 ++++++
 9 files changed, 188 insertions(+), 146 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/main/java/org/apache/geode/distributed/internal/SharedConfiguration.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/SharedConfiguration.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/SharedConfiguration.java
index a45e843..adf9e9d 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/SharedConfiguration.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/SharedConfiguration.java
@@ -14,40 +14,13 @@
  */
 package org.apache.geode.distributed.internal;
 
-import static org.apache.geode.distributed.ConfigurationProperties.*;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.xpath.XPathExpressionException;
+import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_CONFIGURATION_DIR;
+import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_MANAGER;
+import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_POST_PROCESSOR;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.filefilter.DirectoryFileFilter;
-import org.apache.logging.log4j.Logger;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
 import org.apache.geode.CancelException;
 import org.apache.geode.cache.AttributesFactory;
 import org.apache.geode.cache.Cache;
@@ -70,8 +43,6 @@ import org.apache.geode.internal.cache.xmlcache.CacheXmlGenerator;
 import org.apache.geode.internal.lang.StringUtils;
 import org.apache.geode.internal.logging.LogService;
 import org.apache.geode.management.internal.cli.CliUtil;
-import org.apache.geode.management.internal.cli.functions.ImportSharedConfigurationArtifactsFunction;
-import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.configuration.callbacks.ConfigurationChangeListener;
 import org.apache.geode.management.internal.configuration.domain.Configuration;
 import org.apache.geode.management.internal.configuration.domain.SharedConfigurationStatus;
@@ -81,7 +52,31 @@ import org.apache.geode.management.internal.configuration.messages.Configuration
 import org.apache.geode.management.internal.configuration.messages.ConfigurationResponse;
 import org.apache.geode.management.internal.configuration.messages.SharedConfigurationStatusResponse;
 import org.apache.geode.management.internal.configuration.utils.XmlUtils;
-import org.apache.geode.management.internal.configuration.utils.ZipUtils;
+import org.apache.logging.log4j.Logger;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.xpath.XPathExpressionException;
 
 @SuppressWarnings({"deprecation", "unchecked"})
 public class SharedConfiguration {
@@ -181,12 +176,15 @@ public class SharedConfiguration {
 
         if (configuration == null) {
           configuration = new Configuration(group);
-          writeConfig(configuration);
+          //writeConfig(configuration);
         }
-        configuration.addJarNames(jarNames);
-        configRegion.put(group, configuration);
         String groupDir = FilenameUtils.concat(configDirPath, group);
         writeJarFiles(groupDir, jarNames, jarBytes);
+
+        // update the record after writing the jars to the file system, since the listener
+        // will need the jars on file to upload to other locators.
+        configuration.addJarNames(jarNames);
+        configRegion.put(group, configuration);
       }
     } catch (Exception e) {
       success = false;
@@ -219,7 +217,7 @@ public class SharedConfiguration {
       XmlUtils.addNewNode(doc, xmlEntity);
       configuration.setCacheXmlContent(XmlUtils.prettyXml(doc));
       configRegion.put(group, configuration);
-      writeConfig(configuration);
+      //writeConfig(configuration);
     }
   }
 
@@ -248,33 +246,9 @@ public class SharedConfiguration {
 
         Map<String, Configuration> sharedConfigMap = this.readSharedConfigurationFromDisk();
         final DM dm = cache.getDistributedSystem().getDistributionManager();
-
-        if (dm.getNormalDistributionManagerIds().isEmpty()) {
-          Set<DistributedMember> locatorsWithSC = new HashSet<DistributedMember>(
-              dm.getAllHostedLocatorsWithSharedConfiguration().keySet());
-
-          // Send the config to other locators which host the shared configuration.
-          if (!locatorsWithSC.isEmpty()) {
-            final ImportSharedConfigurationArtifactsFunction fn =
-                new ImportSharedConfigurationArtifactsFunction();
-            final Date date = new Date();
-            String zipFileName = CliStrings.format(CliStrings.EXPORT_SHARED_CONFIG__FILE__NAME,
-                new Timestamp(date.getTime()).toString());
-            try {
-              ZipUtils.zip(getSharedConfigurationDirPath(), zipFileName);
-              File zipFile = new File(zipFileName);
-              byte[] zipBytes = FileUtils.readFileToByteArray(zipFile);
-              Object[] args = new Object[] {zipFileName, zipBytes};
-              // Make sure we wait for the result. The fn also does a clear on the config
-              // region so there is a race with the clear below.
-              CliUtil.executeFunction(fn, args, locatorsWithSC).getResult();
-            } catch (Exception e) {
-              logger.error(e.getMessage(), e);
-            }
-          }
-        }
         // Clear the configuration region and load the configuration read from the 'shared_config'
         // directory
+        // on region entry create/update, it will upload the jars to all other locators
         configRegion.clear();
         configRegion.putAll(sharedConfigMap);
       } finally {
@@ -284,21 +258,9 @@ public class SharedConfiguration {
       // Write out the existing configuration into the 'shared_config' directory
       // And get deployed jars from other locators.
       lockSharedConfiguration();
-      putSecurityPropsIntoClusterConfig(configRegion);
-
       try {
-        Set<Entry<String, Configuration>> configEntries = configRegion.entrySet();
-
-        for (Entry<String, Configuration> configEntry : configEntries) {
-          Configuration configuration = configEntry.getValue();
-          try {
-            this.writeConfig(configuration);
-          } catch (Exception e) {
-            logger.info(e.getMessage(), e);
-          }
-        }
-        logger.info("Completed writing the shared configuration to 'cluster_config' directory");
-        this.getAllJarsFromOtherLocators();
+        // on region entry create/update, it should download missing jars from other locators
+        putSecurityPropsIntoClusterConfig(configRegion);
       } finally {
         unlockSharedConfiguration();
       }
@@ -400,7 +362,7 @@ public class SharedConfiguration {
           XmlUtils.deleteNode(doc, xmlEntity);
           configuration.setCacheXmlContent(XmlUtils.prettyXml(doc));
           configRegion.put(group, configuration);
-          writeConfig(configuration);
+          //writeConfig(configuration);
         }
       }
     }
@@ -436,7 +398,7 @@ public class SharedConfiguration {
       // Change the xml content of the configuration and put it the config region
       configuration.setCacheXmlContent(XmlUtils.prettyXml(doc));
       configRegion.put(group, configuration);
-      writeConfig(configuration);
+      //writeConfig(configuration);
     }
   }
 
@@ -569,7 +531,7 @@ public class SharedConfiguration {
       }
       configuration.getGemfireProperties().putAll(properties);
       configRegion.put(group, configuration);
-      writeConfig(configuration);
+      //writeConfig(configuration);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DeployCommands.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DeployCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DeployCommands.java
index a5302ea..6cb92d4 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DeployCommands.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DeployCommands.java
@@ -107,6 +107,7 @@ public final class DeployCommands extends AbstractCommandsSupport implements Com
         return e.getResult();
       }
 
+      // this deploys the jars to all the matching servers
       ResultCollector<?, ?> resultCollector = CliUtil.executeFunction(this.deployFunction,
           new Object[] {jarNames, jarBytes}, targetMembers);
 
@@ -133,8 +134,6 @@ public final class DeployCommands extends AbstractCommandsSupport implements Com
         }
       }
 
-
-
       if (!accumulatedData) {
         // This really should never happen since if a JAR file is already deployed a result is
         // returned indicating that.
@@ -142,10 +141,10 @@ public final class DeployCommands extends AbstractCommandsSupport implements Com
       }
 
       Result result = ResultBuilder.buildResult(tabularData);
-      if (tabularData.getStatus().equals(Status.OK)) {
-        result.setCommandPersisted(
-            (new SharedConfigurationWriter()).addJars(jarNames, jarBytes, groups));
-      }
+      // should update the cc even if there is no running server
+      result.setCommandPersisted(
+          (new SharedConfigurationWriter()).addJars(jarNames, jarBytes, groups));
+
       return result;
     } catch (NotAuthorizedException e) {
       // for NotAuthorizedException, will catch this later in the code
@@ -217,11 +216,11 @@ public final class DeployCommands extends AbstractCommandsSupport implements Com
         return ResultBuilder.createInfoResult(CliStrings.UNDEPLOY__NO_JARS_FOUND_MESSAGE);
       }
 
+      // should update cc even if there is no running servers
       Result result = ResultBuilder.buildResult(tabularData);
-      if (tabularData.getStatus().equals(Status.OK)) {
-        result.setCommandPersisted((new SharedConfigurationWriter())
-            .deleteJars(jars == null ? null : jars.split(","), groups));
-      }
+      result.setCommandPersisted((new SharedConfigurationWriter())
+          .deleteJars(jars == null ? null : jars.split(","), groups));
+
       return result;
     } catch (VirtualMachineError e) {
       SystemFailure.initiateFailure(e);

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
index 8d46773..64bd5ca 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
@@ -14,14 +14,6 @@
  */
 package org.apache.geode.management.internal.cli.commands;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.internal.cache.GemFireCacheImpl;
@@ -44,11 +36,18 @@ import org.apache.geode.management.internal.cli.result.TabularResultData;
 import org.apache.geode.management.internal.security.ResourceOperation;
 import org.apache.geode.security.ResourcePermission.Operation;
 import org.apache.geode.security.ResourcePermission.Resource;
-
 import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
 import org.springframework.shell.core.annotation.CliCommand;
 import org.springframework.shell.core.annotation.CliOption;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /****
  * Commands for the shared configuration
  *
@@ -127,10 +126,10 @@ public class ExportImportSharedConfigurationCommands extends AbstractCommandsSup
       mandatory = true, help = CliStrings.IMPORT_SHARED_CONFIG__ZIP__HELP) String zip) {
 
     GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
+    Set<DistributedMember>  servers = CliUtil.getAllNormalMembers(cache);
 
-    if (!CliUtil.getAllNormalMembers(cache).isEmpty()) {
-      return ResultBuilder
-          .createGemFireErrorResult(CliStrings.IMPORT_SHARED_CONFIG__CANNOT__IMPORT__MSG);
+    for(DistributedMember server: servers){
+      // run a function to check if there is data hosted in the region, if yes, error out.
     }
 
     Set<DistributedMember> locators = new HashSet<DistributedMember>(
@@ -154,40 +153,30 @@ public class ExportImportSharedConfigurationCommands extends AbstractCommandsSup
     TabularResultData errorTable = ResultBuilder.createTabularResultData();
 
     boolean success = false;
-    boolean copySuccess = false;
-
-    ResultCollector<?, ?> rc =
-        CliUtil.executeFunction(importSharedConfigurationFunction, args, locators);
-    List<CliFunctionResult> functionResults =
-        CliFunctionResult.cleanResults((List<CliFunctionResult>) rc.getResult());
-
-    for (CliFunctionResult functionResult : functionResults) {
-      if (!functionResult.isSuccessful()) {
-        errorTable.accumulate(CliStrings.LOCATOR_HEADER, functionResult.getMemberIdOrName());
-        errorTable.accumulate(CliStrings.ERROR__MSG__HEADER, functionResult.getMessage());
-      } else {
-        copySuccess = true;
-      }
-    }
 
-    if (!copySuccess) {
-      errorTable.setStatus(Result.Status.ERROR);
-      return ResultBuilder.buildResult(errorTable);
-    }
-
-    errorTable = ResultBuilder.createTabularResultData();
+    ResultCollector<?, ?> rc = null;
+    List<CliFunctionResult> functionResults = null;
 
+    // only run importSharedConfigurationFunction on one locator
     for (DistributedMember locator : locators) {
-      rc = CliUtil.executeFunction(loadSharedConfiguration, args, locator);
+      rc = CliUtil.executeFunction(importSharedConfigurationFunction, args, locator);
       functionResults = (List<CliFunctionResult>) rc.getResult();
       CliFunctionResult functionResult = functionResults.get(0);
       if (functionResult.isSuccessful()) {
         success = true;
         infoData.addLine(functionResult.getMessage());
         break;
-      } else {
-        errorTable.accumulate(CliStrings.LOCATOR_HEADER, functionResult.getMemberIdOrName());
-        errorTable.accumulate(CliStrings.ERROR__MSG__HEADER, functionResult.getMessage());
+      }
+    }
+
+    if(success) {
+      for (DistributedMember server : servers) {
+        // run a function to reload the cc on the server
+        // this function should (part of GemfireCacheImpl.initialize):
+        // 1 request cc from a locator,
+        // 2, apply runtimeProperties
+        // 3. reload the cache.xml
+        // 4. deploy the jars
       }
     }
 

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportSharedConfigurationFunction.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportSharedConfigurationFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportSharedConfigurationFunction.java
index 821e04b..72985e3 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportSharedConfigurationFunction.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportSharedConfigurationFunction.java
@@ -14,12 +14,8 @@
  */
 package org.apache.geode.management.internal.cli.functions;
 
-import java.io.File;
-import java.util.UUID;
-
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
-
 import org.apache.geode.cache.execute.FunctionAdapter;
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.distributed.internal.InternalLocator;
@@ -28,6 +24,9 @@ import org.apache.geode.internal.InternalEntity;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.configuration.utils.ZipUtils;
 
+import java.io.File;
+import java.util.UUID;
+
 public class ExportSharedConfigurationFunction extends FunctionAdapter implements InternalEntity {
 
   private static final long serialVersionUID = 1L;
@@ -45,6 +44,7 @@ public class ExportSharedConfigurationFunction extends FunctionAdapter implement
 
       String targetFilePath = FilenameUtils.concat(sc.getSharedConfigurationDirPath(), zipFileName);
       try {
+        //Todo: write the xml and properties file to the configDir
         ZipUtils.zip(sc.getSharedConfigurationDirPath(), targetFilePath);
         File zippedSharedConfig = new File(targetFilePath);
         byte[] zippedConfigData = FileUtils.readFileToByteArray(zippedSharedConfig);

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ImportSharedConfigurationArtifactsFunction.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ImportSharedConfigurationArtifactsFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ImportSharedConfigurationArtifactsFunction.java
index 883a036..0f17647 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ImportSharedConfigurationArtifactsFunction.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ImportSharedConfigurationArtifactsFunction.java
@@ -14,7 +14,6 @@
  */
 package org.apache.geode.management.internal.cli.functions;
 
-import java.io.File;
 import org.apache.commons.io.FileUtils;
 import org.apache.geode.cache.execute.FunctionAdapter;
 import org.apache.geode.cache.execute.FunctionContext;
@@ -25,6 +24,8 @@ import org.apache.geode.management.internal.cli.CliUtil;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.configuration.utils.ZipUtils;
 
+import java.io.File;
+
 /******
  * This function copies the zipped shared configuration, renames the existing shared configuration
  * directory and unzips the shared configuration.
@@ -54,8 +55,14 @@ public class ImportSharedConfigurationArtifactsFunction extends FunctionAdapter
         FileUtils.writeByteArrayToFile(zippedSharedConfiguration, zipFileData);
         ZipUtils.unzip(zipFileName, sc.getSharedConfigurationDirPath());
 
-        CliFunctionResult cliFunctionResult = new CliFunctionResult(memberName, true,
-            CliStrings.IMPORT_SHARED_CONFIG__ARTIFACTS__COPIED);
+        // load it from the disk
+        sc.loadSharedConfigurationFromDisk();
+
+        // do we need to delete the xml/properites? this should just be a stale copy.
+        // remember in the ExportSharedConfigurationFunction, we write them to the file system again
+
+        CliFunctionResult cliFunctionResult =
+            new CliFunctionResult(memberName, true, CliStrings.IMPORT_SHARED_CONFIG__SUCCESS__MSG);
         context.getResultSender().lastResult(cliFunctionResult);
       } catch (Exception e) {
         CliFunctionResult result =

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/main/java/org/apache/geode/management/internal/configuration/SharedConfigurationWriter.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/SharedConfigurationWriter.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/SharedConfigurationWriter.java
index 3af5587..a93e7bb 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/SharedConfigurationWriter.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/SharedConfigurationWriter.java
@@ -14,13 +14,6 @@
  */
 package org.apache.geode.management.internal.configuration;
 
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.logging.log4j.Logger;
-
 import org.apache.geode.cache.execute.Function;
 import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.distributed.DistributedMember;
@@ -34,6 +27,12 @@ import org.apache.geode.management.internal.configuration.functions.AddXmlEntity
 import org.apache.geode.management.internal.configuration.functions.DeleteJarFunction;
 import org.apache.geode.management.internal.configuration.functions.DeleteXmlEntityFunction;
 import org.apache.geode.management.internal.configuration.functions.ModifyPropertiesFunction;
+import org.apache.logging.log4j.Logger;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
 
 /***
  * Class for writing configuration changes to the Shared Configuration at the Locator(s). This class
@@ -109,7 +108,7 @@ public class SharedConfigurationWriter {
     args[0] = jarNames;
     args[1] = jarBytes;
     args[2] = groups;
-    return saveConfigChangesAllLocators(saveJarFunction, args);
+    return saveConfigChanges(saveJarFunction, args);
   }
 
   // /****
@@ -122,7 +121,7 @@ public class SharedConfigurationWriter {
     Object[] args = new Object[3];
     args[0] = jarNames;
     args[1] = groups;
-    return saveConfigChangesAllLocators(deleteJarFunction, args);
+    return saveConfigChanges(deleteJarFunction, args);
   }
 
 

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/main/java/org/apache/geode/management/internal/configuration/callbacks/ConfigurationChangeListener.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/callbacks/ConfigurationChangeListener.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/callbacks/ConfigurationChangeListener.java
index c08ba92..10e3c3c 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/callbacks/ConfigurationChangeListener.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/callbacks/ConfigurationChangeListener.java
@@ -38,19 +38,27 @@ public class ConfigurationChangeListener extends CacheListenerAdapter<String, Co
   @Override
   public void afterUpdate(EntryEvent<String, Configuration> event) {
     super.afterUpdate(event);
-    writeToFileSystem(event);
+    uploadDownloadJars(event);
   }
 
   @Override
   public void afterCreate(EntryEvent<String, Configuration> event) {
     super.afterCreate(event);
-    writeToFileSystem(event);
+    uploadDownloadJars(event);
   }
 
-  private void writeToFileSystem(EntryEvent<String, Configuration> event) {
+  // when a new jar is added, if it exist in the current locator, upload to other locators,
+  // otherwise, download from other locators.
+  // when a jar is removed, remove it from all the locators' file system
+  private void uploadDownloadJars(EntryEvent<String, Configuration> event) {
+    String group = event.getKey();
     Configuration newConfig = (Configuration) event.getNewValue();
+    Configuration oldConfig = (Configuration) event.getOldValue();
+    if(oldConfig!=null){
+
+    }
     try {
-      sharedConfig.writeConfig(newConfig);
+
     } catch (Exception e) {
       logger.info(
           "Exception occurred while writing the configuration changes to the filesystem: {}",

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDUnitTest.java
new file mode 100644
index 0000000..6b60c0e
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDUnitTest.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geode.management.internal.configuration;
+
+import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.ServerStarterRule;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Properties;
+
+public class ClusterConfigDUnitTest extends JUnit4DistributedTestCase {
+  @Rule
+  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+
+  @Test
+  public void test() throws Exception {
+    Properties locatorProps = new Properties();
+    //locatorProps.setProperty(LOAD_CLUSTER_CONFIGURATION_FROM_DIR, "true");
+    lsRule.getLocatorVM(0, locatorProps);
+
+    ServerStarterRule server = new ServerStarterRule(new Properties());
+    server.startServer(lsRule.getPort(0));
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/34ddd5e0/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigIntegrationTest.java
new file mode 100644
index 0000000..9c052ca
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigIntegrationTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geode.management.internal.configuration;
+
+import static org.apache.geode.distributed.ConfigurationProperties.LOAD_CLUSTER_CONFIGURATION_FROM_DIR;
+
+import org.apache.geode.test.dunit.rules.LocatorStarterRule;
+import org.junit.Test;
+
+import java.util.Properties;
+
+public class ClusterConfigIntegrationTest {
+
+  @Test
+  public void test() throws Exception {
+    LocatorStarterRule lRule = new LocatorStarterRule(new Properties(){{
+      setProperty(LOAD_CLUSTER_CONFIGURATION_FROM_DIR, "true");
+    }});
+
+    lRule.startLocator();
+  }
+}