X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fswitchmanager%2Fimplementation%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fswitchmanager%2Finternal%2FSwitchManagerImpl.java;h=9ff3f9185053076398a6bd601b5dc8f56bae2b3f;hp=443c7a42ab7da517fbb8df65082c36d1a220a79e;hb=90187806b89850300203ef904223c091262fcf3c;hpb=7c3362df780f30a47d0f6a7b7695360bbb5513bc diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java index 443c7a42ab..9ff3f91850 100644 --- a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java +++ b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java @@ -40,6 +40,7 @@ import org.opendaylight.controller.clustering.services.IClusterServices; import org.opendaylight.controller.configuration.IConfigurationContainerAware; import org.opendaylight.controller.sal.core.Bandwidth; import org.opendaylight.controller.sal.core.Config; +import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Description; import org.opendaylight.controller.sal.core.MacAddress; import org.opendaylight.controller.sal.core.Name; @@ -52,14 +53,13 @@ import org.opendaylight.controller.sal.core.Tier; import org.opendaylight.controller.sal.core.UpdateType; import org.opendaylight.controller.sal.inventory.IInventoryService; import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates; -import org.opendaylight.controller.sal.utils.HexEncode; -import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.sal.utils.GlobalConstants; +import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.IObjectReader; import org.opendaylight.controller.sal.utils.ObjectReader; import org.opendaylight.controller.sal.utils.ObjectWriter; -import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.switchmanager.IInventoryListener; import org.opendaylight.controller.switchmanager.ISpanAware; import org.opendaylight.controller.switchmanager.ISwitchManager; @@ -95,7 +95,7 @@ CommandProvider { private final List spanNodeConnectors = new CopyOnWriteArrayList(); private ConcurrentMap subnets; // set of Subnets keyed by the InetAddress private ConcurrentMap subnetsConfigList; - private ConcurrentMap spanConfigList; + private ConcurrentMap spanConfigList; private ConcurrentMap nodeConfigList; // manually configured parameters for the node like name and tier private ConcurrentMap configSaveEvent; private ConcurrentMap> nodeProps; // properties are maintained in global container only @@ -114,6 +114,7 @@ CommandProvider { private IClusterContainerServices clusterContainerService = null; private String containerName = null; private boolean isDefaultContainer = true; + private static final int REPLACE_RETRY = 1; public enum ReasonCode { SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF( @@ -174,7 +175,7 @@ CommandProvider { public void startUp() { // Initialize configuration file names - subnetFileName = ROOT + "subnets" + this.getContainerName() + ".conf"; + subnetFileName = ROOT + "subnets_" + this.getContainerName() + ".conf"; spanFileName = ROOT + "spanPorts_" + this.getContainerName() + ".conf"; switchConfigFileName = ROOT + "switchConfig_" + this.getContainerName() + ".conf"; @@ -201,12 +202,12 @@ CommandProvider { } public void shutDown() { - destroyCaches(this.getContainerName()); } @SuppressWarnings("deprecation") private void allocateCaches() { if (this.clusterContainerService == null) { + this.nonClusterObjectCreate(); log.warn("un-initialized clusterContainerService, can't create cache"); return; } @@ -252,7 +253,7 @@ CommandProvider { log.error("\nFailed to get cache for subnetsConfigList"); } - spanConfigList = (ConcurrentMap) clusterContainerService + spanConfigList = (ConcurrentMap) clusterContainerService .getCache("switchmanager.spanConfigList"); if (spanConfigList == null) { log.error("\nFailed to get cache for spanConfigList"); @@ -295,9 +296,9 @@ CommandProvider { } } - void nonClusterObjectCreate() { + private void nonClusterObjectCreate() { subnetsConfigList = new ConcurrentHashMap(); - spanConfigList = new ConcurrentHashMap(); + spanConfigList = new ConcurrentHashMap(); nodeConfigList = new ConcurrentHashMap(); subnets = new ConcurrentHashMap(); configSaveEvent = new ConcurrentHashMap(); @@ -306,26 +307,6 @@ CommandProvider { nodeConnectorNames = new ConcurrentHashMap>(); } - @SuppressWarnings("deprecation") - private void destroyCaches(String container) { - if (this.clusterContainerService == null) { - log.info("un-initialized clusterContainerService, can't create cache"); - return; - } - - clusterContainerService.destroyCache("switchmanager.subnetsConfigList"); - clusterContainerService.destroyCache("switchmanager.spanConfigList"); - clusterContainerService.destroyCache("switchmanager.nodeConfigList"); - clusterContainerService.destroyCache("switchmanager.subnets"); - clusterContainerService.destroyCache("switchmanager.configSaveEvent"); - clusterContainerService.destroyCache("switchmanager.nodeProps"); - clusterContainerService - .destroyCache("switchmanager.nodeConnectorProps"); - clusterContainerService - .destroyCache("switchmanager.nodeConnectorNames"); - nonClusterObjectCreate(); - } - @Override public List getSubnetsConfigList() { return new ArrayList(subnetsConfigList.values()); @@ -391,19 +372,26 @@ CommandProvider { return swList; } - private void updateConfig(SubnetConfig conf, boolean add) { + private Status updateConfig(SubnetConfig conf, boolean add) { if (add) { - subnetsConfigList.put(conf.getName(), conf); + if(subnetsConfigList.putIfAbsent(conf.getName(), conf) != null) { + String msg = "Cluster conflict: Subnet with name " + conf.getName() + "already exists."; + return new Status(StatusCode.CONFLICT, msg); + } } else { subnetsConfigList.remove(conf.getName()); } + return new Status(StatusCode.SUCCESS); } - private void updateDatabase(SubnetConfig conf, boolean add) { - Subnet subnet = subnets.get(conf.getIPnum()); + private Status updateDatabase(SubnetConfig conf, boolean add) { if (add) { - if (subnet == null) { + Subnet subnetCurr = subnets.get(conf.getIPnum()); + Subnet subnet; + if (subnetCurr == null) { subnet = new Subnet(conf); + } else { + subnet = subnetCurr.clone(); } // In case of API3 call we may receive the ports along with the // subnet creation @@ -411,29 +399,38 @@ CommandProvider { Set sp = conf.getSubnetNodeConnectors(); subnet.addNodeConnectors(sp); } - subnets.put(conf.getIPnum(), subnet); - } else { // This is the deletion of the whole subnet - if (subnet == null) { - return; + boolean result = false; + if(subnetCurr == null) { + if(subnets.putIfAbsent(conf.getIPnum(), subnet) == null) { + result = true; + } + } else { + result = subnets.replace(conf.getIPnum(), subnetCurr, subnet); } + if(!result) { + String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPnum(); + return new Status(StatusCode.CONFLICT, msg); + } + } else { // This is the deletion of the whole subnet subnets.remove(conf.getIPnum()); } + return new Status(StatusCode.SUCCESS); } private Status semanticCheck(SubnetConfig conf) { Subnet newSubnet = new Subnet(conf); Set IPs = subnets.keySet(); if (IPs == null) { - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } for (InetAddress i : IPs) { Subnet existingSubnet = subnets.get(i); if ((existingSubnet != null) && !existingSubnet.isMutualExclusive(newSubnet)) { - return new Status(StatusCode.CONFLICT, null); + return new Status(StatusCode.CONFLICT); } } - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } private Status addRemoveSubnet(SubnetConfig conf, boolean add) { @@ -456,13 +453,19 @@ CommandProvider { return rc; } } - // Update Configuration - updateConfig(conf, add); // Update Database - updateDatabase(conf, add); + Status rc = updateDatabase(conf, add); - return new Status(StatusCode.SUCCESS, null); + if (rc.isSuccess()) { + // Update Configuration + rc = updateConfig(conf, add); + if(!rc.isSuccess()) { + updateDatabase(conf, (!add)); + } + } + + return rc; } /** @@ -489,38 +492,77 @@ CommandProvider { @Override public Status addPortsToSubnet(String name, String switchPorts) { - // Update Configuration - SubnetConfig conf = subnetsConfigList.get(name); - if (conf == null) { + SubnetConfig confCurr = subnetsConfigList.get(name); + if (confCurr == null) { return new Status(StatusCode.NOTFOUND, "Subnet does not exist"); } - if (!conf.isValidSwitchPort(switchPorts)) { + if (!confCurr.isValidSwitchPort(switchPorts)) { return new Status(StatusCode.BADREQUEST, "Invalid switchports"); } - conf.addNodeConnectors(switchPorts); + Subnet subCurr = subnets.get(confCurr.getIPnum()); + if (subCurr == null) { + log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum()); + return new Status(StatusCode.NOTFOUND, "Subnet does not exist"); + } // Update Database - Subnet sub = subnets.get(conf.getIPnum()); - Set sp = conf.getNodeConnectors(switchPorts); + Subnet sub = subCurr.clone(); + Set sp = confCurr.getNodeConnectors(switchPorts); sub.addNodeConnectors(sp); - return new Status(StatusCode.SUCCESS, null); + boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub); + if (!subnetsReplace) { + String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name; + return new Status(StatusCode.CONFLICT, msg); + } + + // Update Configuration + SubnetConfig conf = confCurr.clone(); + conf.addNodeConnectors(switchPorts); + boolean result = subnetsConfigList.replace(name, confCurr, conf); + if (!result) { + // TODO: recovery using Transactionality + String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name; + return new Status(StatusCode.CONFLICT, msg); + } + + return new Status(StatusCode.SUCCESS); } @Override public Status removePortsFromSubnet(String name, String switchPorts) { - // Update Configuration - SubnetConfig conf = subnetsConfigList.get(name); - if (conf == null) { + SubnetConfig confCurr = subnetsConfigList.get(name); + if (confCurr == null) { + return new Status(StatusCode.NOTFOUND, "Subnet does not exist"); + } + + Subnet subCurr = subnets.get(confCurr.getIPnum()); + if (subCurr == null) { + log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum()); return new Status(StatusCode.NOTFOUND, "Subnet does not exist"); } - conf.removeNodeConnectors(switchPorts); // Update Database - Subnet sub = subnets.get(conf.getIPnum()); - Set sp = conf.getNodeConnectors(switchPorts); + Subnet sub = subCurr.clone(); + Set sp = confCurr.getNodeConnectors(switchPorts); sub.deleteNodeConnectors(sp); - return new Status(StatusCode.SUCCESS, null); + boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub); + if (!subnetsReplace) { + String msg = "Cluster conflict: Conflict while removing ports from the subnet " + name; + return new Status(StatusCode.CONFLICT, msg); + } + + // Update Configuration + SubnetConfig conf = confCurr.clone(); + conf.removeNodeConnectors(switchPorts); + boolean result = subnetsConfigList.replace(name, confCurr, conf); + if (!result) { + // TODO: recovery using Transactionality + String msg = "Cluster conflict: Conflict while removing ports from " + conf; + return new Status(StatusCode.CONFLICT, msg); + } + + return new Status(StatusCode.SUCCESS); } public String getContainerName() { @@ -554,7 +596,7 @@ CommandProvider { @SuppressWarnings("unchecked") private void loadSubnetConfiguration() { ObjectReader objReader = new ObjectReader(); - ConcurrentMap confList = (ConcurrentMap) objReader + ConcurrentMap confList = (ConcurrentMap) objReader .read(this, subnetFileName); if (confList == null) { @@ -598,37 +640,59 @@ CommandProvider { @Override public void updateSwitchConfig(SwitchConfig cfgObject) { - boolean modeChange = false; + // update default container only + if (!isDefaultContainer) { + return; + } SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId()); + if (sc == null) { + if (nodeConfigList.putIfAbsent(cfgObject.getNodeId(), cfgObject) != null) { + return; + } + } else { + if (!nodeConfigList.replace(cfgObject.getNodeId(), sc, cfgObject)) { + return; + } + } + + boolean modeChange = false; + if ((sc == null) || !cfgObject.getMode().equals(sc.getMode())) { modeChange = true; } - nodeConfigList.put(cfgObject.getNodeId(), cfgObject); try { - // update default container only - if (isDefaultContainer) { - String nodeId = cfgObject.getNodeId(); - Node node = Node.fromString(nodeId); - Map propMap; - if (nodeProps.get(node) != null) { - propMap = nodeProps.get(node); - } else { - propMap = new HashMap(); + String nodeId = cfgObject.getNodeId(); + Node node = Node.fromString(nodeId); + Map propMapCurr = nodeProps.get(node); + Map propMap = new HashMap(); + if (propMapCurr != null) { + for (String s : propMapCurr.keySet()) { + propMap.put(s, propMapCurr.get(s).clone()); } - Property desc = new Description(cfgObject.getNodeDescription()); - propMap.put(desc.getName(), desc); - Property tier = new Tier(Integer.parseInt(cfgObject.getTier())); - propMap.put(tier.getName(), tier); - addNodeProps(node, propMap); + } + Property desc = new Description(cfgObject.getNodeDescription()); + propMap.put(desc.getName(), desc); + Property tier = new Tier(Integer.parseInt(cfgObject.getTier())); + propMap.put(tier.getName(), tier); + + if (propMapCurr == null) { + if (nodeProps.putIfAbsent(node, propMap) != null) { + // TODO rollback using Transactionality + return; + } + } else { + if (!nodeProps.replace(node, propMapCurr, propMap)) { + // TODO rollback using Transactionality + return; + } + } - log.info("Set Node {}'s Mode to {}", nodeId, - cfgObject.getMode()); + log.info("Set Node {}'s Mode to {}", nodeId, cfgObject.getMode()); - if (modeChange) { - notifyModeChange(node, cfgObject.isProactive()); - } + if (modeChange) { + notifyModeChange(node, cfgObject.isProactive()); } } catch (Exception e) { log.debug("updateSwitchConfig: {}", e.getMessage()); @@ -648,7 +712,7 @@ CommandProvider { retS = objWriter.write(new ConcurrentHashMap( subnetsConfigList), subnetFileName); - retP = objWriter.write(new ConcurrentHashMap( + retP = objWriter.write(new ConcurrentHashMap( spanConfigList), spanFileName); retS = objWriter.write(new ConcurrentHashMap( nodeConfigList), switchConfigFileName); @@ -679,17 +743,17 @@ CommandProvider { } // Presence check - if (spanConfigList.containsKey(conf.hashCode())) { + if (spanConfigList.containsKey(conf)) { return new Status(StatusCode.CONFLICT, "Same span config exists"); } - // Update database and notify clients - addSpanPorts(conf.getNode(), conf.getPortArrayList()); - // Update configuration - spanConfigList.put(conf.hashCode(), conf); + if (spanConfigList.putIfAbsent(conf, conf) == null) { + // Update database and notify clients + addSpanPorts(conf.getNode(), conf.getPortArrayList()); + } - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } @Override @@ -697,9 +761,9 @@ CommandProvider { removeSpanPorts(conf.getNode(), conf.getPortArrayList()); // Update configuration - spanConfigList.remove(conf.hashCode()); + spanConfigList.remove(conf); - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } @Override @@ -734,11 +798,12 @@ CommandProvider { return; } - Map propMap; - if (nodeProps.get(node) != null) { - propMap = nodeProps.get(node); - } else { - propMap = new HashMap(); + Map propMapCurr = nodeProps.get(node); + Map propMap = new HashMap(); + if (propMapCurr != null) { + for (String s : propMapCurr.keySet()) { + propMap.put(s, propMapCurr.get(s).clone()); + } } // copy node properties from plugin @@ -754,8 +819,7 @@ CommandProvider { String nodeId = node.toString(); for (SwitchConfig conf : nodeConfigList.values()) { if (conf.getNodeId().equals(nodeId)) { - Property description = new Description( - conf.getNodeDescription()); + Property description = new Description(conf.getNodeDescription()); propMap.put(description.getName(), description); Property tier = new Tier(Integer.parseInt(conf.getTier())); propMap.put(tier.getName(), tier); @@ -764,7 +828,22 @@ CommandProvider { } } } - addNodeProps(node, propMap); + + boolean result = false; + if (propMapCurr == null) { + if (nodeProps.putIfAbsent(node, propMap) == null) { + result = true; + } + } else { + result = nodeProps.replace(node, propMapCurr, propMap); + } + + if (!result) { + log.debug( + "Cluster conflict: Conflict while adding the node properties. Node: {} Properties: {}", + node.getID(), props); + addNodeProps(node, propMap); + } // check if span ports are configed addSpanPorts(node); @@ -799,20 +878,32 @@ CommandProvider { return; } - Map propMap; - if (nodeProps.get(node) != null) { - propMap = nodeProps.get(node); - } else { - propMap = new HashMap(); + Map propMapCurr = nodeProps.get(node); + Map propMap = new HashMap(); + if (propMapCurr != null) { + for (String s : propMapCurr.keySet()) { + propMap.put(s, propMapCurr.get(s).clone()); + } } // copy node properties from plugin - if (props != null) { - for (Property prop : props) { - propMap.put(prop.getName(), prop); + for (Property prop : props) { + propMap.put(prop.getName(), prop); + } + + if (propMapCurr == null) { + if (nodeProps.putIfAbsent(node, propMap) != null) { + log.debug("Cluster conflict: Conflict while updating the node. Node: {} Properties: {}", + node.getID(), props); + addNodeProps(node, propMap); + } + } else { + if (!nodeProps.replace(node, propMapCurr, propMap)) { + log.debug("Cluster conflict: Conflict while updating the node. Node: {} Properties: {}", + node.getID(), props); + addNodeProps(node, propMap); } } - addNodeProps(node, propMap); /* notify node listeners */ notifyNode(node, UpdateType.CHANGED, propMap); @@ -840,7 +931,6 @@ CommandProvider { @Override public void updateNodeConnector(NodeConnector nodeConnector, UpdateType type, Set props) { - Node node = nodeConnector.getNode(); Map propMap = new HashMap(); log.debug("updateNodeConnector: {} type {} props {} for container {}", @@ -860,15 +950,12 @@ CommandProvider { } } else { addNodeConnectorProp(nodeConnector, null); - addNodeProps(node, null); } - // check if span is configed addSpanPort(nodeConnector); break; case REMOVED: removeNodeConnectorAllProps(nodeConnector); - removeNodeProps(node); // clean up span config removeSpanPort(nodeConnector); @@ -897,23 +984,15 @@ CommandProvider { */ @Override public Map getNodeProps(Node node) { - if (isDefaultContainer) { - Map rv = null; - if (this.nodeProps != null) { - rv = this.nodeProps.get(node); - if (rv != null) { - /* make a copy of it */ - rv = new HashMap(rv); - } + Map rv = new HashMap(); + if (this.nodeProps != null) { + rv = this.nodeProps.get(node); + if (rv != null) { + /* make a copy of it */ + rv = new HashMap(rv); } - return rv; - } else { - // get it from default container - ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper - .getInstance(ISwitchManager.class, - GlobalConstants.DEFAULT.toString(), this); - return defaultSwitchManager.getNodeProps(node); } + return rv; } @Override @@ -924,30 +1003,67 @@ CommandProvider { @Override public void setNodeProp(Node node, Property prop) { - /* Get a copy of the property map */ - Map propMap = getNodeProps(node); - if (propMap == null) { - return; - } - propMap.put(prop.getName(), prop); - this.nodeProps.put(node, propMap); + for (int i = 0; i <= REPLACE_RETRY; i++) { + /* Get a copy of the property map */ + Map propMapCurr = getNodeProps(node); + if (propMapCurr == null) { + return; + } + + Map propMap = new HashMap(); + for (String s : propMapCurr.keySet()) { + propMap.put(s, propMapCurr.get(s).clone()); + } + + propMap.put(prop.getName(), prop); + + if (nodeProps.replace(node, propMapCurr, propMap)) { + return; + } + if (!propMapCurr.get(prop.getName()).equals(nodeProps.get(node).get(prop.getName()))) { + log.debug("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID()); + return; + } + } + log.warn("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID()); } @Override public Status removeNodeProp(Node node, String propName) { - Map propMap = getNodeProps(node); - if (propMap != null) { - propMap.remove(propName); - this.nodeProps.put(node, propMap); + for (int i = 0; i <= REPLACE_RETRY; i++) { + Map propMapCurr = getNodeProps(node); + if (propMapCurr != null) { + if (!propMapCurr.containsKey(propName)) { + return new Status(StatusCode.SUCCESS); + } + Map propMap = new HashMap(); + for (String s : propMapCurr.keySet()) { + propMap.put(s, propMapCurr.get(s).clone()); + } + + propMap.remove(propName); + if (nodeProps.replace(node, propMapCurr, propMap)) { + return new Status(StatusCode.SUCCESS); + } + if (!propMapCurr.get(propName).equals(nodeProps.get(node).get(propName))) { + String msg = "Cluster conflict: Unable to remove property " + propName + " for node " + + node.getID(); + return new Status(StatusCode.CONFLICT, msg); + } + + } else { + return new Status(StatusCode.SUCCESS); + } } - return new Status(StatusCode.SUCCESS, null); + String msg = "Cluster conflict: Unable to remove property " + propName + " for node " + node.getID(); + return new Status(StatusCode.CONFLICT, msg); } @Override public Status removeNodeAllProps(Node node) { this.nodeProps.remove(node); - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } @Override @@ -1005,24 +1121,15 @@ CommandProvider { } @Override - public Map getNodeConnectorProps( - NodeConnector nodeConnector) { - if (isDefaultContainer) { - Map rv = null; - if (this.nodeConnectorProps != null) { - rv = this.nodeConnectorProps.get(nodeConnector); - if (rv != null) { - rv = new HashMap(rv); - } + public Map getNodeConnectorProps(NodeConnector nodeConnector) { + Map rv = new HashMap(); + if (this.nodeConnectorProps != null) { + rv = this.nodeConnectorProps.get(nodeConnector); + if (rv != null) { + rv = new HashMap(rv); } - return rv; - } else { - // get it from default container - ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper - .getInstance(ISwitchManager.class, - GlobalConstants.DEFAULT.toString(), this); - return defaultSwitchManager.getNodeConnectorProps(nodeConnector); } + return rv; } @Override @@ -1096,36 +1203,73 @@ CommandProvider { @Override public Status addNodeConnectorProp(NodeConnector nodeConnector, Property prop) { - Map propMap = getNodeConnectorProps(nodeConnector); + Map propMapCurr = getNodeConnectorProps(nodeConnector); + Map propMap = new HashMap(); - if (propMap == null) { - propMap = new HashMap(); + if (propMapCurr != null) { + for (String s : propMapCurr.keySet()) { + propMap.put(s, propMapCurr.get(s).clone()); + } } + String msg = "Cluster conflict: Unable to add NodeConnector Property."; // Just add the nodeConnector if prop is not available (in a non-default // container) if (prop == null) { - nodeConnectorProps.put(nodeConnector, propMap); - return new Status(StatusCode.SUCCESS, null); + if (propMapCurr == null) { + if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) { + return new Status(StatusCode.CONFLICT, msg); + } + } else { + if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) { + return new Status(StatusCode.CONFLICT, msg); + } + } + return new Status(StatusCode.SUCCESS); } propMap.put(prop.getName(), prop); - nodeConnectorProps.put(nodeConnector, propMap); + if (propMapCurr == null) { + if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) { + return new Status(StatusCode.CONFLICT, msg); + } + } else { + if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) { + return new Status(StatusCode.CONFLICT, msg); + } + } if (prop.getName().equals(Name.NamePropName)) { if (nodeConnectorNames != null) { Node node = nodeConnector.getNode(); - Map map = nodeConnectorNames.get(node); - if (map == null) { - map = new HashMap(); + Map mapCurr = nodeConnectorNames.get(node); + Map map = new HashMap(); + if (mapCurr != null) { + for (String s : mapCurr.keySet()) { + try { + map.put(s, new NodeConnector(mapCurr.get(s))); + } catch (ConstructionException e) { + e.printStackTrace(); + } + } } map.put(((Name) prop).getValue(), nodeConnector); - nodeConnectorNames.put(node, map); + if (mapCurr == null) { + if (nodeConnectorNames.putIfAbsent(node, map) != null) { + // TODO: recovery using Transactionality + return new Status(StatusCode.CONFLICT, msg); + } + } else { + if (!nodeConnectorNames.replace(node, mapCurr, map)) { + // TODO: recovery using Transactionality + return new Status(StatusCode.CONFLICT, msg); + } + } } } - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } /** @@ -1138,32 +1282,53 @@ CommandProvider { * @return success or failed reason */ @Override - public Status removeNodeConnectorProp(NodeConnector nodeConnector, - String propName) { - Map propMap = getNodeConnectorProps(nodeConnector); + public Status removeNodeConnectorProp(NodeConnector nodeConnector, String propName) { + Map propMapCurr = getNodeConnectorProps(nodeConnector); - if (propMap == null) { + if (propMapCurr == null) { /* Nothing to remove */ - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); + } + + Map propMap = new HashMap(); + + for (String s : propMapCurr.keySet()) { + propMap.put(s, propMapCurr.get(s).clone()); } propMap.remove(propName); - nodeConnectorProps.put(nodeConnector, propMap); + boolean result = nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap); + String msg = "Cluster conflict: Unable to remove NodeConnector property."; + if (!result) { + return new Status(StatusCode.CONFLICT, msg); + } - if (nodeConnectorNames != null) { - Name name = ((Name) getNodeConnectorProp(nodeConnector, - Name.NamePropName)); - if (name != null) { - Node node = nodeConnector.getNode(); - Map map = nodeConnectorNames.get(node); - if (map != null) { - map.remove(name.getValue()); - nodeConnectorNames.put(node, map); + if (propName.equals(Name.NamePropName)) { + if (nodeConnectorNames != null) { + Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName)); + if (name != null) { + Node node = nodeConnector.getNode(); + Map mapCurr = nodeConnectorNames.get(node); + if (mapCurr != null) { + Map map = new HashMap(); + for (String s : mapCurr.keySet()) { + try { + map.put(s, new NodeConnector(mapCurr.get(s))); + } catch (ConstructionException e) { + e.printStackTrace(); + } + } + map.remove(name.getValue()); + if (!nodeConnectorNames.replace(node, mapCurr, map)) { + // TODO: recovery using Transactionality + return new Status(StatusCode.CONFLICT, msg); + } + } } } } - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } /** @@ -1176,20 +1341,31 @@ CommandProvider { @Override public Status removeNodeConnectorAllProps(NodeConnector nodeConnector) { if (nodeConnectorNames != null) { - Name name = ((Name) getNodeConnectorProp(nodeConnector, - Name.NamePropName)); + Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName)); if (name != null) { Node node = nodeConnector.getNode(); - Map map = nodeConnectorNames.get(node); - if (map != null) { + Map mapCurr = nodeConnectorNames.get(node); + if (mapCurr != null) { + Map map = new HashMap(); + for (String s : mapCurr.keySet()) { + try { + map.put(s, new NodeConnector(mapCurr.get(s))); + } catch (ConstructionException e) { + e.printStackTrace(); + } + } map.remove(name.getValue()); - nodeConnectorNames.put(node, map); + if (!nodeConnectorNames.replace(node, mapCurr, map)) { + log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.", + nodeConnector.getID()); + } } + } } nodeConnectorProps.remove(nodeConnector); - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } /** @@ -1334,17 +1510,25 @@ CommandProvider { return; } - nodeProps = this.inventoryService.getNodeProps(); - Set nodeSet = nodeProps.keySet(); - if (nodeSet != null) { - for (Node node : nodeSet) { - log.debug("getInventories: {} added for container {}", - new Object[] { node, containerName }); - addNode(node, null); + Map> nodeProp = this.inventoryService.getNodeProps(); + for (Map.Entry> entry : nodeProp.entrySet()) { + Node node = entry.getKey(); + log.debug("getInventories: {} added for container {}", new Object[] { node, containerName }); + Map propMap = entry.getValue(); + Set props = new HashSet(); + for (Property property : propMap.values()) { + props.add(property); } + addNode(node, props); } - nodeConnectorProps = inventoryService.getNodeConnectorProps(); + Map> nodeConnectorProp = this.inventoryService.getNodeConnectorProps(); + for (Map.Entry> entry : nodeConnectorProp.entrySet()) { + Map propMap = entry.getValue(); + for (Property property : propMap.values()) { + addNodeConnectorProp(entry.getKey(), property); + } + } } private void clearInventories() { @@ -1455,7 +1639,13 @@ CommandProvider { if (nodeSet == null) { return; } + List nodeArray = new ArrayList(); for (Node node : nodeSet) { + nodeArray.add(node.toString()); + } + Collections.sort(nodeArray); + for (String str: nodeArray) { + Node node = Node.fromString(str); Description desc = ((Description) getNodeProp(node, Description.propertyName)); Tier tier = ((Tier) getNodeProp(node, Tier.TierPropName)); @@ -1670,10 +1860,10 @@ CommandProvider { /* * Add span configuration to local cache and notify clients */ - private void addSpanPorts(Node node, List nodeConncetors) { + private void addSpanPorts(Node node, List nodeConnectors) { List ncLists = new ArrayList(); - for (NodeConnector nodeConnector : nodeConncetors) { + for (NodeConnector nodeConnector : nodeConnectors) { if (!spanNodeConnectors.contains(nodeConnector)) { ncLists.add(nodeConnector); } @@ -1691,19 +1881,25 @@ CommandProvider { } } - private void addSpanPort(NodeConnector nodeConncetor) { - List ncLists = new ArrayList(); - ncLists.add(nodeConncetor); - addSpanPorts(nodeConncetor.getNode(), ncLists); + private void addSpanPort(NodeConnector nodeConnector) { + // only add if span is configured on this nodeConnector + for (SpanConfig conf : getSpanConfigList(nodeConnector.getNode())) { + if (conf.getPortArrayList().contains(nodeConnector)) { + List ncLists = new ArrayList(); + ncLists.add(nodeConnector); + addSpanPorts(nodeConnector.getNode(), ncLists); + return; + } + } } /* * Remove span configuration to local cache and notify clients */ - private void removeSpanPorts(Node node, List nodeConncetors) { + private void removeSpanPorts(Node node, List nodeConnectors) { List ncLists = new ArrayList(); - for (NodeConnector nodeConnector : nodeConncetors) { + for (NodeConnector nodeConnector : nodeConnectors) { if (spanNodeConnectors.contains(nodeConnector)) { ncLists.add(nodeConnector); } @@ -1721,10 +1917,12 @@ CommandProvider { } } - private void removeSpanPort(NodeConnector nodeConncetor) { - List ncLists = new ArrayList(); - ncLists.add(nodeConncetor); - removeSpanPorts(nodeConncetor.getNode(), ncLists); + private void removeSpanPort(NodeConnector nodeConnector) { + if (spanNodeConnectors.contains(nodeConnector)) { + List ncLists = new ArrayList(); + ncLists.add(nodeConnector); + removeSpanPorts(nodeConnector.getNode(), ncLists); + } } private void addNodeProps(Node node, Map propMap) {