package org.radargun.service; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import org.radargun.logging.Log; import org.radargun.logging.LogFactory; import org.radargun.traits.Clustered; /** * @author Radim Vansa <rvansa@redhat.com> */ public class InfinispanServerClustered implements Clustered { protected final Log log = LogFactory.getLog(getClass()); protected final InfinispanServerService service; protected final List<Membership> membershipHistory = new ArrayList<>(); protected String lastMembers = null; public InfinispanServerClustered(InfinispanServerService service) { this.service = service; service.schedule(new Runnable() { @Override public void run() { checkAndUpdateMembership(); } }, service.viewCheckPeriod); } @Override public boolean isCoordinator() { if (!service.lifecycle.isRunning()) { return false; } try { MBeanServerConnection connection = service.connection; if (connection == null) return false; ObjectName cacheManagerName = new ObjectName(getCacheManagerObjectName(service.jmxDomain, service.cacheManagerName)); String nodeAddress = (String) connection.getAttribute(cacheManagerName, getNodeAddressAttribute()); String clusterMembers = (String) connection.getAttribute(cacheManagerName, getClusterMembersAttribute()); return clusterMembers.startsWith("[" + nodeAddress); } catch (Exception e) { log.error("Failed to retrieve data from JMX", e); } return false; } protected Collection<Member> checkAndUpdateMembership() { if (!service.lifecycle.isRunning()) { synchronized (this) { if (!membershipHistory.isEmpty() && membershipHistory.get(membershipHistory.size() - 1).members.size() > 0) { lastMembers = null; membershipHistory.add(Membership.empty()); } } return Collections.EMPTY_LIST; } try { MBeanServerConnection connection = service.connection; if (connection == null) return null; ObjectName cacheManagerName = new ObjectName(getCacheManagerObjectName(service.jmxDomain, service.cacheManagerName)); String membersString = (String) connection.getAttribute(cacheManagerName, getClusterMembersAttribute()); String nodeAddress = (String) connection.getAttribute(cacheManagerName, getNodeAddressAttribute()); synchronized (this) { if (lastMembers != null && lastMembers.equals(membersString)) { return membershipHistory.get(membershipHistory.size() - 1).members; } String[] nodes; if (!membersString.startsWith("[") || !membersString.endsWith("]")) { nodes = new String[] {membersString}; } else { nodes = membersString.substring(1, membersString.length() - 1).split(",", 0); } lastMembers = membersString; ArrayList<Member> members = new ArrayList<>(); for (int i = 0; i < nodes.length; ++i) { members.add(new Member(nodes[i].trim(), nodes[i].equals(nodeAddress), i == 0)); } membershipHistory.add(Membership.create(members)); return members; } } catch (Exception e) { log.error("Failed to retrieve data from JMX", e); return null; } } @Override public Collection<Member> getMembers() { return checkAndUpdateMembership(); } @Override public synchronized List<Membership> getMembershipHistory() { return new ArrayList<>(membershipHistory); } protected String getClusterMembersAttribute() { return "clusterMembers"; } protected String getNodeAddressAttribute() { return "nodeAddress"; } protected String getClusterSizeAttribute() { return "clusterSize"; } private String getCacheManagerObjectName(String jmxDomain, String managerName) { return String.format("%s:type=CacheManager,name=\"%s\",component=CacheManager", jmxDomain, managerName); } }