blob: a50f860a21552624079dc4372547f744d51ec764 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.processors.cache;
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.management.MBeanServer;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.ignite.IgniteDataStreamer;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.affinity.AffinityFunction;
import org.apache.ignite.cache.affinity.AffinityFunctionContext;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.mxbean.CacheGroupMetricsMXBean;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
/**
* Cache group JMX metrics test.
*/
public class CacheGroupMetricsMBeanTest extends GridCommonAbstractTest implements Serializable {
/** */
private static class RoundRobinVariableSizeAffinityFunction implements AffinityFunction {
/** {@inheritDoc} */
@Override public void reset() {
// No-op
}
/** {@inheritDoc} */
@Override public int partitions() {
return 10;
}
/** {@inheritDoc} */
@Override public int partition(Object key) {
return key.hashCode() % partitions();
}
/** {@inheritDoc} */
@Override public List<List<ClusterNode>> assignPartitions(AffinityFunctionContext affCtx) {
List<ClusterNode> nodes = affCtx.currentTopologySnapshot();
List<List<ClusterNode>> assignmentParts = new ArrayList<>(partitions());
for (int part = 0; part < partitions(); part++) {
int backups = part % nodes.size() + 1;
List<ClusterNode> assignmentNodes = new ArrayList<>(backups);
for (int backup = 0; backup < backups; backup++)
assignmentNodes.add(nodes.get((part + part / nodes.size() + backup) % nodes.size()));
assignmentParts.add(assignmentNodes);
}
return assignmentParts;
}
/** {@inheritDoc} */
@Override public void removeNode(UUID nodeId) {
// No-op
}
}
/**
* Partition assignment for cache1 with given affinity function:
*
* P/N 0 1 2
* ---------
* 0 | P
* 1 | P B
* 2 | B B P
* 3 | P
* 4 | B P
* 5 | P B B
* 6 | P
* 7 | P B
* 8 | B P B
* 9 | P
*
*/
private static final int [][] assignmentMapArr =
new int[][] {{0}, {1, 2}, {2, 0, 1}, {1}, {2, 0}, {0, 1, 2}, {2}, {0, 1}, {1, 2, 0}, {0}};
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
CacheConfiguration cCfg1 = new CacheConfiguration()
.setName("cache1")
.setGroupName("group1")
.setCacheMode(CacheMode.PARTITIONED)
.setBackups(3)
.setAffinity(new RoundRobinVariableSizeAffinityFunction());
CacheConfiguration cCfg2 = new CacheConfiguration()
.setName("cache2")
.setGroupName("group2")
.setCacheMode(CacheMode.REPLICATED);
CacheConfiguration cCfg3 = new CacheConfiguration()
.setName("cache3")
.setGroupName("group2")
.setCacheMode(CacheMode.REPLICATED);
CacheConfiguration cCfg4 = new CacheConfiguration()
.setName("cache4")
.setCacheMode(CacheMode.PARTITIONED);
cfg.setCacheConfiguration(cCfg1, cCfg2, cCfg3, cCfg4);
return cfg;
}
/** {@inheritDoc} */
@Override protected void afterTestsStopped() throws Exception {
stopAllGrids();
}
/**
* Gets CacheGroupMetricsMXBean for given node and group name.
*
* @param nodeIdx Node index.
* @param cacheOrGrpName Cache group name.
* @return MBean instance.
*/
private CacheGroupMetricsMXBean mxBean(int nodeIdx, String cacheOrGrpName) throws MalformedObjectNameException {
ObjectName mbeanName = U.makeMBeanName(getTestIgniteInstanceName(nodeIdx), "Cache groups", cacheOrGrpName);
MBeanServer mbeanSrv = ManagementFactory.getPlatformMBeanServer();
if (!mbeanSrv.isRegistered(mbeanName))
fail("MBean is not registered: " + mbeanName.getCanonicalName());
return MBeanServerInvocationHandler.newProxyInstance(mbeanSrv, mbeanName, CacheGroupMetricsMXBean.class,
true);
}
/**
* Converts array, containing partitions allocation to map from partitions to set of nodes.
*
* @param arr Array.
* @return Map from partitions to set of nodes.
*/
private Map<Integer, Set<String>> arrayToAllocationMap(int[][] arr) {
Map<Integer, Set<String>> res = new LinkedHashMap<>();
for (int part = 0; part < arr.length; part++) {
Set<String> nodeSet = new HashSet<>();
if (arr[part] != null)
for (int node = 0; node < arr[part].length; node++)
nodeSet.add(grid(arr[part][node]).localNode().id().toString());
res.put(part, nodeSet);
}
return res;
}
/**
* Converts array, containing affinity assignment to map from partitions to list of nodes.
*
* @param arr Array.
* @return Map from partitions to list of nodes.
*/
private Map<Integer, List<String>> arrayToAssignmentMap(int[][] arr) {
Map<Integer, List<String>> res = new LinkedHashMap<>();
for (int part = 0; part < arr.length; part++) {
List<String> nodeList = new ArrayList<>();
if (arr[part] != null)
for (int node = 0; node < arr[part].length; node++)
nodeList.add(grid(arr[part][node]).localNode().id().toString());
res.put(part, nodeList);
}
return res;
}
/**
* @throws Exception If failed.
*/
public void testCacheGroupMetrics() throws Exception {
startGrid(0);
startGrid(1);
startGrid(2);
awaitPartitionMapExchange(true, false, null);
CacheGroupMetricsMXBean mxBean0Grp1 = mxBean(0, "group1");
CacheGroupMetricsMXBean mxBean0Grp2 = mxBean(0, "group2");
CacheGroupMetricsMXBean mxBean0Grp3 = mxBean(0, "cache4");
CacheGroupMetricsMXBean mxBean1Grp1 = mxBean(1, "group1");
CacheGroupMetricsMXBean mxBean2Grp1 = mxBean(2, "group1");
assertEquals("group1", mxBean0Grp1.getGroupName());
assertEquals(null, mxBean0Grp3.getGroupName());
assertEquals(3, mxBean0Grp1.getBackups());
assertEquals(10, mxBean0Grp1.getPartitions());
assertEquals(1, mxBean0Grp1.getMinimumNumberOfPartitionCopies());
assertEquals(3, mxBean0Grp1.getMaximumNumberOfPartitionCopies());
assertEquals(0, mxBean0Grp1.getClusterMovingPartitionsCount());
assertEquals(19, mxBean0Grp1.getClusterOwningPartitionsCount());
assertEquals(7, mxBean0Grp1.getLocalNodeOwningPartitionsCount());
assertEquals(6, mxBean1Grp1.getLocalNodeOwningPartitionsCount());
assertEquals(6, mxBean2Grp1.getLocalNodeOwningPartitionsCount());
assertEquals(F.asList("cache1"), mxBean0Grp1.getCaches());
assertEquals(F.asList("cache2", "cache3"), mxBean0Grp2.getCaches());
assertEquals(F.asList("cache4"), mxBean0Grp3.getCaches());
assertEquals(arrayToAssignmentMap(assignmentMapArr), mxBean0Grp1.getAffinityPartitionsAssignmentMap());
assertEquals(arrayToAllocationMap(assignmentMapArr), mxBean0Grp1.getOwningPartitionsAllocationMap());
assertEquals(arrayToAllocationMap(new int[10][]), mxBean0Grp1.getMovingPartitionsAllocationMap());
try (IgniteDataStreamer<Integer, Integer> st = grid(0).dataStreamer("cache1")) {
for (int i = 0; i < 50_000; i++)
st.addData(i, i);
}
stopGrid(2);
// Check moving partitions while rebalancing.
assertFalse(arrayToAllocationMap(new int[10][]).equals(mxBean0Grp1.getMovingPartitionsAllocationMap()));
assertTrue(mxBean0Grp1.getLocalNodeMovingPartitionsCount() > 0);
assertTrue(mxBean0Grp1.getClusterMovingPartitionsCount() > 0);
}
}