/*
* 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.util.ArrayList;
import java.util.Collection;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.query.Query;
import org.apache.ignite.cache.query.ScanQuery;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.SqlQuery;
import org.apache.ignite.cache.query.TextQuery;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteInterruptedCheckedException;
import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMetricsAdapter;
import org.apache.ignite.internal.util.lang.GridAbsPredicate;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
/**
* Tests for cache query metrics.
*/
public abstract class CacheAbstractQueryMetricsSelfTest extends GridCommonAbstractTest {
/** Grid count. */
protected int gridCnt;
/** Cache mode. */
protected CacheMode cacheMode;
/** */
private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
startGridsMultiThreaded(gridCnt);
IgniteCache<Integer, String> cacheA = grid(0).cache("A");
IgniteCache<Integer, String> cacheB = grid(0).cache("B");
for (int i = 0; i < 100; i++) {
cacheA.put(i, String.valueOf(i));
cacheB.put(i, String.valueOf(i));
}
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
stopAllGrids();
}
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
TcpDiscoverySpi disco = new TcpDiscoverySpi();
disco.setIpFinder(ipFinder);
cfg.setDiscoverySpi(disco);
CacheConfiguration<Integer, String> cacheCfg1 = defaultCacheConfiguration();
cacheCfg1.setName("A");
cacheCfg1.setCacheMode(cacheMode);
cacheCfg1.setWriteSynchronizationMode(FULL_SYNC);
cacheCfg1.setIndexedTypes(Integer.class, String.class);
cacheCfg1.setStatisticsEnabled(true);
CacheConfiguration<Integer, String> cacheCfg2 = defaultCacheConfiguration();
cacheCfg2.setName("B");
cacheCfg2.setCacheMode(cacheMode);
cacheCfg2.setWriteSynchronizationMode(FULL_SYNC);
cacheCfg2.setIndexedTypes(Integer.class, String.class);
cacheCfg2.setStatisticsEnabled(true);
cfg.setCacheConfiguration(cacheCfg1, cacheCfg2);
return cfg;
}
/**
* Test metrics for SQL fields queries.
*
* @throws Exception In case of error.
*/
public void testSqlFieldsQueryMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlFieldsQuery qry = new SqlFieldsQuery("select * from String");
checkQueryMetrics(cache, qry);
}
/**
* Test metrics for SQL fields queries.
*
* @throws Exception In case of error.
*/
public void testSqlFieldsQueryNotFullyFetchedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlFieldsQuery qry = new SqlFieldsQuery("select * from String");
qry.setPageSize(10);
checkQueryNotFullyFetchedMetrics(cache, qry, false);
}
/**
* Test metrics for failed SQL queries.
*
* @throws Exception In case of error.
*/
public void testSqlFieldsQueryFailedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlFieldsQuery qry = new SqlFieldsQuery("select * from UNKNOWN");
checkQueryFailedMetrics(cache, qry);
}
/**
* Test metrics for Scan queries.
*
* @throws Exception In case of error.
*/
public void testScanQueryMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
ScanQuery<Integer, String> qry = new ScanQuery<>();
checkQueryMetrics(cache, qry);
}
/**
* Test metrics for Scan queries.
*
* @throws Exception In case of error.
*/
public void testScanQueryNotFullyFetchedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
ScanQuery<Integer, String> qry = new ScanQuery<>();
qry.setPageSize(10);
checkQueryNotFullyFetchedMetrics(cache, qry, true);
}
/**
* Test metrics for failed Scan queries.
*
* @throws Exception In case of error.
*/
public void testScanQueryFailedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
ScanQuery<Integer, String> qry = new ScanQuery<>(Integer.MAX_VALUE);
checkQueryFailedMetrics(cache, qry);
}
/**
* Test metrics for Sql queries.
*
* @throws Exception In case of error.
*/
public void testSqlQueryMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlQuery qry = new SqlQuery<>("String", "from String");
checkQueryMetrics(cache, qry);
}
/**
* Test metrics for Sql queries.
*
* @throws Exception In case of error.
*/
public void testSqlQueryNotFullyFetchedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlQuery qry = new SqlQuery<>("String", "from String");
qry.setPageSize(10);
checkQueryNotFullyFetchedMetrics(cache, qry, true);
}
/**
* Test metrics for failed Scan queries.
*
* @throws Exception In case of error.
*/
public void testSqlQueryFailedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlQuery qry = new SqlQuery<>("Long", "from Long");
checkQueryFailedMetrics(cache, qry);
}
/**
* Test metrics for Sql queries.
*
* @throws Exception In case of error.
*/
public void testTextQueryMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
TextQuery qry = new TextQuery<>("String", "1");
checkQueryMetrics(cache, qry);
}
/**
* Test metrics for Sql queries.
*
* @throws Exception In case of error.
*/
public void testTextQueryNotFullyFetchedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
TextQuery qry = new TextQuery<>("String", "1");
qry.setPageSize(10);
checkQueryNotFullyFetchedMetrics(cache, qry, true);
}
/**
* Test metrics for failed Scan queries.
*
* @throws Exception In case of error.
*/
public void testTextQueryFailedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
TextQuery qry = new TextQuery<>("Unknown", "zzz");
checkQueryFailedMetrics(cache, qry);
}
/**
* Test metrics for SQL cross cache queries.
*
* @throws Exception In case of error.
*/
public void testSqlFieldsCrossCacheQueryMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlFieldsQuery qry = new SqlFieldsQuery("select * from \"B\".String");
checkQueryMetrics(cache, qry);
}
/**
* Test metrics for SQL cross cache queries.
*
* @throws Exception In case of error.
*/
public void testSqlFieldsCrossCacheQueryNotFullyFetchedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlFieldsQuery qry = new SqlFieldsQuery("select * from \"B\".String");
qry.setPageSize(10);
checkQueryNotFullyFetchedMetrics(cache, qry, false);
}
/**
* Test metrics for failed SQL cross cache queries.
*
* @throws Exception In case of error.
*/
public void testSqlFieldsCrossCacheQueryFailedMetrics() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
SqlFieldsQuery qry = new SqlFieldsQuery("select * from \"G\".String");
checkQueryFailedMetrics(cache, qry);
}
/** */
private static class Worker extends Thread {
/** */
private final IgniteCache cache;
/** */
private final Query qry;
/** */
Worker(IgniteCache cache, Query qry) {
this.cache = cache;
this.qry = qry;
}
/** {@inheritDoc} */
@Override public void run() {
cache.query(qry).getAll();
}
}
/**
* Test metrics if queries executed from several threads.
*
* @throws Exception In case of error.
*/
public void testQueryMetricsMultithreaded() throws Exception {
IgniteCache<Integer, String> cache = grid(0).context().cache().jcache("A");
Collection<CacheAbstractQueryMetricsSelfTest.Worker> workers = new ArrayList<>();
int repeat = 100;
for (int i = 0; i < repeat; i++) {
workers.add(new CacheAbstractQueryMetricsSelfTest.Worker(cache, new SqlFieldsQuery("select * from String limit " + i)));
workers.add(new CacheAbstractQueryMetricsSelfTest.Worker(cache, new SqlQuery("String", "from String")));
workers.add(new CacheAbstractQueryMetricsSelfTest.Worker(cache, new ScanQuery()));
workers.add(new CacheAbstractQueryMetricsSelfTest.Worker(cache, new TextQuery("String", "1")));
}
for (CacheAbstractQueryMetricsSelfTest.Worker worker : workers)
worker.start();
for (CacheAbstractQueryMetricsSelfTest.Worker worker : workers)
worker.join();
checkMetrics(cache, repeat * 4, repeat * 4, 0, false);
}
/**
* Check metrics.
*
* @param cache Cache to check metrics.
* @param execs Expected number of executions.
* @param completions Expected number of completions.
* @param failures Expected number of failures.
* @param first {@code true} if metrics checked for first query only.
*/
private void checkMetrics(IgniteCache<Integer, String> cache, int execs, int completions, int failures, boolean first) {
GridCacheQueryMetricsAdapter m = (GridCacheQueryMetricsAdapter)cache.queryMetrics();
assertNotNull(m);
info("Metrics: " + m);
assertEquals("Executions", execs, m.executions());
assertEquals("Completions", completions, m.completedExecutions());
assertEquals("Failures", failures, m.fails());
assertTrue(m.averageTime() >= 0);
assertTrue(m.maximumTime() >= 0);
assertTrue(m.minimumTime() >= 0);
if (first)
assertTrue("On first execution minTime == maxTime", m.minimumTime() == m.maximumTime());
}
/**
* @param cache Cache.
* @param qry Query.
*/
private void checkQueryMetrics(IgniteCache<Integer, String> cache, Query qry) {
cache.query(qry).getAll();
checkMetrics(cache, 1, 1, 0, true);
// Execute again with the same parameters.
cache.query(qry).getAll();
checkMetrics(cache, 2, 2, 0, false);
}
/**
* @param cache Cache.
* @param qry Query.
* @param waitingForCompletion Waiting for query completion.
*/
private void checkQueryNotFullyFetchedMetrics(IgniteCache<Integer, String> cache, Query qry,
boolean waitingForCompletion) throws IgniteInterruptedCheckedException {
cache.query(qry).iterator().next();
if (waitingForCompletion)
waitingForCompletion(cache, 1);
checkMetrics(cache, 1, 1, 0, true);
// Execute again with the same parameters.
cache.query(qry).iterator().next();
if (waitingForCompletion)
waitingForCompletion(cache, 2);
checkMetrics(cache, 2, 2, 0, false);
}
/**
* @param cache Cache.
* @param qry Query.
*/
private void checkQueryFailedMetrics(IgniteCache<Integer, String> cache, Query qry) {
try {
cache.query(qry).getAll();
}
catch (Exception ignored) {
// No-op.
}
checkMetrics(cache, 1, 0, 1, true);
// Execute again with the same parameters.
try {
cache.query(qry).getAll();
}
catch (Exception ignored) {
// No-op.
}
checkMetrics(cache, 2, 0, 2, true);
}
/**
* @param cache Cache.
* @param exp Expected.
*/
private static void waitingForCompletion(final IgniteCache<Integer, String> cache,
final int exp) throws IgniteInterruptedCheckedException {
GridTestUtils.waitForCondition(new GridAbsPredicate() {
@Override public boolean apply() {
GridCacheQueryMetricsAdapter m = (GridCacheQueryMetricsAdapter)cache.queryMetrics();
return m.completedExecutions() == exp;
}
}, 5000);
}
}