/*
* 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.distributed.near;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import javax.cache.Cache;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.query.QueryCursor;
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.cluster.ClusterNode;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.managers.communication.GridIoMessage;
import org.apache.ignite.internal.processors.cache.IgniteCacheAbstractQuerySelfTest;
import org.apache.ignite.internal.processors.cache.query.GridCacheQueryRequest;
import org.apache.ignite.internal.processors.cache.query.GridCacheQueryResponse;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.lang.IgniteInClosure;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.spi.communication.CommunicationSpi;
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CachePeekMode.ALL;
/**
* Tests for partitioned cache queries.
*/
public class IgniteCachePartitionedQuerySelfTest extends IgniteCacheAbstractQuerySelfTest {
/** {@inheritDoc} */
@Override protected int gridCount() {
return 3;
}
/** {@inheritDoc} */
@Override protected CacheMode cacheMode() {
return PARTITIONED;
}
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
return super.getConfiguration(gridName).setCommunicationSpi(new TestTcpCommunicationSpi());
}
/**
* @throws Exception If failed.
*/
public void testFieldsQuery() throws Exception {
Person p1 = new Person("Jon", 1500);
Person p2 = new Person("Jane", 2000);
Person p3 = new Person("Mike", 1800);
Person p4 = new Person("Bob", 1900);
IgniteCache<UUID, Person> cache0 = jcache(UUID.class, Person.class);
cache0.put(p1.id(), p1);
cache0.put(p2.id(), p2);
cache0.put(p3.id(), p3);
cache0.put(p4.id(), p4);
assertEquals(4, cache0.localSize(ALL));
// Fields query
QueryCursor<List<?>> qry = cache0
.query(new SqlFieldsQuery("select name from Person where salary > ?").setArgs(1600));
Collection<List<?>> res = qry.getAll();
assertEquals(3, res.size());
// Fields query count(*)
qry = cache0.query(new SqlFieldsQuery("select count(*) from Person"));
res = qry.getAll();
int cnt = 0;
for (List<?> row : res)
cnt += (Long)row.get(0);
assertEquals(4, cnt);
}
/**
* @throws Exception If failed.
*/
public void testMultipleNodesQuery() throws Exception {
Person p1 = new Person("Jon", 1500);
Person p2 = new Person("Jane", 2000);
Person p3 = new Person("Mike", 1800);
Person p4 = new Person("Bob", 1900);
IgniteCache<UUID, Person> cache0 = jcache(UUID.class, Person.class);
cache0.put(p1.id(), p1);
cache0.put(p2.id(), p2);
cache0.put(p3.id(), p3);
cache0.put(p4.id(), p4);
assertEquals(4, cache0.localSize(ALL));
assert grid(0).cluster().nodes().size() == gridCount();
QueryCursor<Cache.Entry<UUID, Person>> qry =
cache0.query(new SqlQuery<UUID, Person>(Person.class, "salary < 2000"));
// Execute on full projection, duplicates are expected.
Collection<Cache.Entry<UUID, Person>> entries = qry.getAll();
assert entries != null;
info("Queried entries: " + entries);
// Expect result including backup persons.
assertEquals(gridCount(), entries.size());
checkResult(entries, p1, p3, p4);
}
/**
* @param entries Queried result.
* @param persons Persons that should be in the result.
*/
private void checkResult(Iterable<Cache.Entry<UUID, Person>> entries, Person... persons) {
for (Cache.Entry<UUID, Person> entry : entries) {
assertEquals(entry.getKey(), entry.getValue().id());
assert F.asList(persons).contains(entry.getValue());
}
}
/**
* @throws Exception If failed.
*/
public void testScanQueryPagination() throws Exception {
final int pageSize = 5;
final AtomicInteger pages = new AtomicInteger(0);
IgniteCache<Integer, Integer> cache = jcache(Integer.class, Integer.class);
for (int i = 0; i < 50; i++)
cache.put(i, i);
CommunicationSpi spi = ignite().configuration().getCommunicationSpi();
assert spi instanceof TestTcpCommunicationSpi;
TestTcpCommunicationSpi commSpi = (TestTcpCommunicationSpi)spi;
commSpi.filter = new IgniteInClosure<Message>() {
@Override public void apply(Message msg) {
if (!(msg instanceof GridIoMessage))
return;
Message msg0 = ((GridIoMessage)msg).message();
if (msg0 instanceof GridCacheQueryRequest) {
assertEquals(pageSize, ((GridCacheQueryRequest)msg0).pageSize());
pages.incrementAndGet();
}
else if (msg0 instanceof GridCacheQueryResponse)
assertTrue(((GridCacheQueryResponse)msg0).data().size() <= pageSize);
}
};
try {
ScanQuery<Integer, Integer> qry = new ScanQuery<Integer, Integer>();
qry.setPageSize(pageSize);
List<Cache.Entry<Integer, Integer>> all = cache.query(qry).getAll();
assertTrue(pages.get() > ignite().cluster().forDataNodes(DEFAULT_CACHE_NAME).nodes().size());
assertEquals(50, all.size());
}
finally {
commSpi.filter = null;
}
}
/**
*
*/
private static class TestTcpCommunicationSpi extends TcpCommunicationSpi {
/** */
volatile IgniteInClosure<Message> filter;
/** {@inheritDoc} */
@Override public void sendMessage(ClusterNode node, Message msg, IgniteInClosure<IgniteException> ackC) {
if (filter != null)
filter.apply(msg);
super.sendMessage(node, msg, ackC);
}
}
}