http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c82d4d8e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
----------------------------------------------------------------------
diff --cc 
modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
index 0000000,b19e8f0..431123b
mode 000000,100644..100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
@@@ -1,0 -1,1554 +1,1565 @@@
+ /*
+  * 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 org.apache.ignite.*;
+ import org.apache.ignite.cache.*;
+ import org.apache.ignite.cache.query.*;
+ import org.apache.ignite.cache.query.annotations.*;
+ import org.apache.ignite.cache.store.*;
+ import org.apache.ignite.configuration.*;
+ import org.apache.ignite.events.*;
+ import org.apache.ignite.internal.*;
+ import org.apache.ignite.internal.processors.cache.distributed.replicated.*;
+ import org.apache.ignite.internal.processors.cache.query.*;
+ import org.apache.ignite.internal.util.tostring.*;
+ import org.apache.ignite.internal.util.typedef.*;
+ import org.apache.ignite.internal.util.typedef.internal.*;
+ import org.apache.ignite.lang.*;
+ import org.apache.ignite.marshaller.optimized.*;
+ import org.apache.ignite.spi.discovery.tcp.*;
+ import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+ import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+ import org.apache.ignite.spi.swapspace.file.*;
+ import org.apache.ignite.testframework.*;
+ import org.apache.ignite.testframework.junits.common.*;
+ import org.jdk8.backport.*;
+ import org.jetbrains.annotations.*;
+ 
+ import javax.cache.*;
+ import javax.cache.configuration.*;
+ import javax.cache.expiry.*;
+ import java.io.*;
+ import java.util.*;
+ import java.util.concurrent.*;
+ 
+ import static java.util.concurrent.TimeUnit.*;
+ import static org.apache.ignite.cache.CacheAtomicityMode.*;
+ import static org.apache.ignite.cache.CacheDistributionMode.*;
+ import static org.apache.ignite.cache.CacheMode.*;
+ import static org.apache.ignite.cache.CacheRebalanceMode.*;
+ import static org.apache.ignite.cache.CacheWriteSynchronizationMode.*;
+ import static org.apache.ignite.events.EventType.*;
+ import static 
org.apache.ignite.internal.processors.cache.query.CacheQueryType.*;
+ import static org.junit.Assert.*;
+ 
+ /**
+  * Various tests for cache queries.
+  */
+ public abstract class IgniteCacheAbstractQuerySelfTest extends 
GridCommonAbstractTest {
+     /** Cache store. */
+     private static TestStore store = new TestStore();
+ 
+     /** */
+     private static final TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
+ 
+     /** */
+     protected Ignite ignite;
+ 
+     /**
+      * @return Grid count.
+      */
+     protected abstract int gridCount();
+ 
+     /**
+      * @return Cache mode.
+      */
+     protected abstract CacheMode cacheMode();
+ 
+     /**
+      * @return Atomicity mode.
+      */
+     protected CacheAtomicityMode atomicityMode() {
+         return TRANSACTIONAL;
+     }
+ 
+     /**
+      * @return Distribution.
+      */
+     protected CacheDistributionMode distributionMode() {
+         return NEAR_PARTITIONED;
+     }
+ 
+     /** {@inheritDoc} */
+     @SuppressWarnings("unchecked")
+     @Override protected IgniteConfiguration getConfiguration(String gridName) 
throws Exception {
+         IgniteConfiguration c = super.getConfiguration(gridName);
+ 
+         TcpDiscoverySpi disco = new TcpDiscoverySpi();
+ 
+         disco.setIpFinder(ipFinder);
+ 
+         c.setDiscoverySpi(disco);
+ 
+         // Otherwise noop swap space will be chosen on Windows.
+         c.setSwapSpaceSpi(new FileSwapSpaceSpi());
+ 
+         c.setMarshaller(new OptimizedMarshaller(false));
+ 
 -        CacheConfiguration[] ccs = new CacheConfiguration[2];
++        if (!gridName.startsWith("client")) {
++            CacheConfiguration[] ccs = new CacheConfiguration[2];
+ 
 -        for (int i = 0; i < ccs.length; i++) {
 -            CacheConfiguration cc = defaultCacheConfiguration();
++            for (int i = 0; i < ccs.length; i++) {
++                CacheConfiguration cc = defaultCacheConfiguration();
+ 
 -            if (i > 0)
 -                cc.setName("c" + i);
++                if (i > 0)
++                    cc.setName("c" + i);
+ 
+             cc.setCacheMode(cacheMode());
+             cc.setAtomicityMode(atomicityMode());
 -            cc.setDistributionMode(gridName.startsWith("client") ? 
CLIENT_ONLY : distributionMode());
+             cc.setWriteSynchronizationMode(FULL_SYNC);
+             cc.setCacheStoreFactory(new 
FactoryBuilder.SingletonFactory(store));
+             cc.setReadThrough(true);
+             cc.setWriteThrough(true);
+             cc.setLoadPreviousValue(true);
+             cc.setRebalanceMode(SYNC);
+             cc.setSwapEnabled(true);
 -            cc.setEvictNearSynchronized(false);
+             cc.setSqlFunctionClasses(SqlFunctions.class);
+             cc.setIndexedTypes(
+                 BadHashKeyObject.class, Byte.class,
+                 ObjectValue.class, Long.class,
+                 Integer.class, Integer.class,
+                 Integer.class, String.class,
+                 Integer.class, ObjectValue.class,
+                 String.class, ObjectValueOther.class,
+                 Integer.class, ArrayObject.class,
+                 Key.class, GridCacheQueryTestValue.class,
+                 UUID.class, Person.class,
+                 IgniteCacheReplicatedQuerySelfTest.CacheKey.class, 
IgniteCacheReplicatedQuerySelfTest.CacheValue.class
+             );
+ 
+             // Explicitly set number of backups equal to number of grids.
+             if (cacheMode() == CacheMode.PARTITIONED)
+                 cc.setBackups(gridCount());
+ 
 -            ccs[i] = cc;
 -        }
++                ccs[i] = cc;
++            }
+ 
 -        c.setCacheConfiguration(ccs);
++            c.setCacheConfiguration(ccs);
++        }
++        else
++            c.setClientMode(true);
+ 
+         return c;
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void beforeTest() throws Exception {
+         ignite = startGridsMultiThreaded(gridCount());
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void afterTest() throws Exception {
+         stopAllGrids();
+ 
+         store.reset();
+ 
+         ignite = null;
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testDifferentKeyTypes() throws Exception {
+         final IgniteCache<Object, Object> cache = ignite.jcache(null);
+ 
+         cache.put(1, "value");
+ 
+         try {
+             cache.put("key", "value");
+ 
+             fail();
+         }
+         catch (CacheException e) {
+             // No-op.
+         }
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testDifferentValueTypes() throws Exception {
+         GridCache<Integer, Object> cache = ((IgniteKernal)ignite).cache(null);
+ 
+         cache.putx(7, "value");
+ 
+         // Put value of different type but for the same key type.
+         // Operation should succeed but with warning log message.
+         cache.putx(7, 1);
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testStringType() throws Exception {
+         IgniteCache<Integer, String> cache = ignite.jcache(null);
+ 
+         cache.put(666, "test");
+ 
+         QueryCursor<Cache.Entry<Integer, String>> qry = cache.query(new 
SqlQuery(String.class, "_val='test'"));
+ 
+         Cache.Entry<Integer, String> entry = F.first(qry.getAll());
+ 
+         assert entry != null;
+         assertEquals(666, entry.getKey().intValue());
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testIntegerType() throws Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         int key = 898;
+ 
+         int val = 2;
+ 
+         cache.put(key, val);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> qry =
+             cache.query(new SqlQuery(Integer.class, "_key = ? and _val > 
1").setArgs(key));
+ 
+         Cache.Entry<Integer, Integer> entry = F.first(qry.getAll());
+ 
+         assert entry != null;
+ 
+         assertEquals(key, entry.getKey().intValue());
+         assertEquals(val, entry.getValue().intValue());
+     }
+ 
+     /**
+      * Tests UDFs.
+      *
+      * @throws IgniteCheckedException If failed.
+      */
+     public void testUserDefinedFunction() throws IgniteCheckedException {
+         // Without alias.
+         final IgniteCache<Object, Object> cache = ignite.jcache(null);
+ 
+         QueryCursor<List<?>> qry = cache.queryFields(new 
SqlFieldsQuery("select square(1), square(2)"));
+ 
+         Collection<List<?>> res = qry.getAll();
+ 
+         if (cacheMode() == REPLICATED)
+             assertEquals(1, res.size());
+         else
+             assertEquals(gridCount(), res.size());
+ 
+         List<?> row = res.iterator().next();
+ 
+         assertEquals(1, row.get(0));
+         assertEquals(4, row.get(1));
+ 
+         // With alias.
+         qry = cache.queryFields(new SqlFieldsQuery("select _cube_(1), 
_cube_(2)"));
+ 
+         res = qry.getAll();
+ 
+         if (cacheMode() == REPLICATED)
+             assertEquals(1, res.size());
+         else
+             assertEquals(gridCount(), res.size());
+ 
+         row = res.iterator().next();
+ 
+         assertEquals(1, row.get(0));
+         assertEquals(8, row.get(1));
+ 
+         // Not registered.
+         GridTestUtils.assertThrows(
+             log,
+             new Callable<Object>() {
+                 @Override public Object call() throws Exception {
+                     cache.queryFields(new SqlFieldsQuery("select no()"));
+ 
+                     return null;
+                 }
+             },
+             CacheException.class,
+             null
+         );
+     }
+ 
+     /**
+      * Expired entries are not included to result.
+      *
+      * @throws Exception If failed.
+      */
+     public void testExpiration() throws Exception {
+         ignite.jcache(null).
+             withExpiryPolicy(new TouchedExpiryPolicy(new 
Duration(MILLISECONDS, 1000))).put(7, 1);
+ 
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         List<Cache.Entry<Integer, Integer>> qry = cache.query(new 
SqlQuery(Integer.class, "1=1")).getAll();
+ 
+         Cache.Entry<Integer, Integer> res = F.first(qry);
+ 
+         assertEquals(1, res.getValue().intValue());
+ 
+         U.sleep(1020);
+ 
+         qry = cache.query(new SqlQuery(Integer.class, "1=1")).getAll();
+ 
+         res = F.first(qry);
+ 
+         assertNull(res);
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testIllegalBounds() throws Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         cache.put(1, 1);
+         cache.put(2, 2);
+ 
+         QueryCursor<Cache.Entry<Integer,Integer>> qry = cache.query(new 
SqlQuery(Integer.class, "_key between 2 and 1"));
+ 
+         assertTrue(qry.getAll().isEmpty());
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testComplexType() throws Exception {
+         IgniteCache<Key, GridCacheQueryTestValue> cache = ignite.jcache(null);
+ 
+         GridCacheQueryTestValue val1 = new GridCacheQueryTestValue();
+ 
+         val1.setField1("field1");
+         val1.setField2(1);
+         val1.setField3(1L);
+ 
+         GridCacheQueryTestValue val2 = new GridCacheQueryTestValue();
+ 
+         val2.setField1("field2");
+         val2.setField2(2);
+         val2.setField3(2L);
+         val2.setField6(null);
+ 
+         cache.put(new Key(100500), val1);
+         cache.put(new Key(100501), val2);
+ 
+         QueryCursor<Cache.Entry<Key, GridCacheQueryTestValue>> qry = cache
+             .query(new SqlQuery(GridCacheQueryTestValue.class,
+                     "fieldName='field1' and field2=1 and field3=1 and 
id=100500 and embeddedField2=11 and x=3"));
+ 
+         Cache.Entry<Key, GridCacheQueryTestValue> entry = 
F.first(qry.getAll());
+ 
+         assertNotNull(entry);
+         assertEquals(100500, entry.getKey().id);
+         assertEquals(val1, entry.getValue());
+     }
+ 
+     /**
+      * Complex key type.
+      */
+     private static class Key {
+         /** */
+         @QuerySqlField
+         private final long id;
+ 
+         /**
+          * @param id Id.
+          */
+         private Key(long id) {
+             this.id = id;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public boolean equals(Object o) {
+             if (this == o)
+                 return true;
+ 
+             if (o == null || getClass() != o.getClass())
+                 return false;
+ 
+             Key key = (Key)o;
+ 
+             return id == key.id;
+ 
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public int hashCode() {
+             return (int)(id ^ (id >>> 32));
+         }
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testSelectQuery() throws Exception {
+         IgniteCache<Integer, String> cache = ignite.jcache(null);
+ 
+         cache.put(10, "value");
+ 
+         QueryCursor<Cache.Entry<Integer, String>> qry = cache.query(new 
SqlQuery(String.class, "true"));
+ 
+         Iterator<Cache.Entry<Integer, String>> iter = qry.iterator();
+ 
+         assert iter != null;
+         assert iter.next() != null;
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testObjectQuery() throws Exception {
+         IgniteCache<Integer, ObjectValue> cache = ignite.jcache(null);
+ 
+         ObjectValue val = new ObjectValue("test", 0);
+ 
+         cache.put(1, val);
+ 
+         QueryCursor<Cache.Entry<Integer, ObjectValue>> qry =
+             cache.query(new SqlQuery(ObjectValue.class, 
"_val=?").setArgs(val));
+ 
+         Iterator<Cache.Entry<Integer, ObjectValue>> iter = qry.iterator();
+ 
+         assert iter != null;
+ 
+         int expCnt = 1;
+ 
+         for (int i = 0; i < expCnt; i++)
+             assert iter.next() != null;
+ 
+         assert !iter.hasNext();
+ 
+         qry = cache.query(new TextQuery(ObjectValue.class, "test"));
+ 
+         iter = qry.iterator();
+ 
+         assert iter != null;
+ 
+         for (int i = 0; i < expCnt; i++)
+             assert iter.next() != null;
+ 
+         assert !iter.hasNext();
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testObjectQueryWithSwap() throws Exception {
+         IgniteCache<Integer, ObjectValue> cache = ignite.jcache(null);
+ 
+         boolean partitioned = 
cache.getConfiguration(CacheConfiguration.class).getCacheMode() == PARTITIONED;
+ 
+         int cnt = 10;
+ 
+         for (int i = 0; i < cnt; i++)
+             cache.put(i, new ObjectValue("test" + i, i));
+ 
+         for (Ignite g : G.allGrids()) {
+             GridCache<Integer, ObjectValue> c = ((IgniteKernal)g).cache(null);
+ 
+             for (int i = 0; i < cnt; i++) {
+                 if (i % 2 == 0) {
+                     assertNotNull(c.peek(i));
+ 
+                     c.evict(i); // Swap.
+ 
+                     if (!partitioned || 
c.affinity().mapKeyToNode(i).isLocal()) {
+                         ObjectValue peekVal = c.peek(i);
+ 
+                         assertNull("Non-null value for peek [key=" + i + ", 
val=" + peekVal + ']', peekVal);
+                     }
+                 }
+             }
+         }
+ 
+ 
+         QueryCursor<Cache.Entry<Integer, ObjectValue>> qry =
+             cache.query(new SqlQuery(ObjectValue.class, "intVal >= ? order by 
intVal").setArgs(0));
+ 
+         Iterator<Cache.Entry<Integer, ObjectValue>> iter = qry.iterator();
+ 
+         assert iter != null;
+ 
+         Collection<Integer> set = new HashSet<>(cnt);
+ 
+         Cache.Entry<Integer, ObjectValue> next;
+ 
+         while (iter.hasNext()) {
+             next = iter.next();
+             
+             ObjectValue v = next.getValue();
+ 
+             assert !set.contains(v.intValue());
+ 
+             set.add(v.intValue());
+         }
+ 
+         assert !iter.hasNext();
+ 
+         assertEquals(cnt, set.size());
+ 
+         for (int i = 0; i < cnt; i++)
+             assert set.contains(i);
+ 
+         qry = cache.query(new SqlQuery(ObjectValue.class, "MOD(intVal, 2) = ? 
order by intVal").setArgs(0));
+ 
+         iter = qry.iterator();
+ 
+         assert iter != null;
+ 
+         set.clear();
+ 
+         while (iter.hasNext()) {
+             next = iter.next();
+ 
+             ObjectValue v = next.getValue();
+ 
+             assert !set.contains(v.intValue());
+ 
+             set.add(v.intValue());
+         }
+ 
+         assert !iter.hasNext();
+ 
+         assertEquals(cnt / 2, set.size());
+ 
+         for (int i = 0; i < cnt; i++)
+             if (i % 2 == 0)
+                 assert set.contains(i);
+             else
+                 assert !set.contains(i);
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testFullTextSearch() throws Exception {
+         IgniteCache<Integer, ObjectValue> cache = ignite.jcache(null);
+ 
+         // Try to execute on empty cache first.
+         QueryCursor<Cache.Entry<Integer, ObjectValue>> qry =
+             cache.query(new TextQuery(ObjectValue.class, "full"));
+ 
+         assert qry.getAll().isEmpty();
+ 
+         qry = cache.query(new TextQuery(ObjectValue.class, "full"));
+ 
+         assert qry.getAll().isEmpty();
+ 
+         // Now put indexed values into cache.
+         int key1 = 1;
+ 
+         ObjectValue val1 = new ObjectValue("test full text", 0);
+ 
+         cache.put(key1, val1);
+ 
+         int key2 = 2;
+ 
+         ObjectValue val2 = new ObjectValue("test full text more", 0);
+ 
+         cache.put(key2, val2);
+ 
+         qry = cache.query(new TextQuery(ObjectValue.class, "full"));
+ 
+         Collection<Cache.Entry<Integer, ObjectValue>> res = qry.getAll();
+ 
+         assert res != null;
+ 
+         assert res.size() == 2;
+ 
+         qry = cache.query(new TextQuery(ObjectValue.class, "full"));
+ 
+         res = qry.getAll();
+ 
+         assert res != null;
+         assert res.size() == 2;
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testScanQuery() throws Exception {
+         IgniteCache<Integer, String> c1 = ignite.jcache(null);
+ 
+         c1.put(777, "value");
+ 
+         // Scan query.
+         QueryCursor<Cache.Entry<Integer, String>> qry = c1.query(new 
ScanQuery<String, String>());
+ 
+         Iterator<Cache.Entry<Integer, String>> iter = qry.iterator();
+ 
+         assert iter != null;
+ 
+         int expCnt = 1;
+ 
+         for (int i = 0; i < expCnt; i++) {
+             Cache.Entry<Integer, String> e1 = iter.next();
+ 
+             assertEquals(777, e1.getKey().intValue());
+             assertEquals("value", e1.getValue());
+         }
+ 
+         assert !iter.hasNext();
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception In case of error.
+      */
+     public void testTwoObjectsTextSearch() throws Exception {
+         IgniteCache<Object, Object> c = ignite.jcache(null);
+ 
+         c.put(1, new ObjectValue("ObjectValue str", 1));
+         c.put("key", new ObjectValueOther("ObjectValueOther str"));
+ 
+         Collection<Cache.Entry<Object, Object>> res = c.query(new 
TextQuery(ObjectValue.class, "str")).getAll();
+ 
+         assert res != null;
+         int expCnt = 1;
+         assert res.size() == expCnt;
+         assert F.first(res).getValue().getClass() == ObjectValue.class;
+ 
+         res = c.query(new TextQuery(ObjectValueOther.class, "str")).getAll();
+ 
+         assert res != null;
+         assert res.size() == expCnt;
+         assert F.first(res).getValue().getClass() == ObjectValueOther.class;
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testEmptyObject() throws Exception {
+         IgniteCache<EmptyObject, EmptyObject> cache = ignite.jcache(null);
+ 
+         cache.put(new EmptyObject(1), new EmptyObject(2));
+ 
+         for (int i = 0; i < gridCount(); i++) {
+             GridCacheQueryManager<Object, Object> qryMgr =
+                 ((IgniteKernal)grid(i)).internalCache().context().queries();
+ 
+             assert !hasIndexTable(EmptyObject.class, qryMgr);
+         }
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testPrimitiveType() throws Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         cache.put(1, 1);
+         cache.put(2, 2);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q = cache.query(new 
SqlQuery(Integer.class, "_val > 1"));
+ 
+         Collection<Cache.Entry<Integer, Integer>> res = q.getAll();
+ 
+         assertEquals(1, res.size());
+ 
+         for (Cache.Entry<Integer, Integer> e : res) {
+             assertEquals(2, (int)e.getKey());
+             assertEquals(2, (int)e.getValue());
+         }
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testPaginationIteratorDefaultCache() throws Exception {
+         testPaginationIterator(null);
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testPaginationIteratorNamedCache() throws Exception {
+         testPaginationIterator("c1");
+     }
+ 
+     /**
+      * @param cacheName Cache name.
+      * @throws Exception If failed.
+      */
+     private void testPaginationIterator(@Nullable String cacheName) throws 
Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(cacheName);
+ 
+         for (int i = 0; i < 50; i++)
+             cache.put(i, i);
+ 
+         SqlQuery qry = new SqlQuery(Integer.class, "_key >= 0");
+ 
+         qry.setPageSize(10);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q = cache.query(qry);
+ 
+         int cnt = 0;
+ 
+         for (Cache.Entry<Integer, Integer> e : q) {
+             assertTrue(e.getKey() >= 0 && e.getKey() < 50);
+             assertTrue(e.getValue() >= 0 && e.getValue() < 50);
+ 
+             cnt++;
+         }
+ 
+         assertEquals(50, cnt);
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testPaginationGetDefaultCache() throws Exception {
+         testPaginationGet(null);
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testPaginationGetNamedCache() throws Exception {
+         testPaginationGet("c1");
+     }
+ 
+     /**
+      * @param cacheName Cache name.
+      * @throws Exception If failed.
+      */
+     private void testPaginationGet(@Nullable String cacheName) throws 
Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(cacheName);
+ 
+         for (int i = 0; i < 50; i++)
+             cache.put(i, i);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q =
+             cache.query(new SqlQuery(Integer.class, "_key >= 0"));
+ 
+         List<Cache.Entry<Integer, Integer>> list = new 
ArrayList<>(q.getAll());
+ 
+         Collections.sort(list, new Comparator<Cache.Entry<Integer, 
Integer>>() {
+             @Override public int compare(Cache.Entry<Integer, Integer> e1, 
Cache.Entry<Integer, Integer> e2) {
+                 return e1.getKey().compareTo(e2.getKey());
+             }
+         });
+ 
+         for (int i = 0; i < 50; i++) {
+             Cache.Entry<Integer, Integer> e = list.get(i);
+ 
+             assertEquals(i, (int)e.getKey());
+             assertEquals(i, (int)e.getValue());
+         }
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testScanFilters() throws Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         for (int i = 0; i < 50; i++)
+             cache.put(i, i);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q = cache.query(new 
ScanQuery(new IgniteBiPredicate<Integer,Integer>() {
+             @Override public boolean apply(Integer k, Integer v) {
+                 assertNotNull(k);
+                 assertNotNull(v);
+ 
+                 return k >= 20 && v < 40;
+             }
+         }));
+ 
+         List<Cache.Entry<Integer, Integer>> list = new 
ArrayList<>(q.getAll());
+ 
+         Collections.sort(list, new Comparator<Cache.Entry<Integer, 
Integer>>() {
+             @Override public int compare(Cache.Entry<Integer, Integer> e1, 
Cache.Entry<Integer, Integer> e2) {
+                 return e1.getKey().compareTo(e2.getKey());
+             }
+         });
+ 
+         assertEquals(20, list.size());
+ 
+         for (int i = 20; i < 40; i++) {
+             Cache.Entry<Integer, Integer> e = list.get(i - 20);
+ 
+             assertEquals(i, (int)e.getKey());
+             assertEquals(i, (int)e.getValue());
+         }
+     }
+ 
+     /**
+      * @throws IgniteCheckedException if failed.
+      */
+     public void testBadHashObjectKey() throws IgniteCheckedException {
+         IgniteCache<BadHashKeyObject, Byte> cache = ignite.jcache(null);
+ 
+         cache.put(new BadHashKeyObject("test_key1"), (byte)1);
+         cache.put(new BadHashKeyObject("test_key0"), (byte)10);
+         cache.put(new BadHashKeyObject("test_key1"), (byte)7);
+ 
+         assertEquals(10, cache.query(new SqlQuery(Byte.class, "_key = 
?").setArgs(
+             new 
BadHashKeyObject("test_key0"))).getAll().get(0).getValue().intValue());
+     }
+ 
+     /**
+      * @throws IgniteCheckedException if failed.
+      */
+     public void testTextIndexedKey() throws IgniteCheckedException {
+         IgniteCache<ObjectValue, Long> cache = ignite.jcache(null);
+ 
+         cache.put(new ObjectValue("test_key1", 10), 19L);
+         cache.put(new ObjectValue("test_key0", 11), 11005L);
+         cache.put(new ObjectValue("test_key1", 12), 17L);
+ 
+         assertEquals(11005L,
+             cache.query(new TextQuery(Long.class, "test_key0"))
+                 .getAll().get(0).getValue().intValue());
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testOrderByOnly() throws Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         for (int i = 0; i < 10; i++)
+             cache.put(i, i);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q =
+             cache.query(new SqlQuery(Integer.class, "_key >= 0"));
+ 
+         Collection<Cache.Entry<Integer, Integer>> res = q.getAll();
+ 
+         assertEquals(10, res.size());
+ 
+         if (cacheMode() != PARTITIONED) {
+             Iterator<Cache.Entry<Integer, Integer>> it = res.iterator();
+ 
+             for (Integer i = 0; i < 10; i++) {
+                 assertTrue(it.hasNext());
+ 
+                 Cache.Entry<Integer, Integer> e = it.next();
+ 
+                 assertEquals(i, e.getKey());
+                 assertEquals(i, e.getValue());
+             }
+         }
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testLimitOnly() throws Exception {
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         for (int i = 0; i < 10; i++)
+             cache.put(i, i);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q =
+                 cache.query(new SqlQuery(Integer.class, "limit 5"));
+ 
+         Collection<Cache.Entry<Integer, Integer>> res = q.getAll();
+ 
+         assertEquals(5, res.size());
+ 
+         Set<Integer> checkDuplicate = new HashSet<>();
+ 
+         for (Cache.Entry<Integer, Integer> e : res) {
+             assert e.getKey() < 10 && e.getKey() >= 0;
+             assert e.getValue() < 10 && e.getValue() >= 0;
+ 
+             checkDuplicate.add(e.getValue());
+         }
+ 
+         assertEquals(5, checkDuplicate.size());
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testArray() throws Exception {
+         IgniteCache<Integer, ArrayObject> cache = ignite.jcache(null);
+ 
+         cache.put(1, new ArrayObject(new Long[]{1L, null, 3L}));
+         cache.put(2, new ArrayObject(new Long[] {4L, 5L, 6L}));
+ 
+         QueryCursor<Cache.Entry<Integer, ArrayObject>> q =
+             cache.query(new SqlQuery(ArrayObject.class, "array_contains(arr, 
cast(? as long))").setArgs(4));
+ 
+         Collection<Cache.Entry<Integer, ArrayObject>> res = q.getAll();
+ 
+         assertEquals(1, res.size());
+ 
+         Cache.Entry<Integer, ArrayObject> e = F.first(res);
+ 
+         assertEquals(2, (int)e.getKey());
+         assertArrayEquals(new Long[]{4L, 5L, 6L}, e.getValue().arr);
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testSqlQueryEvents() throws Exception {
+         checkSqlQueryEvents();
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     private void checkSqlQueryEvents() throws Exception {
+         final CountDownLatch execLatch = new CountDownLatch(cacheMode() == 
REPLICATED ? 1 : gridCount());
+ 
+         for (int i = 0; i < gridCount(); i++) {
+             grid(i).events().localListen(new IgnitePredicate<Event>() {
+                 @Override public boolean apply(Event evt) {
+                     assert evt instanceof CacheQueryExecutedEvent;
+ 
+                     CacheQueryExecutedEvent qe = (CacheQueryExecutedEvent)evt;
+ 
+                     assertNull(qe.cacheName());
+                     assertNotNull(qe.clause());
+                     assertNull(qe.scanQueryFilter());
+                     assertNull(qe.continuousQueryFilter());
+                     assertArrayEquals(new Integer[] { 10 }, qe.arguments());
+ 
+                     execLatch.countDown();
+ 
+                     return true;
+                 }
+             }, EVT_CACHE_QUERY_EXECUTED);
+         }
+ 
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         for (int i = 0; i < 20; i++)
+             cache.put(i, i);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q =
+             cache.query(new SqlQuery(Integer.class, "_key >= ?").setArgs(10));
+ 
+         q.getAll();
+ 
+         assert execLatch.await(1000, MILLISECONDS);
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testScanQueryEvents() throws Exception {
+         checkScanQueryEvents();
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     private void checkScanQueryEvents() throws Exception {
+         final Map<Integer, Integer> map = new ConcurrentHashMap8<>();
+         final CountDownLatch latch = new CountDownLatch(10);
+         final CountDownLatch execLatch = new CountDownLatch(cacheMode() == 
REPLICATED ? 1 : gridCount());
+ 
+         for (int i = 0; i < gridCount(); i++) {
+             grid(i).events().localListen(new IgnitePredicate<Event>() {
+                 @Override public boolean apply(Event evt) {
+                     assert evt instanceof CacheQueryReadEvent;
+ 
+                     CacheQueryReadEvent<Integer, Integer> qe = 
(CacheQueryReadEvent<Integer, Integer>)evt;
+ 
+                     assertEquals(SCAN, qe.queryType());
+                     assertNull(qe.cacheName());
+ 
+                     assertNull(qe.className());
+                     assertNull(null, qe.clause());
+                     assertNotNull(qe.scanQueryFilter());
+                     assertNull(qe.continuousQueryFilter());
+                     assertNull(qe.arguments());
+ 
+                     map.put(qe.key(), qe.value());
+ 
+                     latch.countDown();
+ 
+                     return true;
+                 }
+             }, EVT_CACHE_QUERY_OBJECT_READ);
+ 
+             grid(i).events().localListen(new IgnitePredicate<Event>() {
+                 @Override public boolean apply(Event evt) {
+                     assert evt instanceof CacheQueryExecutedEvent;
+ 
+                     CacheQueryExecutedEvent qe = (CacheQueryExecutedEvent)evt;
+ 
+                     assertEquals(SCAN, qe.queryType());
+                     assertNull(qe.cacheName());
+ 
+                     assertNull(qe.className());
+                     assertNull(null, qe.clause());
+                     assertNotNull(qe.scanQueryFilter());
+                     assertNull(qe.continuousQueryFilter());
+                     assertNull(qe.arguments());
+ 
+                     execLatch.countDown();
+ 
+                     return true;
+                 }
+             }, EVT_CACHE_QUERY_EXECUTED);
+         }
+ 
+         IgniteCache<Integer, Integer> cache = ignite.jcache(null);
+ 
+         for (int i = 0; i < 20; i++)
+             cache.put(i, i);
+ 
+         QueryCursor<Cache.Entry<Integer, Integer>> q = cache.query(new 
ScanQuery<>(new IgniteBiPredicate<Integer,Integer>() {
+             @Override public boolean apply(Integer k, Integer v) {
+                 return k >= 10;
+             }
+         }));
+ 
+         q.getAll();
+ 
+         assert latch.await(1000, MILLISECONDS);
+         assert execLatch.await(1000, MILLISECONDS);
+ 
+         assertEquals(10, map.size());
+ 
+         for (int i = 10; i < 20; i++)
+             assertEquals(i, map.get(i).intValue());
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testTextQueryEvents() throws Exception {
+         testTextQueryEvents(false);
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     private void testTextQueryEvents(final boolean customSubjId) throws 
Exception {
+         final Map<Integer, Person> map = new ConcurrentHashMap8<>();
+         final CountDownLatch latch = new CountDownLatch(2);
+         final CountDownLatch execLatch = new CountDownLatch(cacheMode() == 
REPLICATED ? 1 : gridCount());
+ 
+         for (int i = 0; i < gridCount(); i++) {
+             grid(i).events().localListen(new IgnitePredicate<Event>() {
+                 @Override public boolean apply(Event evt) {
+                     assert evt instanceof CacheQueryReadEvent;
+ 
+                     CacheQueryReadEvent<Integer, Person> qe = 
(CacheQueryReadEvent<Integer, Person>)evt;
+ 
+                     assertEquals(FULL_TEXT, qe.queryType());
+                     assertNull(qe.cacheName());
+ 
+                     assertEquals("Person", qe.className());
+                     assertEquals("White", qe.clause());
+                     assertNull(qe.scanQueryFilter());
+                     assertNull(qe.continuousQueryFilter());
+                     assertNull(qe.arguments());
+ 
+                     map.put(qe.key(), qe.value());
+ 
+                     latch.countDown();
+ 
+                     return true;
+                 }
+             }, EVT_CACHE_QUERY_OBJECT_READ);
+ 
+             grid(i).events().localListen(new IgnitePredicate<Event>() {
+                 @Override public boolean apply(Event evt) {
+                     assert evt instanceof CacheQueryExecutedEvent;
+ 
+                     CacheQueryExecutedEvent qe = (CacheQueryExecutedEvent)evt;
+ 
+                     assertEquals(FULL_TEXT, qe.queryType());
+                     assertNull(qe.cacheName());
+ 
+                     assertEquals("Person", qe.className());
+                     assertEquals("White", qe.clause());
+                     assertNull(qe.scanQueryFilter());
+                     assertNull(qe.continuousQueryFilter());
+                     assertNull(qe.arguments());
+ 
+                     execLatch.countDown();
+ 
+                     return true;
+                 }
+             }, EVT_CACHE_QUERY_EXECUTED);
+         }
+ 
+         IgniteCache<Integer, Person> cache = ignite.jcache(null);
+ 
+         cache.put(1, new Person("Bob White", 1000));
+         cache.put(2, new Person("Tom White", 1000));
+         cache.put(3, new Person("Mike Green", 1000));
+ 
+ 
+         QueryCursor<Cache.Entry<Integer, Person>> q = cache.query(new 
TextQuery(Person.class, "White"));
+ 
+         q.getAll();
+ 
+         assert latch.await(1000, MILLISECONDS);
+         assert execLatch.await(1000, MILLISECONDS);
+ 
+         assertEquals(2, map.size());
+ 
+         assertEquals("Bob White", map.get(1).name());
+         assertEquals("Tom White", map.get(2).name());
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     public void testFieldsQueryEvents() throws Exception {
+         checkFieldsQueryEvents();
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     private void checkFieldsQueryEvents() throws Exception {
+         final CountDownLatch execLatch = new CountDownLatch(cacheMode() == 
REPLICATED ? 1 : gridCount());
+ 
+         for (int i = 0; i < gridCount(); i++) {
+             grid(i).events().localListen(new IgnitePredicate<Event>() {
+                 @Override public boolean apply(Event evt) {
+                     assert evt instanceof CacheQueryExecutedEvent;
+ 
+                     CacheQueryExecutedEvent qe = (CacheQueryExecutedEvent)evt;
+ 
+                     assertNull(qe.cacheName());
+                     assertNotNull(qe.clause());
+                     assertNull(qe.scanQueryFilter());
+                     assertNull(qe.continuousQueryFilter());
+                     assertArrayEquals(new Integer[]{10}, qe.arguments());
+ 
+                     execLatch.countDown();
+ 
+                     return true;
+                 }
+             }, EVT_CACHE_QUERY_EXECUTED);
+         }
+ 
+         IgniteCache<Integer, Person> cache = ignite.jcache(null);
+ 
+         for (int i = 1; i <= 20; i++)
+             cache.put(i, new Person("Person " + i, i));
+ 
+         QueryCursor<List<?>> q = cache
+             .queryFields(new SqlFieldsQuery("select _key, name from Person 
where salary > ?").setArgs(10));
+ 
+         q.getAll();
+ 
+         assert execLatch.await(1000, MILLISECONDS);
+     }
+ 
+     /**
+      * @param cls Class to check index table for.
+      * @param qryMgr Query manager.
+      * @return {@code true} if index has a table for given class.
+      * @throws IgniteCheckedException If failed.
+      */
+     private boolean hasIndexTable(Class<?> cls, GridCacheQueryManager<Object, 
Object> qryMgr) throws IgniteCheckedException {
+         return qryMgr.size(cls) != -1;
+     }
+ 
+     /**
+      *
+      */
+     private static class ArrayObject implements Serializable {
+         /** */
+         @QuerySqlField
+         private Long[] arr;
+ 
+         /**
+          * @param arr Array.
+          */
+         private ArrayObject(Long[] arr) {
+             this.arr = arr;
+         }
+     }
+ 
+     /**
+      *
+      */
+     public static class Person implements Externalizable {
+         /** */
+         @GridToStringExclude
+         @QuerySqlField
+         private UUID id = UUID.randomUUID();
+ 
+         /** */
+         @QuerySqlField
+         @QueryTextField
+         private String name;
+ 
+         /** */
+         @QuerySqlField
+         private int salary;
+ 
+         /** */
+         @QuerySqlField(index = true)
+         private int fake$Field;
+ 
+         /**
+          * Required by {@link Externalizable}.
+          */
+         public Person() {
+             // No-op.
+         }
+ 
+         /**
+          * @param name Name.
+          * @param salary Salary.
+          */
+         public Person(String name, int salary) {
+             assert name != null;
+             assert salary > 0;
+ 
+             this.name = name;
+             this.salary = salary;
+         }
+ 
+         /**
+          * @return Id.
+          */
+         public UUID id() {
+             return id;
+         }
+ 
+         /**
+          * @return Name.
+          */
+         public String name() {
+             return name;
+         }
+ 
+         /**
+          * @return Salary.
+          */
+         public double salary() {
+             return salary;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public void writeExternal(ObjectOutput out) throws 
IOException {
+             U.writeUuid(out, id);
+             U.writeString(out, name);
+             out.writeInt(salary);
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public void readExternal(ObjectInput in) throws 
IOException, ClassNotFoundException {
+             id = U.readUuid(in);
+             name = U.readString(in);
+             salary = in.readInt();
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public int hashCode() {
+             return id.hashCode() + 31 * name.hashCode() + 31 * 31 * salary;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public boolean equals(Object obj) {
+             if (obj == this)
+                 return true;
+ 
+             if (!(obj instanceof Person))
+                 return false;
+ 
+             Person that = (Person)obj;
+ 
+             return that.id.equals(id) && that.name.equals(name) && 
that.salary == salary;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public String toString() {
+             return S.toString(Person.class, this);
+         }
+     }
+ 
+     /**
+      * Test value object.
+      */
+     @SuppressWarnings("PublicInnerClass")
+     public static class ObjectValue implements Serializable {
+         /** String value. */
+         @QueryTextField
+         private String strVal;
+ 
+         /** Integer value. */
+         @QuerySqlField
+         private int intVal;
+ 
+         /**
+          * Constructor.
+          *
+          * @param strVal String value.
+          * @param intVal Integer value.
+          */
+         ObjectValue(String strVal, int intVal) {
+             this.strVal = strVal;
+             this.intVal = intVal;
+         }
+ 
+         /**
+          * Gets value.
+          *
+          * @return Value.
+          */
+         public String getStringValue() {
+             return strVal;
+         }
+ 
+         /**
+          * @return Integer value.
+          */
+         public int intValue() {
+             return intVal;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public boolean equals(Object o) {
+             if (this == o)
+                 return true;
+ 
+             if (o == null || getClass() != o.getClass())
+                 return false;
+ 
+             ObjectValue other = (ObjectValue)o;
+ 
+             return strVal == null ? other.strVal == null : 
strVal.equals(other.strVal);
+ 
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public int hashCode() {
+             return strVal != null ? strVal.hashCode() : 0;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public String toString() {
+             return S.toString(ObjectValue.class, this);
+         }
+     }
+ 
+     /**
+      * Another test value object.
+      */
+     private static class ObjectValueOther {
+         /** Value. */
+         @QueryTextField
+         private String val;
+ 
+         /**
+          * @param val String value.
+          */
+         ObjectValueOther(String val) {
+             this.val = val;
+         }
+ 
+         /**
+          * Gets value.
+          *
+          * @return Value.
+          */
+         public String value() {
+             return val;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public boolean equals(Object o) {
+             if (this == o)
+                 return true;
+ 
+             if (o == null || getClass() != o.getClass())
+                 return false;
+ 
+             ObjectValueOther other = (ObjectValueOther)o;
+ 
+             return val == null ? other.val == null : val.equals(other.val);
+ 
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public int hashCode() {
+             return val != null ? val.hashCode() : 0;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public String toString() {
+             return S.toString(ObjectValueOther.class, this);
+         }
+     }
+ 
+     /**
+      * Empty test object.
+      */
+     @SuppressWarnings("UnusedDeclaration")
+     private static class EmptyObject {
+         /** */
+         private int val;
+ 
+         /**
+          * @param val Value.
+          */
+         private EmptyObject(int val) {
+             this.val = val;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public int hashCode() {
+             return val;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public boolean equals(Object o) {
+             if (this == o)
+                 return true;
+ 
+             if (!(o instanceof EmptyObject))
+                 return false;
+ 
+             EmptyObject that = (EmptyObject)o;
+ 
+             return val == that.val;
+         }
+     }
+ 
+     /**
+      *
+      */
+     private static class BadHashKeyObject implements Serializable {
+         /** */
+         @QuerySqlField(index = false)
+         private final String str;
+ 
+         /**
+          * @param str String.
+          */
+         private BadHashKeyObject(String str) {
+             this.str = str;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public boolean equals(Object o) {
+             if (this == o) return true;
+             if (o == null || getClass() != o.getClass()) return false;
+ 
+             BadHashKeyObject keyObj = (BadHashKeyObject) o;
+ 
+             return str.equals(keyObj.str);
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public int hashCode() {
+             return 10;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public String toString() {
+             return S.toString(BadHashKeyObject.class, this);
+         }
+     }
+ 
+     /**
+      * Test store.
+      */
+     private static class TestStore extends CacheStoreAdapter<Object, Object> {
+         /** */
+         private Map<Object, Object> map = new ConcurrentHashMap<>();
+ 
+         /** */
+         void reset() {
+             map.clear();
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public Object load(Object key) {
+             return map.get(key);
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public void write(javax.cache.Cache.Entry<? extends Object, 
? extends Object> e) {
+             map.put(e.getKey(), e.getValue());
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public void delete(Object key) {
+             map.remove(key);
+         }
+     }
+ 
+     /**
+      * Functions for test.
+      */
+     @SuppressWarnings("PublicInnerClass")
+     public static class SqlFunctions {
+         /**
+          * @param x Argument.
+          * @return Square of given value.
+          */
+         @QuerySqlFunction
+         public static int square(int x) {
+             return x * x;
+         }
+ 
+         /**
+          * @param x Argument.
+          * @return Cube of given value.
+          */
+         @QuerySqlFunction(alias = "_cube_")
+         public static int cube(int x) {
+             return x * x * x;
+         }
+ 
+         /**
+          * Method which should not be registered.
+          * @return Nothing.
+          */
+         public static int no() {
+             throw new IllegalStateException();
+         }
+     }
++
++    /**
++     *
++     */
++    private static class StoreFactory implements Factory<CacheStore> {
++        @Override public CacheStore create() {
++            return store;
++        }
++    }
+ }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c82d4d8e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePartitionedQueryMultiThreadedSelfTest.java
----------------------------------------------------------------------
diff --cc 
modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePartitionedQueryMultiThreadedSelfTest.java
index 0000000,a90281f..3f8bc51
mode 000000,100644..100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePartitionedQueryMultiThreadedSelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePartitionedQueryMultiThreadedSelfTest.java
@@@ -1,0 -1,309 +1,307 @@@
+ /*
+  * 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 org.apache.ignite.*;
+ import org.apache.ignite.cache.*;
+ import org.apache.ignite.cache.query.*;
+ import org.apache.ignite.cache.query.annotations.*;
+ import org.apache.ignite.configuration.*;
+ import org.apache.ignite.internal.*;
+ import org.apache.ignite.internal.util.tostring.*;
+ import org.apache.ignite.internal.util.typedef.*;
+ import org.apache.ignite.internal.util.typedef.internal.*;
+ import org.apache.ignite.spi.discovery.tcp.*;
+ import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+ import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+ import org.apache.ignite.testframework.*;
+ import org.apache.ignite.testframework.junits.common.*;
+ 
+ import javax.cache.*;
+ import java.io.*;
+ import java.util.*;
+ import java.util.concurrent.atomic.*;
+ 
+ import static org.apache.ignite.cache.CacheAtomicityMode.*;
 -import static org.apache.ignite.cache.CacheDistributionMode.*;
+ import static org.apache.ignite.cache.CacheMode.*;
+ 
+ /**
+  * Tests for partitioned cache queries.
+  */
+ public class IgniteCachePartitionedQueryMultiThreadedSelfTest extends 
GridCommonAbstractTest {
+     /** */
+     private static final boolean TEST_INFO = true;
+ 
+     /** Number of test grids (nodes). Should not be less than 2. */
+     private static final int GRID_CNT = 3;
+ 
+     /** */
+     private static TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
+ 
+     /** Don't start grid by default. */
+     public IgniteCachePartitionedQueryMultiThreadedSelfTest() {
+         super(false);
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected IgniteConfiguration getConfiguration(String gridName) 
throws Exception {
+         IgniteConfiguration c = super.getConfiguration(gridName);
+ 
+         TcpDiscoverySpi disco = new TcpDiscoverySpi();
+ 
+         disco.setIpFinder(ipFinder);
+ 
+         c.setDiscoverySpi(disco);
+ 
+         CacheConfiguration cc = defaultCacheConfiguration();
+ 
+         cc.setCacheMode(PARTITIONED);
+ 
+         // Query should be executed without ongoing transactions.
+         
cc.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+         cc.setBackups(0);
+         cc.setRebalanceMode(CacheRebalanceMode.SYNC);
+         cc.setAtomicityMode(TRANSACTIONAL);
 -        cc.setDistributionMode(NEAR_PARTITIONED);
+         cc.setIndexedTypes(
+             UUID.class, Person.class
+         );
+ 
+         c.setCacheConfiguration(cc);
+ 
+         return c;
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void beforeTestsStarted() throws Exception {
+         assert GRID_CNT >= 2 : "Constant GRID_CNT must be greater than or 
equal to 2.";
+ 
+         startGridsMultiThreaded(GRID_CNT);
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void afterTestsStopped() throws Exception {
+         stopAllGrids();
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void afterTest() throws Exception {
+         super.afterTest();
+ 
+         // Clean up all caches.
+         for (int i = 0; i < GRID_CNT; i++)
+             grid(i).jcache(null).removeAll();
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void info(String msg) {
+         if (TEST_INFO)
+             super.info(msg);
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testLuceneAndSqlMultithreaded() throws Exception {
+         // ---------- Test parameters ---------- //
+         int luceneThreads = 10;
+         int sqlThreads = 10;
+         long duration = 10 * 1000;
+         final int logMod = 100;
+ 
+         final Person p1 = new Person("Jon", 1500, "Master");
+         final Person p2 = new Person("Jane", 2000, "Master");
+         final Person p3 = new Person("Mike", 1800, "Bachelor");
+         final Person p4 = new Person("Bob", 1900, "Bachelor");
+ 
+         final IgniteCache<UUID, Person> cache0 = grid(0).jcache(null);
+ 
+         cache0.put(p1.id(), p1);
+         cache0.put(p2.id(), p2);
+         cache0.put(p3.id(), p3);
+         cache0.put(p4.id(), p4);
+ 
+         assertEquals(4, cache0.localSize());
+ 
+         assert grid(0).cluster().nodes().size() == GRID_CNT;
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         final AtomicLong luceneCnt = new AtomicLong();
+ 
+         // Start lucene query threads.
+         IgniteInternalFuture<?> futLucene = 
GridTestUtils.runMultiThreadedAsync(new CAX() {
+             @Override public void applyx() throws IgniteCheckedException {
+                 while (!done.get()) {
+                     QueryCursor<Cache.Entry<UUID, Person>> master =
+                         cache0.query(new TextQuery(Person.class, "Master"));
+ 
+                     Collection<Cache.Entry<UUID, Person>> entries = 
master.getAll();
+ 
+                     checkResult(entries, p1, p2);
+ 
+                     long cnt = luceneCnt.incrementAndGet();
+ 
+                     if (cnt % logMod == 0)
+                         info("Executed LUCENE queries: " + cnt);
+                 }
+             }
+         }, luceneThreads, "LUCENE-THREAD");
+ 
+         final AtomicLong sqlCnt = new AtomicLong();
+ 
+         // Start sql query threads.
+         IgniteInternalFuture<?> futSql = 
GridTestUtils.runMultiThreadedAsync(new CAX() {
+             @Override public void applyx() throws IgniteCheckedException {
+                 while (!done.get()) {
+                     QueryCursor<Cache.Entry<UUID, Person>> bachelors =
+                             cache0.query(new SqlQuery(Person.class, "degree = 
'Bachelor'"));
+ 
+                     Collection<Cache.Entry<UUID, Person>> entries = 
bachelors.getAll();
+ 
+                     checkResult(entries, p3, p4);
+ 
+                     long cnt = sqlCnt.incrementAndGet();
+ 
+                     if (cnt % logMod == 0)
+                         info("Executed SQL queries: " + cnt);
+                 }
+             }
+         }, sqlThreads, "SQL-THREAD");
+ 
+         Thread.sleep(duration);
+ 
+         done.set(true);
+ 
+         futLucene.get();
+         futSql.get();
+     }
+ 
+     /**
+      * @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());
+         }
+     }
+ 
+     /** Test class. */
+     private static class Person implements Externalizable {
+         /** */
+         @GridToStringExclude
+         private UUID id = UUID.randomUUID();
+ 
+         /** */
+         @QuerySqlField
+         private String name;
+ 
+         /** */
+         @QuerySqlField
+         private int salary;
+ 
+         /** */
+         @QuerySqlField
+         @QueryTextField
+         private String degree;
+ 
+         /** Required by {@link Externalizable}. */
+         public Person() {
+             // No-op.
+         }
+ 
+         /**
+          * @param name Name.
+          * @param salary Salary.
+          * @param degree Degree.
+          */
+         Person(String name, int salary, String degree) {
+             assert name != null;
+             assert salary > 0;
+             assert degree != null;
+ 
+             this.name = name;
+             this.salary = salary;
+             this.degree = degree;
+         }
+ 
+         /** @return Id. */
+         UUID id() {
+             return id;
+         }
+ 
+         /** @return Name. */
+         String name() {
+             return name;
+         }
+ 
+         /** @return Salary. */
+         double salary() {
+             return salary;
+         }
+ 
+         /** @return Degree. */
+         String degree() {
+             return degree;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public void writeExternal(ObjectOutput out) throws 
IOException {
+             U.writeUuid(out, id);
+             U.writeString(out, name);
+             out.writeInt(salary);
+             U.writeString(out, degree);
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public void readExternal(ObjectInput in) throws 
IOException, ClassNotFoundException {
+             id = U.readUuid(in);
+             name = U.readString(in);
+             salary = in.readInt();
+             degree = U.readString(in);
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public int hashCode() {
+             return id.hashCode() + 31 * name.hashCode() + 31 * 31 * salary;
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public boolean equals(Object obj) {
+             if (obj == this)
+                 return true;
+ 
+             if (!(obj instanceof Person))
+                 return false;
+ 
+             Person that = (Person)obj;
+ 
+             return that.id.equals(id) && that.name.equals(name) && 
that.salary == salary && that.degree.equals(degree);
+         }
+ 
+         /** {@inheritDoc} */
+         @Override public String toString() {
+             return S.toString(Person.class, this);
+         }
+     }
+ }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c82d4d8e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
----------------------------------------------------------------------
diff --cc 
modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
index 0000000,2e54404..46fe6f6
mode 000000,100644..100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
@@@ -1,0 -1,747 +1,746 @@@
+ /*
+  * 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 org.apache.ignite.*;
+ import org.apache.ignite.cache.*;
+ import org.apache.ignite.cache.eviction.lru.*;
+ import org.apache.ignite.cache.query.*;
+ import org.apache.ignite.cache.query.annotations.*;
+ import org.apache.ignite.configuration.*;
+ import org.apache.ignite.internal.*;
+ import org.apache.ignite.internal.processors.cache.query.*;
+ import org.apache.ignite.internal.processors.query.*;
+ import org.apache.ignite.internal.processors.query.h2.*;
+ import org.apache.ignite.internal.util.typedef.*;
+ import org.apache.ignite.marshaller.optimized.*;
+ import org.apache.ignite.spi.discovery.tcp.*;
+ import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+ import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+ import org.apache.ignite.spi.swapspace.file.*;
+ import org.apache.ignite.testframework.junits.common.*;
+ import org.jetbrains.annotations.*;
+ 
+ import javax.cache.*;
+ import java.io.*;
+ import java.util.*;
+ import java.util.concurrent.atomic.*;
+ 
+ import static org.apache.ignite.cache.CacheAtomicityMode.*;
+ import static org.apache.ignite.cache.CacheMode.*;
+ 
+ /**
+  * Multi-threaded tests for cache queries.
+  */
+ @SuppressWarnings("StatementWithEmptyBody")
+ public class IgniteCacheQueryMultiThreadedSelfTest extends 
GridCommonAbstractTest {
+     /** */
+     private static final boolean TEST_INFO = true;
+ 
+     /** Number of test grids (nodes). Should not be less than 2. */
+     private static final int GRID_CNT = 2;
+ 
+     /** */
+     private static TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
+ 
+     /** */
+     private static AtomicInteger idxSwapCnt = new AtomicInteger();
+ 
+     /** */
+     private static AtomicInteger idxUnswapCnt = new AtomicInteger();
+ 
+     /** */
+     private static final long DURATION = 30 * 1000;
+ 
+     /** Don't start grid by default. */
+     public IgniteCacheQueryMultiThreadedSelfTest() {
+         super(false);
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected IgniteConfiguration getConfiguration(String gridName) 
throws Exception {
+         IgniteConfiguration cfg = super.getConfiguration(gridName);
+ 
+         TcpDiscoverySpi disco = new TcpDiscoverySpi();
+ 
+         disco.setIpFinder(ipFinder);
+ 
+         cfg.setDiscoverySpi(disco);
+ 
+         cfg.setSwapSpaceSpi(new FileSwapSpaceSpi());
+         cfg.setMarshaller(new OptimizedMarshaller(false));
+ 
+         CacheConfiguration<?,?> cacheCfg = defaultCacheConfiguration();
+ 
+         cacheCfg.setCacheMode(PARTITIONED);
+         cacheCfg.setAtomicityMode(TRANSACTIONAL);
 -        cacheCfg.setDistributionMode(CacheDistributionMode.NEAR_PARTITIONED);
+         
cacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+         cacheCfg.setSwapEnabled(true);
+         cacheCfg.setBackups(1);
+         cacheCfg.setEvictionPolicy(evictsEnabled() ? new 
CacheLruEvictionPolicy(100) : null);
+         cacheCfg.setSqlOnheapRowCacheSize(128);
+         cacheCfg.setIndexedTypes(
+             Integer.class, Integer.class,
+             Integer.class, TestValue.class,
+             Integer.class, String.class,
+             Integer.class, Long.class,
+             Integer.class, Object.class
+         );
+ 
+         if (offheapEnabled())
+             cacheCfg.setOffHeapMaxMemory(evictsEnabled() ? 1000 : 0); // 
Small offheap for evictions.
+ 
+         cfg.setCacheConfiguration(cacheCfg);
+ 
+         GridQueryProcessor.idxCls = FakeIndexing.class;
+ 
+         return cfg;
+     }
+ 
+     /**
+      *
+      */
+     private static class FakeIndexing extends IgniteH2Indexing {
+         @Override public void onSwap(@Nullable String spaceName, Object key) 
throws IgniteCheckedException {
+             super.onSwap(spaceName, key);
+ 
+             idxSwapCnt.incrementAndGet();
+         }
+ 
+         @Override public void onUnswap(@Nullable String spaceName, Object 
key, Object val, byte[] valBytes)
+         throws IgniteCheckedException {
+             super.onUnswap(spaceName, key, val, valBytes);
+ 
+             idxUnswapCnt.incrementAndGet();
+         }
+     }
+ 
+     /** @return {@code true} If offheap enabled. */
+     protected boolean offheapEnabled() {
+         return false;
+     }
+ 
+     /** @return {@code true} If evictions enabled. */
+     protected boolean evictsEnabled() {
+         return false;
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void beforeTest() throws Exception {
+         super.beforeTest();
+ 
+         // Clean up all caches.
+         for (int i = 0; i < GRID_CNT; i++) {
+             GridCache<Object, Object> c = ((IgniteKernal)grid(i)).cache(null);
+ 
+             assertEquals(0, c.size());
+         }
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void beforeTestsStarted() throws Exception {
+         assert GRID_CNT >= 2 : "Constant GRID_CNT must be greater than or 
equal to 2.";
+ 
+         startGridsMultiThreaded(GRID_CNT);
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void afterTestsStopped() throws Exception {
+         stopAllGrids();
+ 
+         if (evictsEnabled()) {
+             assertTrue(idxSwapCnt.get() > 0);
+             assertTrue(idxUnswapCnt.get() > 0);
+         }
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void afterTest() throws Exception {
+         super.afterTest();
+ 
+         // Clean up all caches.
+         for (int i = 0; i < GRID_CNT; i++) {
+             GridCache<Object, Object> c = ((IgniteKernal)grid(i)).cache(null);
+ 
+             c.removeAll();
+ 
+             // Fix for tests where mapping was removed at primary node
+             // but was not removed at others.
+             // removeAll() removes mapping only when it presents at a primary 
node.
+             // To remove all mappings used force remove by key.
+             if (c.size() > 0) {
+                 for (Object k : c.keySet()) {
+                     c.remove(k);
+                 }
+             }
+ 
+             Iterator<Map.Entry<Object, Object>> it = c.swapIterator();
+ 
+             while (it.hasNext()) {
+                 it.next();
+ 
+                 it.remove();
+             }
+ 
+             it = c.offHeapIterator();
+ 
+             while (it.hasNext()) {
+                 it.next();
+ 
+                 it.remove();
+             }
+ 
+             assertEquals("Swap keys: " + c.swapKeys(), 0, c.swapKeys());
+             assertEquals(0, c.offHeapEntriesCount());
+             assertEquals(0, c.size());
+         }
+     }
+ 
+     /** {@inheritDoc} */
+     @Override protected void info(String msg) {
+         if (TEST_INFO)
+             super.info(msg);
+     }
+ 
+     /**
+      * @param entries Entries.
+      * @param g Grid.
+      * @return Affinity nodes.
+      */
+     private Set<UUID> affinityNodes(Iterable<Cache.Entry<Integer, Integer>> 
entries, Ignite g) {
+         Set<UUID> nodes = new HashSet<>();
+ 
+         for (Cache.Entry<Integer, Integer> entry : entries)
+             
nodes.add(((IgniteKernal)g).cache(null).affinity().mapKeyToPrimaryAndBackups(entry.getKey()).iterator().next().id());
+ 
+         return nodes;
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testMultiThreadedSwapUnswapString() throws Exception {
+         int threadCnt = 150;
+         final int keyCnt = 2000;
+         final int valCnt = 10000;
+ 
+         final Ignite g = grid(0);
+ 
+         // Put test values into cache.
+         final IgniteCache<Integer, String> c = g.jcache(null);
+         final IgniteCache<Integer, Long> cl = g.jcache(null);
+ 
+         assertEquals(0, ((IgniteKernal)g).cache(null).size());
+         assertEquals(0, c.query(new SqlQuery(String.class, "1 = 
1")).getAll().size());
+         assertEquals(0, cl.query(new SqlQuery(Long.class, "1 = 
1")).getAll().size());
+ 
+         Random rnd = new Random();
+ 
+         for (int i = 0; i < keyCnt; i += 1 + rnd.nextInt(3)) {
+             c.put(i, String.valueOf(rnd.nextInt(valCnt)));
+ 
+             if (evictsEnabled() && rnd.nextBoolean())
+                 c.localEvict(Arrays.asList(i));
+         }
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         IgniteInternalFuture<?> fut = multithreadedAsync(new CAX() {
+             @Override public void applyx() throws IgniteCheckedException {
+                 Random rnd = new Random();
+ 
+                 while (!done.get()) {
+                     switch (rnd.nextInt(5)) {
+                         case 0:
+                             c.put(rnd.nextInt(keyCnt), 
String.valueOf(rnd.nextInt(valCnt)));
+ 
+                             break;
+                         case 1:
+                             if (evictsEnabled())
+                                 
c.localEvict(Arrays.asList(rnd.nextInt(keyCnt)));
+ 
+                             break;
+                         case 2:
+                             c.remove(rnd.nextInt(keyCnt));
+ 
+                             break;
+                         case 3:
+                             c.get(rnd.nextInt(keyCnt));
+ 
+                             break;
+                         case 4:
+                             int from = rnd.nextInt(valCnt);
+ 
+                             QueryCursor<Cache.Entry<Integer, String>> qry = 
c.query(
+                                 new SqlQuery(String.class, "_val between ? 
and ?").setArgs(
+                                     String.valueOf(from), String.valueOf(from 
+ 250)));
+ 
+                             Collection<Cache.Entry<Integer, String>> res = 
qry.getAll();
+ 
+                             for (Cache.Entry<Integer, String> ignored : res) {
+                                 //No-op.
+                             }
+                     }
+                 }
+             }
+         }, threadCnt);
+ 
+         Thread.sleep(DURATION);
+ 
+         done.set(true);
+ 
+         fut.get();
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testMultiThreadedSwapUnswapLong() throws Exception {
+         int threadCnt = 150;
+         final int keyCnt = 2000;
+         final int valCnt = 10000;
+ 
+         final Ignite g = grid(0);
+ 
+         // Put test values into cache.
+         final IgniteCache<Integer, Long> c = g.jcache(null);
+         final IgniteCache<Integer, String> c1 = g.jcache(null);
+ 
+         assertEquals(0, ((IgniteKernal)g).cache(null).size());
+         assertEquals(0, c1.query(new SqlQuery(String.class, "1 = 
1")).getAll().size());
+         assertEquals(0, c.query(new SqlQuery(Long.class, "1 = 
1")).getAll().size());
+ 
+         Random rnd = new Random();
+ 
+         for (int i = 0; i < keyCnt; i += 1 + rnd.nextInt(3)) {
+             c.put(i, (long)rnd.nextInt(valCnt));
+ 
+             if (evictsEnabled() && rnd.nextBoolean())
+                 c.localEvict(Arrays.asList(i));
+         }
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         IgniteInternalFuture<?> fut = multithreadedAsync(new CAX() {
+             @Override public void applyx() throws IgniteCheckedException {
+                 Random rnd = new Random();
+ 
+                 while (!done.get()) {
+                     int key = rnd.nextInt(keyCnt);
+ 
+                     switch (rnd.nextInt(5)) {
+                         case 0:
+                             c.put(key, (long)rnd.nextInt(valCnt));
+ 
+                             break;
+                         case 1:
+                             if (evictsEnabled())
+                                 c.localEvict(Arrays.asList(key));
+ 
+                             break;
+                         case 2:
+                             c.remove(key);
+ 
+                             break;
+                         case 3:
+                             c.get(key);
+ 
+                             break;
+                         case 4:
+                             int from = rnd.nextInt(valCnt);
+ 
+                             Collection<Cache.Entry<Integer, Long>> res = 
c.query(new SqlQuery(Long.class,
+                                 "_val between ? and ?").setArgs(from, from + 
250)).getAll();
+ 
+                             for (Cache.Entry<Integer, Long> ignored : res) {
+                                 //No-op.
+                             }
+                     }
+                 }
+             }
+         }, threadCnt);
+ 
+         Thread.sleep(DURATION);
+ 
+         done.set(true);
+ 
+         fut.get();
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testMultiThreadedSwapUnswapLongString() throws Exception {
+         int threadCnt = 150;
+         final int keyCnt = 2000;
+         final int valCnt = 10000;
+ 
+         final Ignite g = grid(0);
+ 
+         // Put test values into cache.
+         final IgniteCache<Integer, Object> c = g.jcache(null);
+ 
+         assertEquals(0, g.jcache(null).size());
+         assertEquals(0, c.query(new SqlQuery(Object.class, "1 = 
1")).getAll().size());
+ 
+         Random rnd = new Random();
+ 
+         for (int i = 0; i < keyCnt; i += 1 + rnd.nextInt(3)) {
+             c.put(i, rnd.nextBoolean() ? (long)rnd.nextInt(valCnt) : 
String.valueOf(rnd.nextInt(valCnt)));
+ 
+             if (evictsEnabled() && rnd.nextBoolean())
+                 c.localEvict(Arrays.asList(i));
+         }
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         IgniteInternalFuture<?> fut = multithreadedAsync(new CAX() {
+             @Override public void applyx() throws IgniteCheckedException {
+                 Random rnd = new Random();
+ 
+                 while (!done.get()) {
+                     int key = rnd.nextInt(keyCnt);
+ 
+                     switch (rnd.nextInt(5)) {
+                         case 0:
+                             c.put(key, rnd.nextBoolean() ? 
(long)rnd.nextInt(valCnt) :
+                                 String.valueOf(rnd.nextInt(valCnt)));
+ 
+                             break;
+                         case 1:
+                             if (evictsEnabled())
+                                 c.localEvict(Arrays.asList(key));
+ 
+                             break;
+                         case 2:
+                             c.remove(key);
+ 
+                             break;
+                         case 3:
+                             c.get(key);
+ 
+                             break;
+                         case 4:
+                             int from = rnd.nextInt(valCnt);
+ 
+                             Collection<Cache.Entry<Integer, Object>> res = 
c.query(
+                                 new SqlQuery(Object.class, "_val between ? 
and ?").setArgs(from, from + 250))
+                                 .getAll();
+ 
+                             for (Cache.Entry<Integer, Object> ignored : res) {
+                                 //No-op.
+                             }
+                     }
+                 }
+             }
+         }, threadCnt);
+ 
+         Thread.sleep(DURATION);
+ 
+         done.set(true);
+ 
+         fut.get();
+     }
+ 
+     /**
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testMultiThreadedSwapUnswapObject() throws Exception {
+         int threadCnt = 50;
+         final int keyCnt = 4000;
+         final int valCnt = 10000;
+ 
+         final Ignite g = grid(0);
+ 
+         // Put test values into cache.
+         final IgniteCache<Integer, TestValue> c = g.jcache(null);
+ 
+         assertEquals(0, ((IgniteKernal)g).cache(null).size());
+         assertEquals(0, c.query(new SqlQuery(TestValue.class, "1 = 
1")).getAll().size());
+ 
+         Random rnd = new Random();
+ 
+         for (int i = 0; i < keyCnt; i += 1 + rnd.nextInt(3)) {
+             c.put(i, new TestValue(rnd.nextInt(valCnt)));
+ 
+             if (evictsEnabled() && rnd.nextBoolean())
+                 c.localEvict(Arrays.asList(i));
+         }
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         IgniteInternalFuture<?> fut = multithreadedAsync(new CAX() {
+             @Override public void applyx() throws IgniteCheckedException {
+                 Random rnd = new Random();
+ 
+                 while (!done.get()) {
+                     int key = rnd.nextInt(keyCnt);
+ 
+                     switch (rnd.nextInt(5)) {
+                         case 0:
+                             c.put(key, new TestValue(rnd.nextInt(valCnt)));
+ 
+                             break;
+                         case 1:
+                             if (evictsEnabled())
+                                 c.localEvict(Arrays.asList(key));
+ 
+                             break;
+                         case 2:
+                             c.remove(key);
+ 
+                             break;
+                         case 3:
+                             c.get(key);
+ 
+                             break;
+                         case 4:
+                             int from = rnd.nextInt(valCnt);
+ 
+                             Collection<Cache.Entry<Integer, TestValue>> res =
+                                 c.query(new SqlQuery(TestValue.class, 
"TestValue.val between ? and ?").setArgs(
+                                     from, from + 250)).getAll();
+ 
+                             for (Cache.Entry<Integer, TestValue> ignored : 
res) {
+                                 //No-op.
+                             }
+                     }
+                 }
+             }
+         }, threadCnt);
+ 
+         Thread.sleep(DURATION);
+ 
+         done.set(true);
+ 
+         fut.get();
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testMultiThreadedSameQuery() throws Exception {
+         int threadCnt = 50;
+         final int keyCnt = 10;
+         final int logMod = 5000;
+ 
+         final Ignite g = grid(0);
+ 
+         // Put test values into cache.
+         final IgniteCache<Integer, Integer> c = g.jcache(null);
+ 
+         for (int i = 0; i < keyCnt; i++) {
+             c.put(i, i);
+ 
+             c.localEvict(Arrays.asList(i));
+         }
+ 
+         final AtomicInteger cnt = new AtomicInteger();
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         IgniteInternalFuture<?> fut = multithreadedAsync(
+             new CAX() {
+                 @Override public void applyx() throws IgniteCheckedException {
+                     int iter = 0;
+ 
+                     while (!done.get() && 
!Thread.currentThread().isInterrupted()) {
+                         iter++;
+ 
+                         Collection<Cache.Entry<Integer, Integer>> entries =
+                             c.query(new SqlQuery(Integer.class, "_val >= 
0")).getAll();
+ 
+                         assert entries != null;
+ 
+                         assertEquals("Query results [entries=" + entries + ", 
aff=" + affinityNodes(entries, g) +
+                             ", iteration=" + iter + ']', keyCnt, 
entries.size());
+ 
+                         if (cnt.incrementAndGet() % logMod == 0) {
+                             GridCacheQueryManager<Object, Object> qryMgr =
+                                 
((IgniteKernal)g).internalCache().context().queries();
+ 
+                             assert qryMgr != null;
+ 
+                             qryMgr.printMemoryStats();
+                         }
+                     }
+                 }
+             }, threadCnt);
+ 
+         Thread.sleep(DURATION);
+ 
+         info("Finishing test...");
+ 
+         done.set(true);
+ 
+         fut.get();
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testMultiThreadedNewQueries() throws Exception {
+         int threadCnt = 50;
+         final int keyCnt = 10;
+         final int logMod = 5000;
+ 
+         final Ignite g = grid(0);
+ 
+         // Put test values into cache.
+         final IgniteCache<Integer, Integer> c = g.jcache(null);
+ 
+         for (int i = 0; i < keyCnt; i++) {
+             c.put(i, i);
+ 
+             c.localEvict(Arrays.asList(i));
+         }
+ 
+         final AtomicInteger cnt = new AtomicInteger();
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         IgniteInternalFuture<?> fut = multithreadedAsync(new CAX() {
+             @Override public void applyx() throws IgniteCheckedException {
+                 int iter = 0;
+ 
+                 while (!done.get() && 
!Thread.currentThread().isInterrupted()) {
+                     iter++;
+ 
+                     Collection<Cache.Entry<Integer, Integer>> entries =
+                         c.query(new SqlQuery(Integer.class, "_val >= 
0")).getAll();
+ 
+                     assert entries != null;
+ 
+                     assertEquals("Entries count is not as expected on 
iteration: " + iter, keyCnt, entries.size());
+ 
+                     if (cnt.incrementAndGet() % logMod == 0) {
+                         GridCacheQueryManager<Object, Object> qryMgr =
+                             
((IgniteKernal)g).internalCache().context().queries();
+ 
+                         assert qryMgr != null;
+ 
+                         qryMgr.printMemoryStats();
+                     }
+                 }
+             }
+         }, threadCnt);
+ 
+         Thread.sleep(DURATION);
+ 
+         done.set(true);
+ 
+         fut.get();
+     }
+ 
+     /**
+      * JUnit.
+      *
+      * @throws Exception If failed.
+      */
+     @SuppressWarnings({"TooBroadScope"})
+     public void testMultiThreadedScanQuery() throws Exception {
+         int threadCnt = 50;
+         final int keyCnt = 500;
+         final int logMod = 5000;
+ 
+         final Ignite g = grid(0);
+ 
+         // Put test values into cache.
+         final IgniteCache<Integer, Integer> c = g.jcache(null);
+ 
+         for (int i = 0; i < keyCnt; i++)
+             c.put(i, i);
+ 
+         final AtomicInteger cnt = new AtomicInteger();
+ 
+         final AtomicBoolean done = new AtomicBoolean();
+ 
+         IgniteInternalFuture<?> fut = multithreadedAsync(
+             new CAX() {
+                 @Override public void applyx() throws IgniteCheckedException {
+                     int iter = 0;
+ 
+                     while (!done.get() && 
!Thread.currentThread().isInterrupted()) {
+                         iter++;
+ 
+                         // Scan query.
+                         Collection<Cache.Entry<Integer, Integer>> entries =
+                             c.query(new ScanQuery<Integer, 
Integer>()).getAll();
+ 
+                         assert entries != null;
+ 
+                         assertEquals("Entries count is not as expected on 
iteration: " + iter, keyCnt, entries.size());
+ 
+                         if (cnt.incrementAndGet() % logMod == 0) {
+                             GridCacheQueryManager<Object, Object> qryMgr =
+                                 
((IgniteKernal)g).internalCache().context().queries();
+ 
+                             assert qryMgr != null;
+ 
+                             qryMgr.printMemoryStats();
+                         }
+                     }
+                 }
+             }, threadCnt);
+ 
+         Thread.sleep(DURATION);
+ 
+         done.set(true);
+ 
+         fut.get();
+     }
+ 
+     /**
+      * Test value.
+      */
+     private static class TestValue implements Serializable {
+         /** Value. */
+         @QuerySqlField
+         private int val;
+ 
+         /**
+          * @param val Value.
+          */
+         private TestValue(int val) {
+             this.val = val;
+         }
+ 
+         /**
+          * @return Value.
+          */
+         public int value() {
+             return val;
+         }
+     }
+ }

Reply via email to