|
14 | 14 | import java.util.Collections; |
15 | 15 | import java.util.Enumeration; |
16 | 16 | import java.util.HashMap; |
| 17 | +import java.util.HashSet; |
17 | 18 | import java.util.Map; |
18 | 19 | import java.util.Objects; |
19 | 20 | import java.util.Optional; |
@@ -102,7 +103,12 @@ public class OperatorRestServer { |
102 | 103 | /** |
103 | 104 | * The MBean name of the Service MBean. |
104 | 105 | */ |
105 | | - public static final String MBEAN_SERVICE = "%s:" + Registry.SERVICE_TYPE |
| 106 | + public static final String MBEAN_SERVICE = Registry.SERVICE_TYPE + ",name=*,nodeId=*"; |
| 107 | + |
| 108 | + /** |
| 109 | + * The MBean name of the Service MBean pattern. |
| 110 | + */ |
| 111 | + public static final String MBEAN_SERVICE_PATTERN = "%s:" + Registry.SERVICE_TYPE |
106 | 112 | + ",name=%s,nodeId=%d"; |
107 | 113 |
|
108 | 114 | /** |
@@ -133,8 +139,8 @@ public class OperatorRestServer { |
133 | 139 | /** |
134 | 140 | * The MBean attribute to check the state of a partitioned cache service. |
135 | 141 | */ |
136 | | - public static final String[] CACHE_SERVICE_ATTRIBUTES = new String[] {"StorageEnabled", "MemberCount", |
137 | | - "OwnedPartitionsPrimary", "PartitionsAll"}; |
| 142 | + public static final String[] CACHE_SERVICE_ATTRIBUTES = new String[] {"Type", "StorageEnabled", "MemberCount", |
| 143 | + "OwnedPartitionsPrimary", "PartitionsAll", "StorageEnabledCount"}; |
138 | 144 |
|
139 | 145 | /** |
140 | 146 | * The value of the Status HA attribute to signify endangered. |
@@ -545,6 +551,29 @@ boolean isStatusHA(String exclusions) { |
545 | 551 | Cluster cluster = clusterSupplier.get(); |
546 | 552 | if (cluster != null && cluster.isRunning()) { |
547 | 553 | int id = cluster.getLocalMember().getId(); |
| 554 | + |
| 555 | + Set<String> cacheServices = getDistributedCacheServiceNames(); |
| 556 | + Set<String> distributionCoordinators = getPartitionAssignmentMBeans(); |
| 557 | + |
| 558 | + // Ensure we have a DistributionCoordinator for all cache services |
| 559 | + // If the senior just died we might not have one |
| 560 | + if (cacheServices.size() != distributionCoordinators.size()) { |
| 561 | + Set<String> coords = new HashSet<>(); |
| 562 | + for (String s : distributionCoordinators) { |
| 563 | + ObjectName objectName = ObjectName.getInstance(s); |
| 564 | + coords.add(objectName.getKeyProperty("service")); |
| 565 | + } |
| 566 | + for (String name : cacheServices) { |
| 567 | + if (!coords.contains(name)) { |
| 568 | + err("CoherenceOperator: StatusHA check failed - No DistributionCoordinator " |
| 569 | + + "for DistributedCache service " + name); |
| 570 | + } |
| 571 | + } |
| 572 | + err("CoherenceOperator: StatusHA check failed - DistributedCache service count " + cacheServices.size() |
| 573 | + + " does not match DistributionCoordinator count " + distributionCoordinators.size()); |
| 574 | + return false; |
| 575 | + } |
| 576 | + |
548 | 577 | for (String mBean : getPartitionAssignmentMBeans()) { |
549 | 578 | if (allowEndangered != null && allowEndangered.stream().anyMatch(mBean::contains)) { |
550 | 579 | // this service is allowed to be endangered so skip it. |
@@ -605,7 +634,7 @@ private boolean isCacheServiceSafe(String mBean, int memberId) throws MalformedO |
605 | 634 | ObjectName objectName = ObjectName.getInstance(mBean); |
606 | 635 | String domain = objectName.getDomain(); |
607 | 636 | String serviceName = objectName.getKeyProperty("service"); |
608 | | - String serviceMBean = String.format(MBEAN_SERVICE, domain, serviceName, memberId); |
| 637 | + String serviceMBean = String.format(MBEAN_SERVICE_PATTERN, domain, serviceName, memberId); |
609 | 638 | Map<String, Object> attributes = getMBeanAttributes(serviceMBean, CACHE_SERVICE_ATTRIBUTES); |
610 | 639 | Boolean storageEnabled = (Boolean) attributes.get(ATTRIB_STORAGE_ENABLED); |
611 | 640 | Integer memberCount = (Integer) attributes.get(ATTRIB_MEMBER_COUNT); |
@@ -729,6 +758,23 @@ private Set<String> getPartitionAssignmentMBeans() { |
729 | 758 | .orElse(Collections.emptySet()); |
730 | 759 | } |
731 | 760 |
|
| 761 | + private Set<String> getDistributedCacheServiceNames() throws MalformedObjectNameException { |
| 762 | + Set<String> cacheServices = new HashSet<>(); |
| 763 | + Set<String> set = getMBeanServerProxy() |
| 764 | + .map(p -> p.queryNames(MBEAN_SERVICE, null)) |
| 765 | + .orElse(Collections.emptySet()); |
| 766 | + |
| 767 | + for (String mBean : set) { |
| 768 | + Map<String, Object> attributes = getMBeanAttributes(mBean, new String[]{"Type"}); |
| 769 | + String type = (String) attributes.get("type"); |
| 770 | + if ("DistributedCache".equals(type)) { |
| 771 | + ObjectName objectName = new ObjectName(mBean); |
| 772 | + cacheServices.add(objectName.getKeyProperty("name")); |
| 773 | + } |
| 774 | + } |
| 775 | + return cacheServices; |
| 776 | + } |
| 777 | + |
732 | 778 | private Set<String> getPersistenceCoordinatorMBeans() { |
733 | 779 | return getMBeanServerProxy() |
734 | 780 | .map(p -> p.queryNames(MBEAN_PERSISTENCE_COORDINATOR, null)) |
|
0 commit comments