/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.mobicents.tools.sip.balancer; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.mobicents.tools.heartbeat.api.Node; public class ClusterSubdomainAffinityAlgorithm extends CallIDAffinityBalancerAlgorithm { private static Logger logger = Logger.getLogger(ClusterSubdomainAffinityAlgorithm.class.getCanonicalName()); protected ConcurrentHashMap<String, List<String>> nodeToNodeGroup = new ConcurrentHashMap<String, List<String>>(); protected Node selectNewNode(Node node, String callId,Boolean isIpV6) { if(logger.isDebugEnabled()) { logger.debug("The assigned node has died. This is the dead node: " + node); } Node oldNode = node; List<String> alternativeNodes = nodeToNodeGroup.get(oldNode.getIp()); //for(Node check : invocationContext.nodes) { for(Node check : invocationContext.sipNodeMap(isIpV6).values()) { for(String alt : alternativeNodes) if(check.getIp().equals(alt)) { groupedFailover(oldNode, check); logger.info("Grouped failover to partner node from " + oldNode + " to " + check); return check; } } logger.info("No alternatives found for " + oldNode + " from " + alternativeNodes); return super.selectNewNode(oldNode, callId, isIpV6); } public void init() { super.init(); String subclusterMap = getConfiguration().getSipConfiguration().getAlgorithmConfiguration().getSubclusterMap(); logger.info("Subcluster map: " + subclusterMap); loadSubclusters(subclusterMap); logger.info("Grouped failover is set to " + this.groupedFailover); } public void loadSubclusters(String subclustersString) { ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<String, List<String>>(); if(subclustersString != null) { subclustersString = subclustersString.replaceAll(" ", ""); String[] groups = subclustersString.split("\\)\\("); for(int q=0; q<groups.length; q++) { String group = groups[q]; group = group.replaceAll("\\(", "").replaceAll("\\)",""); String[] hosts = group.split(","); LinkedList<String> hostGroupList = new LinkedList<String>(); for(String host:hosts) { if(host.length()>0) { if(hostGroupList.contains(host)) { throw new RuntimeException("Duplicate host " + host + " in " + hosts); } hostGroupList.add(host); } } for(String host:hosts) { List<String> tmp = new LinkedList<String>(hostGroupList); tmp.remove(host); map.put(host, tmp); } } } nodeToNodeGroup = map; } public String dumpSubcluster() { String result = ""; for(String host:nodeToNodeGroup.keySet()) { String mapped = host + ": " + nodeToNodeGroup.get(host); result += mapped + "\n"; } return result; } public void configurationChanged() { super.configurationChanged(); try { loadSubclusters(getConfiguration().getSipConfiguration().getAlgorithmConfiguration().getSubclusterMap()); logger.info("Subclusters reloaded. The groups are as follows:" + dumpSubcluster()); } catch (Exception e) { logger.error("Subcluster changes were unsuccesful", e); } } }