Michael Blow has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/2007

Change subject: [ASTERIXDB-2091][HYR][CLUS] Fix unsafe concurrent access to 
config on NC registration
......................................................................

[ASTERIXDB-2091][HYR][CLUS] Fix unsafe concurrent access to config on NC 
registration

Change-Id: I399d26d128794a0a52eff419f59ca28d64b17375
---
M 
hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java
1 file changed, 11 insertions(+), 8 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/07/2007/1

diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java
index 2e04e13..8675604 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java
@@ -34,6 +34,7 @@
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -66,19 +67,21 @@
     private static final Logger LOGGER = 
Logger.getLogger(ConfigManager.class.getName());
 
     private HashSet<IOption> registeredOptions = new HashSet<>();
-    private HashMap<IOption, Object> definedMap = new HashMap<>();
-    private HashMap<IOption, Object> defaultMap = new HashMap<>();
+    private ConcurrentHashMap<IOption, Object> definedMap = new 
ConcurrentHashMap<>();
+    private ConcurrentHashMap<IOption, Object> defaultMap = new 
ConcurrentHashMap<>();
     private CompositeMap<IOption, Object> configurationMap = new 
CompositeMap<>(definedMap, defaultMap,
             new NoOpMapMutator());
     private EnumMap<Section, Map<String, IOption>> sectionMap = new 
EnumMap<>(Section.class);
-    private TreeMap<String, Map<IOption, Object>> nodeSpecificMap = new 
TreeMap<>();
+    @SuppressWarnings("squid:S1948") // TreeMap is serializable, and therefore 
so is its synchronized map
+    private Map<String, ConcurrentHashMap<IOption, Object>> nodeSpecificMap = 
Collections
+            .synchronizedMap(new TreeMap<>());
     private transient ArrayListValuedHashMap<IOption, IConfigSetter> 
optionSetters = new ArrayListValuedHashMap<>();
     private final String[] args;
     private ConfigManagerApplicationConfig appConfig = new 
ConfigManagerApplicationConfig(this);
     private Set<String> allSections = new HashSet<>();
     private transient Collection<Consumer<List<String>>> argListeners = new 
ArrayList<>();
     private transient Collection<IOption> iniPointerOptions = new 
ArrayList<>();
-    private transient Collection<Section> cmdLineSections = new ArrayList<>();;
+    private transient Collection<Section> cmdLineSections = new ArrayList<>();
     private transient OptionHandlerFilter usageFilter;
     private transient SortedMap<Integer, List<IConfigurator>> configurators = 
new TreeMap<>();
     private boolean configured;
@@ -164,9 +167,9 @@
         nodeSpecificMap.computeIfAbsent(nodeId, this::createNodeSpecificMap);
     }
 
-    private Map<IOption, Object> createNodeSpecificMap(String nodeId) {
+    private ConcurrentHashMap<IOption, Object> createNodeSpecificMap(String 
nodeId) {
         LOGGER.fine("createNodeSpecificMap: " + nodeId);
-        return Collections.synchronizedMap(new HashMap<>());
+        return new ConcurrentHashMap<>();
     }
 
     @Override
@@ -347,7 +350,7 @@
             if (entry.getKey() == Section.NC) {
                 entry.getValue().values().forEach(option -> getNodeNames()
                         .forEach(node -> 
getOrDefault(getNodeEffectiveMap(node), option, node)));
-                for (Map.Entry<String, Map<IOption, Object>> nodeMap : 
nodeSpecificMap.entrySet()) {
+                for (Map.Entry<String, ConcurrentHashMap<IOption, Object>> 
nodeMap : nodeSpecificMap.entrySet()) {
                     entry.getValue().values()
                             .forEach(option -> getOrDefault(
                                     new CompositeMap<>(nodeMap.getValue(), 
definedMap, new NoOpMapMutator()), option,
@@ -455,7 +458,7 @@
                 ini.add(option.section().sectionName(), option.ini(), 
option.type().serializeToIni(entry.getValue()));
             }
         }
-        for (Map.Entry<String, Map<IOption, Object>> nodeMapEntry : 
nodeSpecificMap.entrySet()) {
+        for (Map.Entry<String, ConcurrentHashMap<IOption, Object>> 
nodeMapEntry : nodeSpecificMap.entrySet()) {
             String section = Section.NC.sectionName() + "/" + 
nodeMapEntry.getKey();
             for (Map.Entry<IOption, Object> entry : 
nodeMapEntry.getValue().entrySet()) {
                 if (entry.getValue() != null) {

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/2007
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I399d26d128794a0a52eff419f59ca28d64b17375
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Michael Blow <[email protected]>

Reply via email to