http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/b5b7203a/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/HashIndexQueryIntegrationTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/HashIndexQueryIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/HashIndexQueryIntegrationTest.java new file mode 100755 index 0000000..8f8c8aa --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/HashIndexQueryIntegrationTest.java @@ -0,0 +1,1567 @@ +/* + * 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.geode.cache.query.internal.index; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.text.ParseException; +import java.util.Collection; +import java.util.Iterator; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.cache.AttributesFactory; +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.EvictionAction; +import org.apache.geode.cache.EvictionAttributes; +import org.apache.geode.cache.PartitionAttributesFactory; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionAttributes; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache.query.CacheUtils; +import org.apache.geode.cache.query.Index; +import org.apache.geode.cache.query.IndexInvalidException; +import org.apache.geode.cache.query.IndexStatistics; +import org.apache.geode.cache.query.QueryService; +import org.apache.geode.cache.query.SelectResults; +import org.apache.geode.cache.query.data.Portfolio; +import org.apache.geode.cache.query.internal.QueryObserverAdapter; +import org.apache.geode.cache.query.internal.QueryObserverHolder; +import org.apache.geode.test.junit.categories.IntegrationTest; +import org.apache.geode.pdx.PdxInstance; + +@Category(IntegrationTest.class) +public class HashIndexQueryIntegrationTest { + + private QueryService qs; + private Region region; + private Region joinRegion; + private MyQueryObserverAdapter observer; + private Index index; + + @Before + public void setUp() throws java.lang.Exception { + CacheUtils.startCache(); + qs = CacheUtils.getQueryService(); + observer = new MyQueryObserverAdapter(); + QueryObserverHolder.setInstance(observer); + } + + private void createJoinTable(int numEntries) throws Exception { + joinRegion = CacheUtils.createRegion("portfolios2", Portfolio.class); + + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i); + joinRegion.put("" + i, p); + } + } + + @After + public void tearDown() throws java.lang.Exception { + qs.removeIndexes(); + if (joinRegion != null) { + joinRegion.close(); + joinRegion = null; + } + region.close(); + CacheUtils.closeCache(); + } + + /** + * Helper that tests that hash index is used and that it returns the correct result + * @throws Exception + */ + + private void helpTestHashIndexForQuery(String query)throws Exception { + helpTestHashIndexForQuery(query,"p.ID", "/portfolios p"); + } + + private void helpTestHashIndexForQuery(String query, String indexedExpression, String regionPath) throws Exception { + SelectResults nonIndexedResults = (SelectResults)qs.newQuery(query).execute(); + assertFalse(observer.indexUsed); + + index = (Index)qs.createHashIndex("idHash", indexedExpression, regionPath); + SelectResults indexedResults = (SelectResults)qs.newQuery(query).execute(); + assertEquals(nonIndexedResults.size(), indexedResults.size()); + assertTrue(observer.indexUsed); + assertTrue(indexedResults.size() > 0); + } + + private void helpTestHashIndexForQuery(String query, Object[] params, String indexedExpression, String regionPath) throws Exception { + SelectResults nonIndexedResults = (SelectResults)qs.newQuery(query).execute(params); + assertFalse(observer.indexUsed); + + index = (Index)qs.createHashIndex("idHash", indexedExpression, regionPath); + SelectResults indexedResults = (SelectResults)qs.newQuery(query).execute(params); + assertEquals(nonIndexedResults.size(), indexedResults.size()); + assertTrue(observer.indexUsed); + } + + + /* + * helper method to test against a compact range index instead of hash index + * @param query + * @throws Exception + */ + private void helpTestCRIndexForQuery(String query, String indexedExpression, String regionPath) throws Exception { + SelectResults nonIndexedResults = (SelectResults)qs.newQuery(query).execute(); + assertFalse(observer.indexUsed); + + index = (Index)qs.createIndex("crIndex", indexedExpression, regionPath); + SelectResults indexedResults = (SelectResults)qs.newQuery(query).execute(); + assertEquals(nonIndexedResults.size(), indexedResults.size()); + assertTrue(observer.indexUsed); + } + + /** + * Tests that hash index with And query for local region + * @throws Exception + */ + @Test + public void testHashIndexWithORQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.ID = 1 OR p.ID = 2", "p.ID", "/portfolios p"); + } + + @Test + public void testHashIndexWithNullsForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + int id = i % numIds; + Portfolio p = new Portfolio(id); + if(id % 2 == 0) { + p.status = null; + } + region.put("" + i, p); + } + + helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.status = 'inactive'", "p.status", "/portfolios p"); + qs.removeIndexes(); + observer = new MyQueryObserverAdapter(); + QueryObserverHolder.setInstance(observer); + helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.status != 'inactive'", "p.status", "/portfolios p"); + qs.removeIndexes(); + observer = new MyQueryObserverAdapter(); + QueryObserverHolder.setInstance(observer); + helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.status = null", "p.status", "/portfolios p"); + qs.removeIndexes(); + observer = new MyQueryObserverAdapter(); + QueryObserverHolder.setInstance(observer); + helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.status != null", "p.status", "/portfolios p"); + } + + /** + * Tests that hash index with And query for local region + * @throws Exception + */ + @Test + public void testHashIndexWithNestedQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestCRIndexForQuery("SELECT * FROM (SELECT * FROM /portfolios p WHERE p.shortID = 1)", "p.shortID", "/portfolios p"); + } + + /** + * Tests that hash index with Short vs Integer comparison + * @throws Exception + */ + @Test + public void testHashIndexWithNestedQueryWithShortVsIntegerCompareForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.shortID in (SELECT p2.ID FROM /portfolios p2 WHERE p2.shortID = 1)", "p.shortID", "/portfolios p"); + } + + + /** + * Tests that hash index with comparison between float and integer + * @throws Exception + */ +// @Test +// public void testHashIndexQueryWithFloatVsIntegerCompareForLocalRegion() throws Exception { +// createLocalRegion("portfolios"); +// int numEntries = 1000; +// int numIds = 100; +// for (int i = 0; i < numEntries; i++) { +// Portfolio p = new Portfolio(i % (numIds)); +// p.shortID = (short)i; +// region.put("" + i, p); +// } +// helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.ID = 1.0f", "p.ID", "/portfolios p"); +// } + + /** + * Tests that hash index with comparison between float and integer + * @throws Exception + */ +// @Test +// public void testHashIndexNotEqualsWithFloatVsIntegerLocalRegion() throws Exception { +// createLocalRegion("portfolios"); +// int numEntries = 1000; +// int numIds = 100; +// for (int i = 0; i < numEntries; i++) { +// Portfolio p = new Portfolio(i % (numIds)); +// p.shortID = (short)i; +// region.put("" + i, p); +// } +// helpTestCRIndexForQuery("SELECT * FROM /portfolios p WHERE p.ID != 1.0f", "p.ID", "/portfolios p"); +// } + + /** + * Tests that hash index with And query for local region + * @throws Exception + */ + @Test + public void testHashIndexWithAndQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("SELECT * FROM /portfolios p WHERE p.ID = 1 AND p.shortID > 0", "p.ID", "/portfolios p"); + } + + /** + * Tests that hash index is used and that it returns the correct result for local region + * @throws Exception + */ + @Test + public void testHashIndexWithLimitQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("SELECT * FROM /portfolios.entries p WHERE p.key = '1' limit 3", "p.key", "/portfolios.entries p"); + } + + /** + * Tests that hash index is used and that it returns the correct result for local region + * @throws Exception + */ + @Test + public void testHashIndexEntriesQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("SELECT * FROM /portfolios.entries p WHERE p.key = '1'", "p.key", "/portfolios.entries p"); + } + + /** + * Tests that hash index is used and that it returns the correct result for local region + * @throws Exception + */ + @Test + public void testHashIndexValueQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("SELECT * FROM /portfolios.values p WHERE p.ID = 1", "p.ID", "/portfolios.values p"); + } + + /** + * Tests that hash index is used and that it returns the correct result for local region + * @throws Exception + */ + @Test + public void testHashIndexKeySetQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("SELECT * FROM /portfolios.keySet p WHERE p = '1'", "p", "/portfolios.keySet p"); + } + + /** + * Tests that hash index is used and that it returns the correct result for local region + * @throws Exception + */ + @Test + public void testHashIndexEqualsForSingleResultOnLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID = 1"); + } + + /** + * Tests that hash index is used and that it returns the correct result for replicated region + * @throws Exception + */ + @Test + public void testHashIndexEqualsForSingleResultOnReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID = 1"); + } + + /** + * Tests that hash index is used and that it returns the correct result for partitioned region + * @throws Exception + */ + @Test + public void testHashIndexEqualsForSingleResultOnPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID = 1"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexAndEquiJoinForSingleResultQueryWithHashIndex() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + createJoinTable(400); + Index index = (Index)qs.createHashIndex("index2","p2.ID", "/portfolios2 p2"); + helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where (p.ID = 1 or p.ID = 2 )and p.ID = p2.ID"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexAndEquiJoinForSingleResultQueryWithCompactRangeIndex() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + createJoinTable(400); + Index index = (Index)qs.createIndex("index2","p2.ID", "/portfolios2 p2"); + helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where (p.ID = 1 or p.ID = 2 )and p.ID = p2.ID"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexAndEquiJoinForSingleResultQueryWithRangeIndex() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + createJoinTable(400); + Index index = (Index)qs.createIndex("index2","p2.ID", "/portfolios2 p2, p2.positions.values v"); + helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where (p.ID = 1 or p.ID = 2 )and p.ID = p2.ID"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ +// @Test +// public void testHashIndexAndEquiJoinForSingleResultQueryWithMapRangeIndex() throws Exception { +// createReplicatedRegion("portfolios"); +// createData(region, 1000); +// createJoinTable(2000); +// Index index = (Index)qs.createIndex("index2","p2.names[*]", "/portfolios2 p2"); +// helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where (p.names['1'] or p.names['2'] ) and p.names = p2.names", "p.names[*]", "/portfolios p"); +// } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexAndEquiJoinForSingleResultQueryWithHashIndexLessEntries() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 400); + createJoinTable(200); + Index index = (Index)qs.createHashIndex("index2","p2.ID", "/portfolios2 p2"); + helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where (p.ID = 1 or p.ID = 2 )and p.ID = p2.ID"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexAndEquiJoinForSingleResultQueryWithCompactRangeIndexLessEntries() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 400); + createJoinTable(200); + Index index = (Index)qs.createIndex("index2","p2.ID", "/portfolios2 p2"); + helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where (p.ID = 1 or p.ID = 2 )and p.ID = p2.ID"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexAndEquiJoinForSingleResultQueryWithRangeIndexLessEntries() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 400); + createJoinTable(200); + Index index = (Index)qs.createIndex("index2","p2.ID", "/portfolios2 p2, p2.positions.values v"); + helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where (p.ID = 1 or p.ID = 2 )and p.ID = p2.ID"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ +// @Test +// public void testHashIndexAndEquiJoinForSingleResultQueryWithMapRangeIndexLessEntries() throws Exception { +// createReplicatedRegion("portfolios"); +// createData(region, 1000); +// createJoinTable(500); +// Index index = (Index)qs.createIndex("index2","p2.positions[*]", "/portfolios2 p2"); +// helpTestHashIndexForQuery("Select * FROM /portfolios p, /portfolios2 p2 where p.positions['IBM'] and p.positions['IBM']=p2.positions['IBM']", "p.positions[*]", "/portfolios p"); +// } + + /** + * Tests that hash index is used and that it returns the correct number of results + * on local region + * @throws Exception + */ + @Test + public void testHashIndexEqualsForMultipleResultQueryOnLocalRegion() throws Exception { + createLocalRegion("portfolios"); + //Create the data + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID = 1"); + } + + /** + * Tests that hash index is used and that it returns the correct number of results + * on replicated region + * @throws Exception + */ + @Test + public void testHashIndexEqualsForMultipleResultQueryOnReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + //Create the data + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID = 1"); + } + + /** + * Tests that hash index is used and that it returns the correct number of results + * on partitioned region + * @throws Exception + */ + @Test + public void testHashIndexEqualsForMultipleResultQueryOnPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + //Create the data + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID = 1"); + } + + + /** + * Tests that hash index is used and that it returns the correct number of results + * @throws Exception + */ + @Test + public void testHashIndexEquiJoinForMultipleResultQueryWithHashIndex() throws Exception { + createReplicatedRegion("portfolios"); + createJoinTable(400); + index = (HashIndex) qs.createHashIndex("idHash", + "p.ID", "/portfolios p"); + Index index = (Index)qs.createHashIndex("index2","p2.ID", "/portfolios2 p2"); + + + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p, /portfolios2 p2 where p.ID = 1 and p.ID = p2.ID").execute(); + assertEquals(numEntries/numIds, results.size()); + assertTrue(observer.indexUsed); + } + + /** + * Tests that hash index is used and that the value is correctly removed from the index + * where only 1 value is using the key for partitioned regions + * @throws Exception + */ + @Test + public void testHashIndexRemoveOnLocalRegion() throws Exception { + createLocalRegion("portfolios"); + helpTestHashIndexRemove(); + } + + /** + * Tests that hash index is used and that the value is correctly removed from the index + * where only 1 value is using the key for replicated regions + * @throws Exception + */ + @Test + public void testHashIndexRemoveOnReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + helpTestHashIndexRemove(); + } + + @Test + public void testHashIndexRemoveOnPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + createData(region, 200); + region.destroy("1"); + SelectResults noIndexResults = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 1").execute(); + + region.destroyRegion(); + createPartitionedRegion("portfolios"); + createData(region, 200); + region.destroy("1"); + index = (Index)qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 1").execute(); + assertEquals(noIndexResults.size(), results.size()); + assertTrue(observer.indexUsed); + } + /** + * Tests that hash index is used and that the value is correctly removed from the index + * where only 1 value is using the key for partitioned regions + * @throws Exception + */ + private void helpTestHashIndexRemove() throws Exception { + createData(region, 200); + region.destroy("1"); + SelectResults noIndexResults = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 1").execute(); + + region.clear(); + createData(region, 200); + region.destroy("1"); + index = (Index)qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 1").execute(); + assertEquals(noIndexResults.size(), results.size()); + assertTrue(observer.indexUsed); + } + + /** + * Tests that hash index is used and that the value is correctly removed from the index + * where multiple entries are using the key on localRegion + * @throws Exception + */ + @Test + public void testHashIndexRemoveFromCommonKeyQueryOnLocalRegion() throws Exception { + createLocalRegion("portfolios"); + helpTestHashIndexRemoveFromCommonKeyQuery(); + } + + /** + * Tests that hash index is used and that the value is correctly removed from the index + * where multiple entries are using the key on replicated region + * @throws Exception + */ + @Test + public void testHashIndexRemoveFromCommonKeyQueryOnReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + helpTestHashIndexRemoveFromCommonKeyQuery(); + } + + /** + * Tests that hash index is used and that the value is correctly removed from the index + * where multiple entries are using the key on partitioned region + * @throws Exception + */ + @Test + public void testHashIndexRemoveFromCommonKeyQueryOnPartitionedRegion() throws Exception { + createReplicatedRegion("portfolios"); + helpTestHashIndexRemoveFromCommonKeyQuery(); + } + + private void helpTestHashIndexRemoveFromCommonKeyQuery() throws Exception { + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + Portfolio p2 = new Portfolio(10000); + region.put("2", p2); + p2.ID = 1000; + region.put("2", p2); + SelectResults noIndexResult = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 2").execute(); + + region.clear(); + index = (HashIndex) qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + p2 = new Portfolio(10000); + region.put("2", p2); + p2.ID = 1000; + region.put("2", p2); + + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 2").execute(); + assertEquals(numEntries/numIds - 1, results.size()); + assertEquals(noIndexResult.size(), results.size()); + assertTrue(observer.indexUsed); + } + + /** + * Tests that hash index is used and that it returns the correct result + * on local region + * @throws Exception + */ + @Test + public void testHashIndexNotEqualsQueryOnLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * on replicated region + * @throws Exception + */ + @Test + public void testHashIndexNotEqualsQueryOnReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * on partitioned region + * @throws Exception + */ + @Test + public void testHashIndexNotEqualsQueryOnPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index is used and that it returns the correct number of results + * for local region + * @throws Exception + */ + @Test + public void testHashIndexNotEqualsForMultipleResultQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index is used and that it returns the correct number of results + * for replicated region + * @throws Exception + */ + @Test + public void testHashIndexNotEqualsForMultipleResultQueryForReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index is used and that it returns the correct number of results + * for partitioned region + * @throws Exception + */ + @Test + public void testHashIndexNotEqualsForMultipleResultQueryForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + int numEntries = 200; + int numIds = 100; + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i % (numIds)); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexInQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID in set (1)"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexInQueryForReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID in set (1)"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + @Test + public void testHashIndexInQueryForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID in set (1)"); + } + + /** + * Tests that hash index is used and that it returns the correct result + * for local region + * @throws Exception + */ + @Test + public void testHashIndexNotUsedInRangeQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexNotUsedInRangeQuery(); + } + + /** + * Tests that hash index is used and that it returns the correct result + * for replicated region + * @throws Exception + */ + @Test + public void testHashIndexNotUsedInRangeQueryForReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexNotUsedInRangeQuery(); + } + + /** + * Tests that hash index is used and that it returns the correct result + * for partitioned region + * @throws Exception + */ + @Test + public void testHashIndexNotUsedInRangeQueryForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexNotUsedInRangeQuery(); + } + + /** + * Tests that hash index is used and that it returns the correct result + * @throws Exception + */ + private void helpTestHashIndexNotUsedInRangeQuery() throws Exception { + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID < 2").execute(); + assertFalse(observer.indexUsed); + } + + /** + * Test order by asc query for local region using hash index + * @throws Exception + */ + @Test + public void testHashIndexOrderByAscQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexOrderByAscQuery(); + } + + /** + * Test order by asc query for replicated region using hash index + * @throws Exception + */ + @Test + public void testHashIndexOrderByAscQueryForReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexOrderByAscQuery(); + } + + /** + * Test order by asc query for partitioned region using hash index + * @throws Exception + */ + @Test + public void testHashIndexOrderByAscQueryForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexOrderByAscQuery(); + } + + private void helpTestHashIndexOrderByAscQuery() throws Exception { + index = (Index)qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID != 0 order by ID asc ").execute(); + assertEquals(199, results.size()); + assertTrue(observer.indexUsed); + int countUp = 1; + for (Object o: results) { + Portfolio p = (Portfolio) o; + assertEquals(countUp++, p.getID()); + } + } + + /** + * Test order by desc query for local region using hash index + * @throws Exception + */ + @Test + public void testHashIndexOrderByDescQueryForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + createData(region, 200); + helpTestHashIndexOrderByDescQuery(); + } + + /** + * Test order by desc query for replicated region using hash index + * @throws Exception + */ + @Test + public void testHashIndexOrderByDescQueryForReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexOrderByDescQuery(); + } + + /** + * Test order by desc query for partitioned region using hash index + * @throws Exception + */ + @Test + public void testHashIndexOrderByDescQueryForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + createData(region, 200); + helpTestHashIndexOrderByDescQuery(); + } + + /** + * Tests that hash index on non sequential hashes + * for local region + * @throws Exception + */ + @Test + public void testHashIndexOnNonSequentialHashForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + for (int i = 0; i < 100; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + + for (int i = 200; i < 300; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + + for (int i = 500; i < 600; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index on non sequential hashes + * for replicated region + * @throws Exception + */ + @Test + public void testHashIndexOnNonSequentialHashForReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + for (int i = 0; i < 100; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + + for (int i = 200; i < 300; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + + for (int i = 500; i < 600; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + /** + * Tests that hash index on non sequential hashes + * for partitioned region + * @throws Exception + */ + @Test + public void testHashIndexOnNonSequentialHashForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + for (int i = 0; i < 100; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + + for (int i = 200; i < 300; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + + for (int i = 500; i < 600; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + helpTestHashIndexForQuery("Select * FROM /portfolios p where p.ID != 1"); + } + + private void helpTestHashIndexOrderByDescQuery() throws Exception { + index = (Index)qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID != 0 order by ID desc ").execute(); + assertEquals(199, results.size()); + assertTrue(observer.indexUsed); + int countDown = 199; + for (Object o: results) { + Portfolio p = (Portfolio) o; + assertEquals(countDown--, p.getID()); + } + } + + /** + * test async exception for hash index using partitioned region + * @throws Exception + */ + @Test + public void testHashIndexAsyncMaintenanceExceptionForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios_async", false); + helpTestAsyncMaintenance(); + } + + private void helpTestAsyncMaintenance() throws Exception { + boolean expected = false; + try { + index = qs.createHashIndex("idHash", "p.ID", "/portfolios_async p"); + } + catch ( UnsupportedOperationException e) { + expected = true; + } + catch (IndexInvalidException e) { + //for partition region execption; + expected = true; + } + + assertTrue(expected); + } + + /** + * test multiple iterators exception for hash index using local region + * @throws Exception + */ + @Test + public void testHashIndexMultipleIteratorsExceptionForLocalRegion() throws Exception { + createLocalRegion("portfolios"); + helpTestMultipleIteratorsException(); + } + + /** + * test multiple iterators exception for hash index using replicated region + * @throws Exception + */ + @Test + public void testHashIndexMultipleIteratorsExceptionForReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + helpTestMultipleIteratorsException(); + } + + /** + * test multiple iterators exception for hash index using partiioned region + * @throws Exception + */ + @Test + public void testHashIndexMultipleIteratorsExceptionForPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + helpTestMultipleIteratorsException(); + } + + private void helpTestMultipleIteratorsException() throws Exception { + boolean expected = false; + try { + index = qs.createHashIndex("idHash", + "p.ID", "/portfolios p, p.positions.values p"); + } + catch ( UnsupportedOperationException e) { + expected = true; + } + assertTrue(expected); + } + + /** + * test remove and not equals Query + * @throws Exception + */ + @Test + public void testRemoveAndNotEqualsQuery() throws Exception { + createReplicatedRegion("portfolios"); + helpTestRemoveAndNotEqualsQuery(); + } + + private void helpTestRemoveAndNotEqualsQuery() throws Exception { + int numEntries = 200; + index = (HashIndex) qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i); + p.shortID = (short)i; + region.put("" + i, p); + } + + region.destroy("1"); + + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID != 1").execute(); + assertEquals(numEntries - 1, results.size()); + assertTrue(observer.indexUsed); + } + + @Test + public void testHashCollisionAndProbe() throws Exception { + createReplicatedRegion("relationships"); + int numEntries = 40000; + int numIds = 200; + for (int i = 0; i < numEntries; i++) { + int ki = i % numIds; + Object key = new RelationshipKey(ki, i); + Object value = new Schema(new Relationship(new RelationshipKey(ki, i))); + region.put(key, value); + } + Object[] params = new Object[2]; + params[0] = new Identifier("Customer" +1); + params[1] = new Identifier("Customer" + 1); + String query = "select * from /relationships.keySet k where k.leftKey = $1 OR k.rightKey = $2"; +// String query = "select * from /relationships r where r.relationship.key IN (select * from /relationships.keySet k where k.leftKey = $1 OR k.rightKey = $2)"; + SelectResults nonIndexedResults = (SelectResults)qs.newQuery(query).execute(params); + assertFalse(observer.indexUsed); + + index = (Index)qs.createHashIndex("leftKey", "k.leftKey", "/relationships.keySet k"); + Index index2 = (Index)qs.createHashIndex("rightKey", "k.rightKey", "/relationships.keySet k"); + Index index3 = (Index)qs.createKeyIndex("keyIndex", "r.key", "/relationships r"); + SelectResults indexedResults = (SelectResults)qs.newQuery(query).execute(params); + assertEquals(nonIndexedResults.size(), indexedResults.size()); + assertEquals(nonIndexedResults.size(), numEntries/numIds); + assertTrue(observer.indexUsed); + } + + @Test + public void testHashIndexRecreateOnReplicatedRegion() throws Exception { + createReplicatedRegion("portfolios"); + helpTestHashIndexRecreate(); + } + + @Test + public void testHashIndexRecreateOnPartitionedRegion() throws Exception { + createPartitionedRegion("portfolios"); + helpTestHashIndexRecreate(); + } + + private void helpTestHashIndexRecreate() throws Exception { + index = (Index)qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + createData(region, 200); + + SelectResults noIndexResults = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 1").execute(); + + IndexStatistics ist = index.getStatistics(); + assertEquals(200, ist.getNumberOfValues()); + assertEquals(200, ist.getNumUpdates()); + assertEquals(1, ist.getTotalUses()); + + region.clear(); + + ist = index.getStatistics(); + assertEquals(0, ist.getNumberOfValues()); + assertEquals(1, ist.getTotalUses()); + assertEquals(400, ist.getNumUpdates()); + + createData(region, 200); + + SelectResults results = (SelectResults)qs.newQuery("Select * FROM /portfolios p where p.ID = 1").execute(); + + ist = index.getStatistics(); + assertEquals(200, ist.getNumberOfValues()); + assertEquals(2, ist.getTotalUses()); + assertEquals(600, ist.getNumUpdates()); + + assertEquals(noIndexResults.size(), results.size()); + assertTrue(observer.indexUsed); + } + + @Test + public void testUpdatesOnKeyWithSameHash() throws Exception { + createReplicatedRegion("portfolios"); + helpTestUpdatesOnKeyWithSameHash(); + } + + private void helpTestUpdatesOnKeyWithSameHash() throws Exception { + int numEntries = 10; + for (int i = 0; i < numEntries; i++) { + SameHashObject p = new SameHashObject(5, i); + region.put("" + i, p); + } + region.put("0", new SameHashObject(100, 100)); + SelectResults noIndexResults = (SelectResults) qs.newQuery( + "Select * FROM /portfolios p where p.ID = 5").execute(); + region.clear(); + + HashIndex index = (HashIndex) qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + for (int i = 0; i < numEntries; i++) { + SameHashObject p = new SameHashObject(5, i); + region.put("" + i, p); + } + region.put("0", new SameHashObject(index.entriesSet.hashIndexSetProperties.set.length + 5, 100)); + + SelectResults results = (SelectResults) qs.newQuery( + "Select * FROM /portfolios p where p.ID = 5").execute(); + + assertTrue(results.size() > 0); + assertEquals(noIndexResults.size(), results.size()); + assertTrue(observer.indexUsed); + } + + @Test + public void testInPlaceModification() throws Exception { + createReplicatedRegion("portfolios"); + int numEntries = 10; + HashIndex index = (HashIndex) qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + for (int i = 0; i < numEntries; i++) { + SameHashObject p = new SameHashObject(5, i); + region.put("" + i, p); + } + SameHashObject object = (SameHashObject)region.get("0"); + object.ID = 200; + region.put("0", object); + + SelectResults results = (SelectResults) qs.newQuery( + "Select * FROM /portfolios p where p.ID = 5").execute(); + assertEquals(10, index.getStatistics().getNumberOfValues()); + assertEquals(9, results.size()); + assertTrue(observer.indexUsed); + } + + @Test + public void testInPlaceModificationToSameKey() throws Exception { + createReplicatedRegion("portfolios"); + int numEntries = 10; + HashIndex index = (HashIndex) qs.createHashIndex("idHash", "p.ID", "/portfolios p"); + for (int i = 0; i < numEntries; i++) { + SameHashObject p = new SameHashObject(5, i); + region.put("" + i, p); + } + SameHashObject object = (SameHashObject)region.get("0"); + object.ID = 5; + region.put("0", object); + + SelectResults results = (SelectResults) qs.newQuery( + "Select * FROM /portfolios p where p.ID = 5").execute(); + assertEquals(10, index.getStatistics().getNumberOfValues()); + assertEquals(10, results.size()); + assertTrue(observer.indexUsed); + } + + @Test + public void testInPlaceModificationWithUndefinedKeys() throws Exception { + createReplicatedRegion("portfolios"); + int numEntries = 10; + Index index = qs.createIndex("idHash", "p.IDS", "/portfolios p"); + for (int i = 0; i < numEntries; i++) { + SameHashObject p = new SameHashObject(5, i); + region.put("" + i, p); + } + SameHashObject object = (SameHashObject)region.get("0"); + object.ID = 5; + region.put("0", object); + + SelectResults results = (SelectResults) qs.newQuery( + "Select * FROM /portfolios p where p.IDS = 5").execute(); + assertEquals(10, index.getStatistics().getNumberOfValues()); + assertEquals(0, results.size()); + assertTrue(observer.indexUsed); + } + + @Test + public void testInPlaceModificationWithNullKeys() throws Exception { + createReplicatedRegion("portfolios"); + int numEntries = 10; + Index index = qs.createHashIndex("idHash", "p.stringValue", "/portfolios p"); + for (int i = 0; i < numEntries; i++) { + SameHashObject p = new SameHashObject(5, i, null); + region.put("" + i, p); + } + SameHashObject object = (SameHashObject)region.get("0"); + object.stringValue = "wow"; + region.put("0", object); + + SelectResults results = (SelectResults) qs.newQuery( + "Select * FROM /portfolios p where p.stringValue = 'wow'").execute(); + assertEquals(10, index.getStatistics().getNumberOfValues()); + assertEquals(1, results.size()); + assertTrue(observer.indexUsed); + } + + @Test + public void testOverflowWithRehash() throws Exception { + try { + final boolean[] threadCompleted = new boolean[3]; + createReplicatedRegionWithOverflow("portfolios"); + HashIndexSet.TEST_ALWAYS_REHASH = true; + Index index = qs.createHashIndex("idHash", "p", "/portfolios p"); + + Thread puts = new Thread(new Runnable() { + public void run() { + for (int j = 0; j < 20; j++) { + for (int i = 0; i < 2; i++) { + region.put("" + i, "SOME STRING OBJECT" + i); + } + } + threadCompleted[0] = true; + } + }); + + Thread morePuts = new Thread(new Runnable() { + public void run() { + for (int j = 0; j < 20; j++) { + for (int i = 0; i < 1; i++) { + region.put("" + (i + 100), "SOME OTHER STRING OBJECT" + (i+100)); + } + } + threadCompleted[1] = true; + } + }); + + Thread evenMorePuts = new Thread(new Runnable() { + public void run() { + for (int j = 0; j < 20; j++) { + for (int i = 0; i < 1; i++) { + region.put("" + (i + 200), "ANOTHER STRING OBJECT" + (i + 200)); + } + } + threadCompleted[2] = true; + } + }); + + evenMorePuts.start(); + morePuts.start(); + puts.start(); + + puts.join(30000); + morePuts.join(30000); + evenMorePuts.join(30000); + assertTrue("Thread possibly deadlocked, thread did not complete", threadCompleted[0]); + assertTrue("Thread possibly deadlocked, thread did not complete", threadCompleted[1]); + assertTrue("Thread possibly deadlocked, thread did not complete", threadCompleted[2]); + + SelectResults results = (SelectResults) qs.newQuery( + "Select * FROM /portfolios p").execute(); + assertEquals(4, results.size()); + } + finally { + HashIndexSet.TEST_ALWAYS_REHASH = false; + } + } + + @Test + public void testPdxWithStringIndexKeyValues() throws Exception { + createPartitionedRegion("test_region"); + int numEntries = 10; + Index index = qs.createHashIndex("idHash", "p.id", "/test_region p"); + for (int i = 0; i < numEntries; i++) { + PdxInstance record = CacheUtils.getCache().createPdxInstanceFactory("test_region").writeString("id", "" + i).writeString("domain", "A").create(); + region.put("" + i, record); + } + + SelectResults results = (SelectResults) qs.newQuery( + "SELECT DISTINCT tr.domain FROM /test_region tr WHERE tr.id='1'").execute(); + assertEquals(1, results.size()); + assertTrue(observer.indexUsed); + } + + +// private void printIndex(Index index) { +// if (index instanceof PartitionedIndex) { +// Iterator it = ((PartitionedIndex)index).getBucketIndexes().iterator(); +// while (it.hasNext()) { +// ((HashIndex)it.next()).printAll(); +// } +// } +// else { +// System.out.println(((HashIndex)index).printAll()); +// } +// } + + + private class RelationshipKey implements Comparable { + public Identifier leftKey; + public Identifier rightKey; + + public RelationshipKey(int leftKeyId, int rightKeyId) { + this.leftKey = new Identifier("Customer" + leftKeyId); + this.rightKey = new Identifier("Customer" + rightKeyId); + } + + public Identifier getLeftKey() { + return leftKey; + } + public Identifier getRightKey() { + return rightKey; + } + + public int compareTo(Object o) { + if (o instanceof RelationshipKey) { + return leftKey.compareTo(((RelationshipKey)o).leftKey); + } + throw new ClassCastException("Unable to cast " + o + " to Identifier"); + } + + public boolean equals(Object o) { + if (o instanceof RelationshipKey) { + return leftKey.equals(((RelationshipKey)o).leftKey) && rightKey.equals(((RelationshipKey)o).rightKey); + } + return false; + } + + @Override + public int hashCode() { + return leftKey.hashCode(); + } + } + + private class Schema { + public Relationship relationship; + + public Schema(Relationship relationship) { + this.relationship = relationship; + } + + public Relationship getRelationship() { + return relationship; + } + } + + private class Relationship { + public RelationshipKey key; + public Relationship(RelationshipKey key) { + this.key = key; + } + + public RelationshipKey getKey() { + return key; + } + } + + public class Identifier implements Comparable { + private int hashCode = 0; + public String id; + + public Identifier(String id) { + this.id = id; + } + + @Override + public int compareTo(Object o) { + if (o instanceof Identifier) { + String otherId = ((Identifier)o).id; + return id.compareTo(otherId); + } + throw new ClassCastException("Unable to cast " + o + " to Identifier"); + } + + public boolean equals(Object o) { + if (o instanceof Identifier) { + return id.equals(((Identifier)o).id); + } + return false; + } + + @Override + public int hashCode() { + if (this.hashCode == 0) { + this.hashCode = id.hashCode(); + this.hashCode += 7 * "something".hashCode(); + } + + return this.hashCode; + } + } + + public class SameHashObject implements Serializable { + + public int ID = 0; + public String stringValue; + private int uniqueId = 0; + + public SameHashObject(int i, int uniqueId, String stringValue) { + ID = i; + this.uniqueId = uniqueId; + this.stringValue = stringValue; + } + + public SameHashObject(int i, int uniqueId) { + this(i, uniqueId, "" + i); + } + + public boolean equals(Object o) { + if (o instanceof SameHashObject) { + return ID == ((SameHashObject)o).ID; + } + return false; + } + public int hashCode() { + return 99; + } + + public String toString() { + return "SameHashObject:" + ID + ":" + uniqueId + " :" + stringValue; + } + } + + + private void createLocalRegion(String regionName) throws ParseException { + createLocalRegion(regionName, true); + } + + private void createLocalRegion(String regionName, boolean synchMaintenance) throws ParseException { + Cache cache = CacheUtils.getCache(); + AttributesFactory attributesFactory = new AttributesFactory(); + attributesFactory.setDataPolicy(DataPolicy.NORMAL); + attributesFactory.setIndexMaintenanceSynchronous(synchMaintenance); + RegionAttributes regionAttributes = attributesFactory.create(); + region = cache.createRegion(regionName, regionAttributes); + } + + private void createReplicatedRegion(String regionName) throws ParseException { + createReplicatedRegion(regionName, true); + } + + private void createReplicatedRegion(String regionName, boolean synchMaintenance) throws ParseException { + Cache cache = CacheUtils.getCache(); + AttributesFactory attributesFactory = new AttributesFactory(); + attributesFactory.setDataPolicy(DataPolicy.REPLICATE); + attributesFactory.setIndexMaintenanceSynchronous(synchMaintenance); + RegionAttributes regionAttributes = attributesFactory.create(); + region = cache.createRegion(regionName, regionAttributes); + } + + private void createReplicatedRegionWithOverflow(String regionName) throws ParseException { + Cache cache = CacheUtils.getCache(); + AttributesFactory attributesFactory = new AttributesFactory(); + attributesFactory.setDataPolicy(DataPolicy.REPLICATE); + attributesFactory.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(1, EvictionAction.OVERFLOW_TO_DISK)); + RegionAttributes regionAttributes = attributesFactory.create(); + region = cache.createRegion(regionName, regionAttributes); + } + + private void createPartitionedRegion(String regionName) throws ParseException { + createLocalRegion(regionName, true); + } + + private void createPartitionedRegion(String regionName, boolean synchMaintenance) throws ParseException { + Cache cache = CacheUtils.getCache(); + PartitionAttributesFactory prAttFactory = new PartitionAttributesFactory(); + AttributesFactory attributesFactory = new AttributesFactory(); + attributesFactory.setPartitionAttributes(prAttFactory.create()); + attributesFactory.setIndexMaintenanceSynchronous(synchMaintenance); + RegionAttributes regionAttributes = attributesFactory.create(); + region = cache.createRegion(regionName, regionAttributes); + } + + private void createData(Region region, int numEntries) { + for (int i = 0; i < numEntries; i++) { + Portfolio p = new Portfolio(i); + region.put("" + i, p); + } + } + + + class MyQueryObserverAdapter extends QueryObserverAdapter { + public boolean indexUsed = false; + + public void afterIndexLookup(Collection results){ + super.afterIndexLookup(results); + indexUsed = true; + } + }; + + +}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/b5b7203a/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/RangeIndexMaintenanceIntegrationTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/RangeIndexMaintenanceIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/RangeIndexMaintenanceIntegrationTest.java new file mode 100644 index 0000000..659433f --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/RangeIndexMaintenanceIntegrationTest.java @@ -0,0 +1,39 @@ +/* + * 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.geode.cache.query.internal.index; + +import org.junit.experimental.categories.Category; + +import org.apache.geode.cache.query.IndexExistsException; +import org.apache.geode.cache.query.IndexNameConflictException; +import org.apache.geode.cache.query.QueryService; +import org.apache.geode.cache.query.RegionNotFoundException; +import org.apache.geode.test.junit.categories.IntegrationTest; + +@Category(IntegrationTest.class) +public class RangeIndexMaintenanceIntegrationTest extends AbstractIndexMaintenanceIntegrationTest { + + @Override + protected AbstractIndex createIndex(final QueryService qs, String name, String indexExpression, String regionPath) + throws IndexNameConflictException, IndexExistsException, RegionNotFoundException { + boolean oldTestValue = IndexManager.TEST_RANGEINDEX_ONLY; + IndexManager.TEST_RANGEINDEX_ONLY = true; + RangeIndex index = (RangeIndex)qs.createIndex(name, indexExpression, regionPath); + IndexManager.TEST_RANGEINDEX_ONLY = oldTestValue; + return index; + } +}