| /* |
| * 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.lang.management.ManagementFactory; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.concurrent.BrokenBarrierException; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.CyclicBarrier; |
| import java.util.concurrent.ThreadLocalRandom; |
| import java.util.concurrent.atomic.AtomicInteger; |
| import javax.cache.CacheManager; |
| import javax.cache.Caching; |
| import javax.management.MBeanServer; |
| import javax.management.MBeanServerInvocationHandler; |
| import javax.management.ObjectName; |
| import org.apache.ignite.Ignite; |
| import org.apache.ignite.IgniteCache; |
| import org.apache.ignite.IgniteCheckedException; |
| import org.apache.ignite.IgniteTransactions; |
| import org.apache.ignite.cache.CacheAtomicityMode; |
| import org.apache.ignite.cache.CacheMetrics; |
| import org.apache.ignite.cache.CacheMode; |
| import org.apache.ignite.cache.CacheWriteSynchronizationMode; |
| import org.apache.ignite.cluster.ClusterNode; |
| import org.apache.ignite.configuration.CacheConfiguration; |
| import org.apache.ignite.configuration.DataRegionConfiguration; |
| import org.apache.ignite.configuration.DataStorageConfiguration; |
| import org.apache.ignite.configuration.IgniteConfiguration; |
| import org.apache.ignite.configuration.WALMode; |
| import org.apache.ignite.internal.IgniteEx; |
| import org.apache.ignite.internal.IgniteInternalFuture; |
| import org.apache.ignite.internal.IgniteInterruptedCheckedException; |
| import org.apache.ignite.internal.TestRecordingCommunicationSpi; |
| import org.apache.ignite.internal.TransactionsMXBeanImpl; |
| import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxFinishResponse; |
| import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse; |
| import org.apache.ignite.internal.processors.cache.transactions.IgniteTxManager; |
| import org.apache.ignite.internal.util.future.GridCompoundFuture; |
| import org.apache.ignite.internal.util.lang.GridAbsPredicate; |
| import org.apache.ignite.internal.util.typedef.G; |
| import org.apache.ignite.internal.util.typedef.internal.U; |
| import org.apache.ignite.lang.IgniteBiPredicate; |
| import org.apache.ignite.mxbean.CacheMetricsMXBean; |
| import org.apache.ignite.mxbean.TransactionsMXBean; |
| import org.apache.ignite.plugin.extensions.communication.Message; |
| import org.apache.ignite.testframework.GridTestUtils; |
| import org.apache.ignite.testframework.MvccFeatureChecker; |
| import org.apache.ignite.testframework.junits.WithSystemProperty; |
| import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; |
| import org.apache.ignite.transactions.Transaction; |
| import org.junit.Assume; |
| import org.junit.Test; |
| |
| import static org.apache.ignite.IgniteSystemProperties.IGNITE_DUMP_TX_COLLISIONS_INTERVAL; |
| import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC; |
| import static org.apache.ignite.transactions.TransactionIsolation.READ_COMMITTED; |
| |
| /** |
| * |
| */ |
| @SuppressWarnings("unchecked") |
| public class CacheMetricsManageTest extends GridCommonAbstractTest { |
| /** */ |
| private static final String CACHE1 = "cache1"; |
| |
| /** */ |
| private static final String CACHE2 = "cache2"; |
| |
| /** */ |
| private static final String GROUP = "group1"; |
| |
| /** Wait condition timeout. */ |
| private static final long WAIT_CONDITION_TIMEOUT = 3_000L; |
| |
| /** Persistence. */ |
| private boolean persistence; |
| |
| /** Use test spi flag. */ |
| private boolean useTestCommSpi; |
| |
| /** Backups count. */ |
| private int backups = -1; |
| |
| /** Client flag. */ |
| private boolean client; |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testJmxNoPdsStatisticsEnable() throws Exception { |
| Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-9224", MvccFeatureChecker.forcedMvcc()); |
| |
| testJmxStatisticsEnable(false); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testJmxPdsStatisticsEnable() throws Exception { |
| Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-9224", MvccFeatureChecker.forcedMvcc()); |
| |
| testJmxStatisticsEnable(true); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCacheManagerStatisticsEnable() throws Exception { |
| final CacheManager mgr1 = Caching.getCachingProvider().getCacheManager(); |
| final CacheManager mgr2 = Caching.getCachingProvider().getCacheManager(); |
| |
| CacheConfiguration<Object, Object> cfg1 = new CacheConfiguration<>() |
| .setName(CACHE1) |
| .setGroupName(GROUP) |
| .setCacheMode(CacheMode.PARTITIONED) |
| .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); |
| |
| mgr1.createCache(CACHE1, cfg1); |
| |
| CacheConfiguration<Object, Object> cfg2 = new CacheConfiguration<>(cfg1) |
| .setName(CACHE2) |
| .setStatisticsEnabled(true); |
| |
| mgr1.createCache(CACHE2, cfg2); |
| |
| assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() { |
| @Override public boolean apply() { |
| return !isStatisticsEnabled(mgr1, CACHE1) && !isStatisticsEnabled(mgr2, CACHE1) |
| && isStatisticsEnabled(mgr1, CACHE2) && isStatisticsEnabled(mgr2, CACHE2); |
| } |
| }, WAIT_CONDITION_TIMEOUT)); |
| |
| mgr1.enableStatistics(CACHE1, true); |
| mgr2.enableStatistics(CACHE2, false); |
| |
| assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() { |
| @Override public boolean apply() { |
| return isStatisticsEnabled(mgr1, CACHE1) && isStatisticsEnabled(mgr2, CACHE1) |
| && !isStatisticsEnabled(mgr1, CACHE2) && !isStatisticsEnabled(mgr2, CACHE2); |
| } |
| }, WAIT_CONDITION_TIMEOUT)); |
| } |
| |
| /** |
| * |
| */ |
| @Test |
| public void testPublicApiStatisticsEnable() throws Exception { |
| Ignite ig1 = startGrid(1); |
| startGrid(2); |
| |
| IgniteCache<Object, Object> cache1 = ig1.cache(CACHE1); |
| |
| CacheConfiguration<Object, Object> cacheCfg2 = new CacheConfiguration<Object, Object>(cache1.getConfiguration(CacheConfiguration.class)); |
| |
| cacheCfg2.setName(CACHE2); |
| cacheCfg2.setStatisticsEnabled(true); |
| |
| ig1.getOrCreateCache(cacheCfg2); |
| |
| assertCachesStatisticsMode(false, true); |
| |
| cache1.enableStatistics(true); |
| |
| assertCachesStatisticsMode(true, true); |
| |
| ig1.cluster().enableStatistics(Arrays.asList(CACHE1, CACHE2), false); |
| |
| assertCachesStatisticsMode(false, false); |
| } |
| |
| /** |
| * |
| */ |
| @Test |
| public void testMultiThreadStatisticsEnable() throws Exception { |
| startGrids(5); |
| |
| IgniteCache<?, ?> cache1 = grid(0).cache(CACHE1); |
| |
| CacheConfiguration<Object, Object> cacheCfg2 = new CacheConfiguration<Object, Object>(cache1.getConfiguration(CacheConfiguration.class)); |
| |
| cacheCfg2.setName(CACHE2); |
| |
| grid(0).getOrCreateCache(cacheCfg2); |
| |
| awaitPartitionMapExchange(); |
| |
| final CyclicBarrier barrier = new CyclicBarrier(10); |
| |
| final AtomicInteger gridIdx = new AtomicInteger(-1); |
| |
| IgniteInternalFuture<?> fut = multithreadedAsync(new Runnable() { |
| @Override public void run() { |
| try { |
| Ignite ignite = grid(gridIdx.incrementAndGet() % 5); |
| |
| barrier.await(); |
| |
| ignite.cluster().enableStatistics(Arrays.asList(CACHE1, CACHE2), true); |
| |
| assertCachesStatisticsMode(true, true); |
| |
| barrier.await(); |
| |
| ignite.cluster().enableStatistics(Arrays.asList(CACHE1, CACHE2), false); |
| |
| assertCachesStatisticsMode(false, false); |
| |
| barrier.await(); |
| |
| ignite.cluster().enableStatistics(Collections.singletonList(CACHE1), true); |
| |
| assertCachesStatisticsMode(true, false); |
| } |
| catch (InterruptedException | BrokenBarrierException | IgniteCheckedException e) { |
| fail("Unexpected exception: " + e); |
| } |
| } |
| }, 10); |
| |
| fut.get(); |
| |
| startGrid(5); |
| |
| assertCachesStatisticsMode(true, false); |
| } |
| |
| /** |
| * |
| */ |
| @Test |
| public void testCacheApiClearStatistics() throws Exception { |
| startGrids(3); |
| |
| IgniteCache<Integer, String> cache = grid(0).cache(CACHE1); |
| |
| cache.enableStatistics(true); |
| |
| incrementCacheStatistics(cache); |
| |
| cache.clearStatistics(); |
| |
| assertCacheStatisticsIsClear(Collections.singleton(CACHE1)); |
| } |
| |
| /** |
| * |
| */ |
| @Test |
| public void testClearStatisticsAfterDisableStatistics() throws Exception { |
| startGrids(3); |
| |
| IgniteCache<Integer, String> cache = grid(0).cache(CACHE1); |
| |
| cache.enableStatistics(true); |
| |
| incrementCacheStatistics(cache); |
| |
| cache.enableStatistics(false); |
| |
| cache.clearStatistics(); |
| |
| cache.enableStatistics(true); |
| |
| assertCacheStatisticsIsClear(Collections.singleton(CACHE1)); |
| } |
| |
| /** |
| * |
| */ |
| @Test |
| public void testClusterApiClearStatistics() throws Exception { |
| startGrids(3); |
| |
| IgniteCache<Object, Object> cache = grid(0).cache(CACHE1); |
| |
| cache.enableStatistics(true); |
| |
| grid(0).getOrCreateCache( |
| new CacheConfiguration<Object, Object>(cache.getConfiguration(CacheConfiguration.class)).setName(CACHE2) |
| ).enableStatistics(true); |
| |
| Collection<String> cacheNames = Arrays.asList(CACHE1, CACHE2); |
| |
| for (String cacheName : cacheNames) |
| incrementCacheStatistics(grid(0).cache(cacheName)); |
| |
| grid(0).cluster().clearStatistics(cacheNames); |
| |
| assertCacheStatisticsIsClear(cacheNames); |
| } |
| |
| /** |
| * |
| */ |
| @Test |
| public void testJmxApiClearStatistics() throws Exception { |
| startGrids(3); |
| |
| IgniteCache<Integer, String> cache = grid(0).cache(CACHE1); |
| |
| cache.enableStatistics(true); |
| |
| incrementCacheStatistics(cache); |
| |
| mxBean(0, CACHE1, CacheClusterMetricsMXBeanImpl.class).clear(); |
| |
| assertCacheStatisticsIsClear(Collections.singleton(CACHE1)); |
| } |
| |
| /** |
| * Cache statistics is cleared on all nodes. |
| * |
| * @param cacheNames a collection of cache names. |
| */ |
| private void assertCacheStatisticsIsClear(Collection<String> cacheNames) throws Exception { |
| for (String cacheName : cacheNames) { |
| for (Ignite ig : G.allGrids()) { |
| assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() { |
| @SuppressWarnings("ErrorNotRethrown") |
| @Override public boolean apply() { |
| boolean res = true; |
| |
| IgniteCache<?, ?> cache = ig.cache(cacheName); |
| |
| try { |
| assertEquals("CachePuts", 0L, cache.mxBean().getCachePuts()); |
| assertEquals("CacheHits", 0L, cache.mxBean().getCacheHits()); |
| assertEquals("CacheGets", 0L, cache.mxBean().getCacheGets()); |
| assertEquals("CacheRemovals", 0L, cache.mxBean().getCacheRemovals()); |
| assertEquals("CacheMisses", 0L, cache.mxBean().getCacheMisses()); |
| assertEquals("AverageGetTime", 0f, cache.mxBean().getAveragePutTime()); |
| assertEquals("AveragePutTime", 0f, cache.mxBean().getAverageGetTime()); |
| assertEquals("AverageRemoveTime", 0f, cache.mxBean().getAverageRemoveTime()); |
| } |
| catch (AssertionError e) { |
| log.warning(e.toString()); |
| |
| res = false; |
| } |
| |
| return res; |
| } |
| }, WAIT_CONDITION_TIMEOUT)); |
| } |
| } |
| } |
| |
| /** |
| * Increment cache statistics. |
| * |
| * @param cache cache. |
| */ |
| private void incrementCacheStatistics(IgniteCache<Integer, String> cache) { |
| cache.get(1); |
| cache.put(1, "one"); |
| cache.get(1); |
| cache.remove(1); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override protected void beforeTest() throws Exception { |
| super.beforeTest(); |
| |
| cleanPersistenceDir(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override protected void afterTest() throws Exception { |
| super.afterTest(); |
| |
| stopAllGrids(); |
| |
| cleanPersistenceDir(); |
| |
| persistence = false; |
| } |
| |
| /** |
| * @param persistence Persistence. |
| */ |
| private void testJmxStatisticsEnable(boolean persistence) throws Exception { |
| this.persistence = persistence; |
| |
| Ignite ig1 = startGrid(1); |
| Ignite ig2 = startGrid(2); |
| |
| ig1.cluster().active(true); |
| |
| CacheConfiguration<Object, Object> ccfg = ig1.cache(CACHE1).getConfiguration(CacheConfiguration.class); |
| CacheConfiguration<Object, Object> cacheCfg2 = new CacheConfiguration<>(ccfg); |
| |
| cacheCfg2.setName(CACHE2); |
| cacheCfg2.setStatisticsEnabled(true); |
| |
| ig2.getOrCreateCache(cacheCfg2); |
| |
| CacheMetricsMXBean mxBeanCache1 = mxBean(2, CACHE1, CacheClusterMetricsMXBeanImpl.class); |
| CacheMetricsMXBean mxBeanCache2 = mxBean(2, CACHE2, CacheClusterMetricsMXBeanImpl.class); |
| CacheMetricsMXBean mxBeanCache1loc = mxBean(2, CACHE1, CacheLocalMetricsMXBeanImpl.class); |
| |
| mxBeanCache1.enableStatistics(); |
| mxBeanCache2.disableStatistics(); |
| |
| assertCachesStatisticsMode(true, false); |
| |
| stopGrid(1); |
| |
| startGrid(3); |
| |
| assertCachesStatisticsMode(true, false); |
| |
| mxBeanCache1loc.disableStatistics(); |
| |
| assertCachesStatisticsMode(false, false); |
| |
| mxBeanCache1.enableStatistics(); |
| mxBeanCache2.enableStatistics(); |
| |
| // Start node 1 again. |
| startGrid(1); |
| |
| if (persistence) |
| ig2.resetLostPartitions(Arrays.asList(CACHE1, CACHE2)); |
| |
| assertCachesStatisticsMode(true, true); |
| |
| int gridIdx = 0; |
| |
| for (Ignite ignite : G.allGrids()) { |
| gridIdx++; |
| |
| ignite.cache(CACHE1).put(gridIdx, gridIdx); |
| ignite.cache(CACHE2).put(gridIdx, gridIdx); |
| |
| ignite.cache(CACHE1).get(gridIdx); |
| ignite.cache(CACHE2).get(gridIdx); |
| } |
| |
| assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() { |
| @Override public boolean apply() { |
| int cnt = G.allGrids().size(); |
| |
| for (Ignite ignite : G.allGrids()) { |
| CacheMetrics metrics1 = ignite.cache(CACHE1).metrics(); |
| CacheMetrics metrics2 = ignite.cache(CACHE2).metrics(); |
| |
| if (metrics1.getCacheGets() < cnt || metrics2.getCacheGets() < cnt |
| || metrics1.getCachePuts() < cnt || metrics2.getCachePuts() < cnt) |
| return false; |
| } |
| |
| return true; |
| } |
| }, 10_000L)); |
| |
| stopAllGrids(); |
| |
| ig1 = startGrid(1); |
| |
| ig1.cluster().active(true); |
| |
| ig1.getOrCreateCache(cacheCfg2.setStatisticsEnabled(false)); |
| |
| if (persistence) |
| // Both caches restored from pds. |
| assertCachesStatisticsMode(true, true); |
| else |
| assertCachesStatisticsMode(false, false); |
| |
| mxBeanCache1 = mxBean(1, CACHE1, CacheLocalMetricsMXBeanImpl.class); |
| mxBeanCache2 = mxBean(1, CACHE2, CacheLocalMetricsMXBeanImpl.class); |
| |
| mxBeanCache1.enableStatistics(); |
| mxBeanCache2.disableStatistics(); |
| |
| startGrid(2); |
| |
| assertCachesStatisticsMode(true, false); |
| } |
| |
| /** |
| * Gets CacheGroupMetricsMXBean for given node and group name. |
| * |
| * @param nodeIdx Node index. |
| * @param cacheName Cache name. |
| * @return MBean instance. |
| */ |
| private CacheMetricsMXBean mxBean(int nodeIdx, String cacheName, Class<? extends CacheMetricsMXBean> clazz) { |
| return getMxBean(getTestIgniteInstanceName(nodeIdx), cacheName, clazz.getName(), CacheMetricsMXBean.class); |
| } |
| |
| /** Default cache config. */ |
| private CacheConfiguration<?, ?> getCacheConfiguration() { |
| CacheConfiguration<?, ?> cacheCfg = new CacheConfiguration<>() |
| .setName(CACHE1) |
| .setGroupName(GROUP) |
| .setCacheMode(CacheMode.PARTITIONED) |
| .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL) |
| .setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC); |
| |
| if (backups != -1) |
| cacheCfg.setBackups(2); |
| |
| return cacheCfg; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { |
| IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); |
| |
| CacheConfiguration<?, ?> cacheCfg = getCacheConfiguration(); |
| |
| cfg.setCacheConfiguration(cacheCfg); |
| |
| if (useTestCommSpi) |
| cfg.setCommunicationSpi(new TestRecordingCommunicationSpi()); |
| |
| if (client) |
| cfg.setClientMode(client); |
| |
| if (persistence) |
| cfg.setDataStorageConfiguration(new DataStorageConfiguration() |
| .setDefaultDataRegionConfiguration( |
| new DataRegionConfiguration() |
| .setPersistenceEnabled(true) |
| .setMaxSize(DataStorageConfiguration.DFLT_DATA_REGION_INITIAL_SIZE) |
| ) |
| .setWalMode(WALMode.LOG_ONLY) |
| ); |
| |
| return cfg; |
| } |
| |
| /** Test correct metric for tx key contention. */ |
| @Test |
| @WithSystemProperty(key = IGNITE_DUMP_TX_COLLISIONS_INTERVAL, value = "30000") |
| public void testTxContentionMetric() throws Exception { |
| Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-9224", MvccFeatureChecker.forcedMvcc()); |
| |
| backups = 1; |
| |
| useTestCommSpi = true; |
| |
| Ignite ig = startGridsMultiThreaded(2); |
| |
| int contCnt = (int)U.staticField(IgniteTxManager.class, "COLLISIONS_QUEUE_THRESHOLD") * 20; |
| |
| CountDownLatch txLatch = new CountDownLatch(contCnt * 2); |
| |
| CountDownLatch txLatch0 = new CountDownLatch(contCnt * 2); |
| |
| ig.cluster().active(true); |
| |
| client = true; |
| |
| Ignite cl = startGrid(); |
| |
| CacheConfiguration<?, ?> dfltCacheCfg = getCacheConfiguration(); |
| |
| dfltCacheCfg.setStatisticsEnabled(true); |
| |
| String cacheName = dfltCacheCfg.getName(); |
| |
| IgniteCache<Integer, Integer> cache = ig.cache(cacheName); |
| |
| IgniteCache<Integer, Integer> cache0 = cl.cache(cacheName); |
| |
| CacheMetricsMXBean mxBeanCache = mxBean(0, cacheName, CacheLocalMetricsMXBeanImpl.class); |
| |
| final List<Integer> priKeys = primaryKeys(cache, 3, 1); |
| |
| final Integer backKey = backupKey(cache); |
| |
| IgniteTransactions txMgr = cl.transactions(); |
| |
| CountDownLatch blockOnce = new CountDownLatch(1); |
| |
| for (Ignite ig0 : G.allGrids()) { |
| TestRecordingCommunicationSpi commSpi0 = |
| (TestRecordingCommunicationSpi)ig0.configuration().getCommunicationSpi(); |
| |
| commSpi0.blockMessages(new IgniteBiPredicate<ClusterNode, Message>() { |
| @Override public boolean apply(ClusterNode node, Message msg) { |
| if (msg instanceof GridNearTxPrepareResponse && blockOnce.getCount() > 0) { |
| blockOnce.countDown(); |
| |
| return true; |
| } |
| |
| return false; |
| } |
| }); |
| } |
| |
| IgniteInternalFuture f = GridTestUtils.runAsync(() -> { |
| try (Transaction tx = txMgr.txStart(PESSIMISTIC, READ_COMMITTED)) { |
| cache0.put(priKeys.get(0), 0); |
| cache0.put(priKeys.get(2), 0); |
| tx.commit(); |
| } |
| }); |
| |
| blockOnce.await(); |
| |
| GridCompoundFuture<?, ?> finishFut = new GridCompoundFuture<>(); |
| |
| for (int i = 0; i < contCnt; ++i) { |
| IgniteInternalFuture f0 = GridTestUtils.runAsync(() -> { |
| try (Transaction tx = txMgr.txStart(PESSIMISTIC, READ_COMMITTED)) { |
| cache0.put(priKeys.get(0), 0); |
| cache0.put(priKeys.get(1), 0); |
| |
| txLatch0.countDown(); |
| |
| tx.commit(); |
| |
| txLatch.countDown(); |
| } |
| |
| try (Transaction tx = txMgr.txStart(PESSIMISTIC, READ_COMMITTED)) { |
| cache0.put(priKeys.get(2), 0); |
| cache0.put(backKey, 0); |
| |
| txLatch0.countDown(); |
| |
| tx.commit(); |
| |
| txLatch.countDown(); |
| } |
| }); |
| |
| finishFut.add(f0); |
| } |
| |
| finishFut.markInitialized(); |
| |
| txLatch0.await(); |
| |
| for (Ignite ig0 : G.allGrids()) { |
| TestRecordingCommunicationSpi commSpi0 = |
| (TestRecordingCommunicationSpi)ig0.configuration().getCommunicationSpi(); |
| |
| commSpi0.stopBlock(); |
| } |
| |
| IgniteTxManager txManager = ((IgniteEx) ig).context().cache().context().tm(); |
| |
| assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() { |
| @Override public boolean apply() { |
| try { |
| U.invoke(IgniteTxManager.class, txManager, "collectTxCollisionsInfo"); |
| } |
| catch (IgniteCheckedException e) { |
| fail(e.toString()); |
| } |
| |
| String coll = mxBeanCache.getTxKeyCollisions(); |
| |
| if (coll.contains("val=" + priKeys.get(2)) || coll.contains("val=" + priKeys.get(0))); |
| return true; |
| } |
| }, 10_000)); |
| |
| f.get(); |
| |
| finishFut.get(); |
| |
| txLatch.await(); |
| } |
| |
| /** Tests metric change interval. */ |
| @Test |
| public void testKeyCollisionsMetricDifferentTimeout() throws Exception { |
| Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-9224", MvccFeatureChecker.forcedMvcc()); |
| |
| backups = 2; |
| |
| useTestCommSpi = true; |
| |
| Ignite ig = startGridsMultiThreaded(3); |
| |
| int contCnt = (int)U.staticField(IgniteTxManager.class, "COLLISIONS_QUEUE_THRESHOLD") * 5; |
| |
| CountDownLatch txLatch = new CountDownLatch(contCnt); |
| |
| ig.cluster().active(true); |
| |
| client = true; |
| |
| Ignite cl = startGrid(); |
| |
| IgniteTransactions txMgr = cl.transactions(); |
| |
| CacheConfiguration<?, ?> dfltCacheCfg = getCacheConfiguration(); |
| |
| dfltCacheCfg.setStatisticsEnabled(true); |
| |
| String cacheName = dfltCacheCfg.getName(); |
| |
| IgniteCache<Integer, Integer> cache = ig.cache(cacheName); |
| |
| IgniteCache<Integer, Integer> cache0 = cl.cache(cacheName); |
| |
| final Integer keyId = primaryKey(cache); |
| |
| CountDownLatch blockOnce = new CountDownLatch(1); |
| |
| for (Ignite ig0 : G.allGrids()) { |
| if (ig0.configuration().isClientMode()) |
| continue; |
| |
| TestRecordingCommunicationSpi commSpi0 = |
| (TestRecordingCommunicationSpi)ig0.configuration().getCommunicationSpi(); |
| |
| commSpi0.blockMessages(new IgniteBiPredicate<ClusterNode, Message>() { |
| @Override public boolean apply(ClusterNode node, Message msg) { |
| if (msg instanceof GridNearTxFinishResponse && blockOnce.getCount() > 0) { |
| blockOnce.countDown(); |
| |
| return true; |
| } |
| |
| return false; |
| } |
| }); |
| } |
| |
| IgniteInternalFuture f = GridTestUtils.runAsync(() -> { |
| try (Transaction tx = txMgr.txStart(PESSIMISTIC, READ_COMMITTED)) { |
| cache0.put(keyId, 0); |
| tx.commit(); |
| } |
| }); |
| |
| blockOnce.await(); |
| |
| GridCompoundFuture<?, ?> finishFut = new GridCompoundFuture<>(); |
| |
| for (int i = 0; i < contCnt; ++i) { |
| IgniteInternalFuture f0 = GridTestUtils.runAsync(() -> { |
| try (Transaction tx = txMgr.txStart(PESSIMISTIC, READ_COMMITTED)) { |
| cache0.put(keyId, 0); |
| |
| tx.commit(); |
| |
| txLatch.countDown(); |
| } |
| }); |
| |
| finishFut.add(f0); |
| } |
| |
| finishFut.markInitialized(); |
| |
| for (Ignite ig0 : G.allGrids()) { |
| TestRecordingCommunicationSpi commSpi0 = |
| (TestRecordingCommunicationSpi)ig0.configuration().getCommunicationSpi(); |
| |
| if (ig0.configuration().isClientMode()) |
| continue; |
| |
| commSpi0.stopBlock(); |
| } |
| |
| CacheMetricsMXBean mxBeanCache = mxBean(0, cacheName, CacheLocalMetricsMXBeanImpl.class); |
| |
| IgniteTxManager txManager = ((IgniteEx) ig).context().cache().context().tm(); |
| |
| final TransactionsMXBean txMXBean1 = txMXBean(0); |
| |
| final TransactionsMXBean txMXBean2 = txMXBean(1); |
| |
| for (int i = 0; i < 10; ++i) { |
| txMXBean1.setTxKeyCollisionsInterval(ThreadLocalRandom.current().nextInt(1000, 1100)); |
| |
| txMXBean2.setTxKeyCollisionsInterval(ThreadLocalRandom.current().nextInt(1000, 1100)); |
| |
| mxBeanCache.getTxKeyCollisions(); |
| |
| mxBeanCache.clear(); |
| |
| try { |
| U.invoke(IgniteTxManager.class, txManager, "collectTxCollisionsInfo"); |
| } |
| catch (IgniteCheckedException e) { |
| fail(e.toString()); |
| } |
| |
| U.sleep(500); |
| } |
| |
| f.get(); |
| |
| finishFut.get(); |
| |
| txLatch.await(); |
| } |
| |
| /** @throws Exception If failed. */ |
| @Test |
| public void testCacheSizeOnInactiveCluster() throws Exception { |
| persistence = true; |
| |
| IgniteEx grid = startGrid(0); |
| |
| assertFalse(grid.cluster().state().active()); |
| |
| CacheMetricsMXBean mxBean = mxBean(0, CACHE1, CacheLocalMetricsMXBeanImpl.class); |
| |
| long size = mxBean.getCacheSize(); |
| |
| assertEquals(-1, size); |
| } |
| |
| /** |
| * |
| */ |
| private TransactionsMXBean txMXBean(int igniteInt) throws Exception { |
| ObjectName mbeanName = U.makeMBeanName(getTestIgniteInstanceName(igniteInt), "Transactions", |
| TransactionsMXBeanImpl.class.getSimpleName()); |
| |
| MBeanServer mbeanSrv = ManagementFactory.getPlatformMBeanServer(); |
| |
| if (!mbeanSrv.isRegistered(mbeanName)) |
| fail("MBean is not registered: " + mbeanName.getCanonicalName()); |
| |
| return MBeanServerInvocationHandler.newProxyInstance(mbeanSrv, mbeanName, TransactionsMXBean.class, true); |
| } |
| |
| /** |
| * Check cache statistics enabled/disabled flag for all nodes |
| * |
| * @param cacheName Cache name. |
| * @param enabled Enabled. |
| */ |
| private boolean checkStatisticsMode(String cacheName, boolean enabled) { |
| for (Ignite ignite : G.allGrids()) |
| if (ignite.cache(cacheName).metrics().isStatisticsEnabled() != enabled) { |
| log.warning("Wrong cache statistics mode [grid=" + ignite.name() + ", cache=" + cacheName |
| + ", expected=" + enabled); |
| |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * @param enabled1 Statistics enabled for cache 1. |
| * @param enabled2 Statistics enabled for cache 2. |
| */ |
| private void assertCachesStatisticsMode(final boolean enabled1, final boolean enabled2) throws IgniteInterruptedCheckedException { |
| assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() { |
| @Override public boolean apply() { |
| return checkStatisticsMode(CACHE1, enabled1) && checkStatisticsMode(CACHE2, enabled2); |
| } |
| }, WAIT_CONDITION_TIMEOUT)); |
| } |
| |
| /** |
| * @param cacheMgr Cache manager. |
| * @param cacheName Cache name. |
| */ |
| private boolean isStatisticsEnabled(CacheManager cacheMgr, String cacheName) { |
| return ((IgniteCache)cacheMgr.getCache(cacheName)).metrics().isStatisticsEnabled(); |
| } |
| } |