|
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