/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.internal.processors.cache; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.cache.query.annotations.QueryTextField; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.cache.CacheMode.LOCAL; import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC; /** * */ public class GridCacheLuceneQueryIndexTest extends GridCommonAbstractTest { /** */ private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true); /** * */ public GridCacheLuceneQueryIndexTest() { super(false); } /** {@inheritDoc} */ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); TcpDiscoverySpi disco = new TcpDiscoverySpi(); disco.setIpFinder(ipFinder); cfg.setDiscoverySpi(disco); cfg.setIncludeEventTypes(); cfg.setConnectorConfiguration(null); CacheConfiguration cacheCfg1 = defaultCacheConfiguration(); cacheCfg1.setName("local1"); cacheCfg1.setCacheMode(LOCAL); cacheCfg1.setWriteSynchronizationMode(FULL_SYNC); CacheConfiguration cacheCfg2 = defaultCacheConfiguration(); cacheCfg2.setName("local2"); cacheCfg2.setCacheMode(LOCAL); cacheCfg2.setWriteSynchronizationMode(FULL_SYNC); cfg.setCacheConfiguration(cacheCfg1, cacheCfg2); return cfg; } /** {@inheritDoc} */ @Override protected void afterTest() throws Exception { super.afterTest(); stopAllGrids(); } /** {@inheritDoc} */ @Override protected long getTestTimeout() { return 10 * 60 * 1000; } /** * Tests puts one by one. * * @throws Exception In case of error. */ public void testLuceneIndex() throws Exception { final Ignite g = startGrid(0); final IgniteCache<Integer, ObjectValue> cache1 = g.cache("local1"); final IgniteCache<Integer, ObjectValue> cache2 = g.cache("local2"); final AtomicInteger threadIdxGen = new AtomicInteger(); final int keyCnt = 10000; final IgniteInternalFuture<?> fut = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { int threadIdx = threadIdxGen.getAndIncrement() % 2; for (int i = 0; i < keyCnt; i++) { if (threadIdx == 0) cache1.put(i, new ObjectValue("test full text more" + i)); else cache2.put(i, new ObjectValue("test full text more" + i)); if (i % 200 == 0) info("Put entries count: " + i); } return null; } }, 10); IgniteInternalFuture<?> fut1 = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { while (!fut.isDone()) { Thread.sleep(10000); // ((GridKernal)g).internalCache("local1").context().queries().index().printH2Stats(); // ((GridKernal)g).internalCache("local2").context().queries().index().printH2Stats(); } return null; } }, 1); fut.get(); fut1.get(); assert cache1.size() == keyCnt; assert cache2.size() == keyCnt; } /** * Tests with putAll. * * @throws Exception In case of error. */ public void testLuceneIndex1() throws Exception { final Ignite g = startGrid(0); final IgniteCache<Integer, ObjectValue> cache1 = g.cache("local1"); final IgniteCache<Integer, ObjectValue> cache2 = g.cache("local2"); final AtomicInteger threadIdxGen = new AtomicInteger(); final int keyCnt = 10000; final IgniteInternalFuture<?> fut = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { int threadIdx = threadIdxGen.getAndIncrement() % 2; Map<Integer, ObjectValue> map = new HashMap<>(); for (int i = 0; i < keyCnt; i++) { if (i % 200 == 0 && !map.isEmpty()) { if (threadIdx == 0) cache1.putAll(map); else cache2.putAll(map); info("Put entries count: " + i); map = new HashMap<>(); } map.put(i, new ObjectValue("String value " + i)); } if (!map.isEmpty()) { if (threadIdx == 0) cache1.putAll(map); else cache2.putAll(map); } return null; } }, 10); IgniteInternalFuture<?> fut1 = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { while (!fut.isDone()) { Thread.sleep(10000); // ((GridKernal)g).internalCache("local1").context().queries().index().printH2Stats(); // ((GridKernal)g).internalCache("local2").context().queries().index().printH2Stats(); } return null; } }, 1); fut.get(); fut1.get(); assert cache1.size() == keyCnt; assert cache2.size() == keyCnt; } /** * Test same value with putAll. * * @throws Exception In case of error. */ public void testLuceneIndex2() throws Exception { final Ignite g = startGrid(0); final IgniteCache<Integer, ObjectValue> cache1 = g.cache("local1"); final IgniteCache<Integer, ObjectValue> cache2 = g.cache("local2"); final AtomicInteger threadIdxGen = new AtomicInteger(); final int keyCnt = 10000; final ObjectValue val = new ObjectValue("String value"); final IgniteInternalFuture<?> fut = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { int threadIdx = threadIdxGen.getAndIncrement() % 2; Map<Integer, ObjectValue> map = new HashMap<>(); for (int i = 0; i < keyCnt; i++) { if (i % 200 == 0 && !map.isEmpty()) { if (threadIdx == 0) cache1.putAll(map); else cache2.putAll(map); info("Put entries count: " + i); map = new HashMap<>(); } map.put(i, val); } if (!map.isEmpty()) { if (threadIdx == 0) cache1.putAll(map); else cache2.putAll(map); } return null; } }, 10); IgniteInternalFuture<?> fut1 = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { while (!fut.isDone()) { Thread.sleep(10000); // ((GridKernal)g).internalCache("local1").context().queries().index().printH2Stats(); // ((GridKernal)g).internalCache("local2").context().queries().index().printH2Stats(); } return null; } }, 1); fut.get(); fut1.get(); assert cache1.size() == keyCnt; assert cache2.size() == keyCnt; } /** * Test limited values set and custom keys with putAll. * * @throws Exception In case of error. */ public void testLuceneIndex3() throws Exception { final Ignite g = startGrid(0); final IgniteCache<ObjectKey, ObjectValue> cache1 = g.cache("local1"); final IgniteCache<ObjectKey, ObjectValue> cache2 = g.cache("local2"); final AtomicInteger threadIdxGen = new AtomicInteger(); final int keyCnt = 10000; final ObjectValue[] vals = new ObjectValue[10]; for (int i = 0; i < vals.length; i++) vals[i] = new ObjectValue("Object value " + i); final IgniteInternalFuture<?> fut = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { int threadIdx = threadIdxGen.getAndIncrement() % 2; Map<ObjectKey, ObjectValue> map = new HashMap<>(); for (int i = 0; i < keyCnt; i++) { if (i % 200 == 0 && !map.isEmpty()) { if (threadIdx == 0) cache1.putAll(map); else cache2.putAll(map); info("Put entries count: " + i); map = new HashMap<>(); } map.put(new ObjectKey(String.valueOf(i)), F.rand(vals)); } if (!map.isEmpty()) { if (threadIdx == 0) cache1.putAll(map); else cache2.putAll(map); } return null; } }, 1); IgniteInternalFuture<?> fut1 = multithreadedAsync( new Callable<Object>() { @Nullable @Override public Object call() throws Exception { while (!fut.isDone()) { Thread.sleep(10000); // ((GridKernal)g).internalCache("local1").context().queries().index().printH2Stats(); // ((GridKernal)g).internalCache("local2").context().queries().index().printH2Stats(); } return null; } }, 1); fut.get(); fut1.get(); assert cache1.size() == keyCnt; assert cache2.size() == keyCnt; } /** * Test value object. */ private static class ObjectValue implements Serializable { /** String value. */ @QueryTextField private String strVal; /** * @param strVal String value. */ ObjectValue(String strVal) { this.strVal = strVal; } /** * @return Value. */ public String stringValue() { return strVal; } /** {@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); } } /** * Test value key. */ private static class ObjectKey implements Serializable { /** String key. */ @QueryTextField private String strKey; /** * @param strKey String key. */ ObjectKey(String strKey) { this.strKey = strKey; } /** * @return Key. */ public String stringKey() { return strKey; } /** {@inheritDoc} */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ObjectKey other = (ObjectKey)o; return strKey == null ? other.strKey == null : strKey.equals(other.strKey); } /** {@inheritDoc} */ @Override public int hashCode() { return strKey != null ? strKey.hashCode() : 0; } /** {@inheritDoc} */ @Override public String toString() { return S.toString(ObjectKey.class, this); } } }