blob: 0a340c1ca82d3dc1a641640789f805f8286811c6 [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;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import org.apache.ignite.cache.CacheRebalanceMode;
import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl;
import org.apache.ignite.mxbean.TransactionsMXBean;
import org.apache.ignite.testframework.ListeningTestLogger;
import org.apache.ignite.testframework.LogListener;
import org.apache.ignite.testframework.junits.WithSystemProperty;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.transactions.Transaction;
import org.junit.Test;
import static java.util.Collections.singletonMap;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
import static org.apache.ignite.testframework.LogListener.matches;
/**
*
*/
public class TransactionsMXBeanImplTest extends GridCommonAbstractTest {
/** Listener log messages. */
private static ListeningTestLogger testLog;
/** Client node. */
private boolean clientNode;
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
super.beforeTestsStarted();
testLog = new ListeningTestLogger(false, log);
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
stopAllGrids();
testLog.clearListeners();
super.afterTest();
}
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String name) throws Exception {
return super.getConfiguration(name)
.setCommunicationSpi(new TestRecordingCommunicationSpi())
.setGridLogger(testLog)
.setClientMode(clientNode)
.setCacheConfiguration(
new CacheConfiguration<>()
.setName(DEFAULT_CACHE_NAME)
.setAffinity(new RendezvousAffinityFunction(false, 32))
.setBackups(1)
.setAtomicityMode(TRANSACTIONAL)
.setRebalanceMode(CacheRebalanceMode.ASYNC)
.setWriteSynchronizationMode(FULL_SYNC)
);
}
/**
*
*/
@Test
public void testBasic() throws Exception {
IgniteEx ignite = startGrid(0);
TransactionsMXBean bean = txMXBean(0);
ignite.transactions().txStart();
ignite.cache(DEFAULT_CACHE_NAME).put(0, 0);
String res = bean.getActiveTransactions(null, null, null, null, null, null, null, null, false, false);
assertEquals("1", res);
res = bean.getActiveTransactions(null, null, null, null, null, null, null, null, true, false);
assertTrue(res.indexOf("Tx:") > 0);
res = bean.getActiveTransactions(null, null, null, null, null, null, null, null, false, true);
assertEquals("1", res);
doSleep(500);
res = bean.getActiveTransactions(null, null, null, null, null, null, null, null, false, false);
assertEquals("0", res);
}
/**
* Test for changing lrt timeout and their appearance before default
* timeout through MXBean.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = "60000")
public void testLongOperationsDumpTimeoutPositive() throws Exception {
checkLongOperationsDumpTimeoutViaTxMxBean(60_000, 100, 10_000, true);
}
/**
* Test to disable the LRT by setting timeout to 0.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = "100")
public void testLongOperationsDumpTimeoutZero() throws Exception {
checkLongOperationsDumpTimeoutViaTxMxBean(100, 0, 1_000, false);
}
/**
* Test to disable the LRT by setting timeout to -1.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = "100")
public void testLongOperationsDumpTimeoutNegative() throws Exception {
checkLongOperationsDumpTimeoutViaTxMxBean(100, -1, 1_000, false);
}
/**
* Test to verify the correct change of "Long operations dump timeout." in
* an immutable cluster.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = "100")
public void testChangeLongOperationsDumpTimeoutOnImmutableCluster() throws Exception {
Map<IgniteEx, TransactionsMXBean> allNodes = new HashMap<>();
for (int i = 0; i < 2; i++)
allNodes.put(startGrid(i), txMXBean(i));
clientNode = true;
for (int i = 2; i < 4; i++)
allNodes.put(startGrid(i), txMXBean(i));
//check for default value
checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, 100L);
//check update value via server node
long newTimeout = 200L;
updateLongOperationsDumpTimeoutViaTxMxBean(allNodes, node -> !node.configuration().isClientMode(), newTimeout);
checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, newTimeout);
//check update value via client node
newTimeout = 300L;
updateLongOperationsDumpTimeoutViaTxMxBean(allNodes, node -> node.configuration().isClientMode(), newTimeout);
checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, newTimeout);
}
/**
* Test to verify the correct change of "Long operations dump timeout." in
* an mutable cluster.
*
* @throws Exception If failed.
*/
@Test
@WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = "100")
public void testChangeLongOperationsDumpTimeoutOnMutableCluster() throws Exception {
Map<IgniteEx, TransactionsMXBean> node0 = singletonMap(startGrid(0), txMXBean(0));
Map<IgniteEx, TransactionsMXBean> node1 = singletonMap(startGrid(1), txMXBean(1));
Map<IgniteEx, TransactionsMXBean> allNodes = new HashMap<>();
allNodes.putAll(node0);
allNodes.putAll(node1);
long newTimeout = 200L;
updateLongOperationsDumpTimeoutViaTxMxBean(allNodes, node -> true, newTimeout);
checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, newTimeout);
allNodes.clear();
stopGrid(1);
node1 = singletonMap(startGrid(1), txMXBean(1));
//check that default value in restart node
long defTimeout = 100L;
checkLongOperationsDumpTimeoutViaTxMxBean(node0, newTimeout);
checkLongOperationsDumpTimeoutViaTxMxBean(node1, defTimeout);
newTimeout = 300L;
updateLongOperationsDumpTimeoutViaTxMxBean(node0, node -> true, newTimeout);
Map<IgniteEx, TransactionsMXBean> node2 = singletonMap(startGrid(2), txMXBean(2));
//check that default value in new node
checkLongOperationsDumpTimeoutViaTxMxBean(node0, newTimeout);
checkLongOperationsDumpTimeoutViaTxMxBean(node1, newTimeout);
checkLongOperationsDumpTimeoutViaTxMxBean(node2, defTimeout);
}
/**
* Search for the first node by the predicate and change
* "Long operations dump timeout." through TransactionsMXBean.
*
* @param nodes Nodes with TransactionsMXBean's.
* @param nodePred Predicate to search for a node.
* @param newTimeout New timeout.
*/
private void updateLongOperationsDumpTimeoutViaTxMxBean(
Map<IgniteEx, TransactionsMXBean> nodes,
Predicate<? super IgniteEx> nodePred,
long newTimeout
) {
assertNotNull(nodes);
assertNotNull(nodePred);
nodes.entrySet().stream()
.filter(e -> nodePred.test(e.getKey()))
.findAny().get().getValue().setLongOperationsDumpTimeout(newTimeout);
}
/**
* Checking the value of "Long operations dump timeout." on all nodes
* through the TransactionsMXBean.
*
* @param nodes Nodes with TransactionsMXBean's.
* @param checkTimeout Checked timeout.
*/
private void checkLongOperationsDumpTimeoutViaTxMxBean(Map<IgniteEx, TransactionsMXBean> nodes, long checkTimeout) {
assertNotNull(nodes);
nodes.forEach((node, txMxBean) -> assertEquals(checkTimeout, txMxBean.getLongOperationsDumpTimeout()));
}
/**
* Checking changes and receiving lrt through MXBean.
*
* @param defTimeout Default lrt timeout.
* @param newTimeout New lrt timeout.
* @param waitTimeTx Waiting time for a lrt.
* @param expectTx Expect or not a lrt to log.
* @throws Exception If failed.
*/
private void checkLongOperationsDumpTimeoutViaTxMxBean(
long defTimeout,
long newTimeout,
long waitTimeTx,
boolean expectTx
) throws Exception {
IgniteEx ignite = startGrid(0);
TransactionsMXBean txMXBean = txMXBean(0);
assertEquals(defTimeout, txMXBean.getLongOperationsDumpTimeout());
Transaction tx = ignite.transactions().txStart();
LogListener lrtLogLsnr = matches("First 10 long running transactions [total=1]").build();
LogListener txLogLsnr = matches(((TransactionProxyImpl)tx).tx().xidVersion().toString()).build();
testLog.registerListener(lrtLogLsnr);
testLog.registerListener(txLogLsnr);
txMXBean.setLongOperationsDumpTimeout(newTimeout);
assertEquals(newTimeout, ignite.context().cache().context().tm().longOperationsDumpTimeout());
if (expectTx)
assertTrue(waitForCondition(() -> lrtLogLsnr.check() && txLogLsnr.check(), waitTimeTx));
else
assertFalse(waitForCondition(() -> lrtLogLsnr.check() && txLogLsnr.check(), waitTimeTx));
}
/** */
private TransactionsMXBean txMXBean(int igniteInt) throws Exception {
return getMxBean(getTestIgniteInstanceName(igniteInt), "Transactions",
TransactionsMXBeanImpl.class, TransactionsMXBean.class);
}
}