/* * 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.assertTrue; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.cache.Cache; import org.apache.geode.cache.Region; 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.IndexStatistics; import org.apache.geode.cache.query.IndexType; import org.apache.geode.cache.query.Query; import org.apache.geode.cache.query.QueryService; import org.apache.geode.cache.query.SelectResults; import org.apache.geode.cache.query.data.Numbers; import org.apache.geode.cache.query.data.Portfolio; import org.apache.geode.cache.query.data.Position; import org.apache.geode.cache.query.internal.QueryObserver; import org.apache.geode.cache.query.internal.QueryObserverAdapter; import org.apache.geode.cache.query.internal.QueryObserverHolder; import org.apache.geode.test.junit.categories.IntegrationTest; /** * */ @Category(IntegrationTest.class) public class IndexStatisticsJUnitTest { static QueryService qs; static boolean isInitDone = false; static Region region; static IndexProtocol keyIndex1; static IndexProtocol keyIndex2; static IndexProtocol keyIndex3; @Before public void setUp() throws Exception { try { CacheUtils.startCache(); region = CacheUtils.createRegion("portfolio", Portfolio.class); Position.cnt = 0; if (region.size() == 0) { for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } } assertEquals(100, region.size()); qs = CacheUtils.getQueryService(); } catch (Exception e) { e.printStackTrace(); } } @After public void tearDown() throws Exception { CacheUtils.closeCache(); IndexManager.TEST_RANGEINDEX_ONLY = false; } /* * public static Test suite() { TestSuite suite = new TestSuite(IndexMaintenanceTest.class); * return suite; } */ /** * Test RenageIndex IndexStatistics for keys, values, updates and uses. * * @throws Exception */ @Test public void testStatsForRangeIndex() throws Exception { keyIndex1 = (IndexProtocol) qs.createIndex("multiKeyIndex1", IndexType.FUNCTIONAL, "pos.secId", "/portfolio p, p.positions.values pos"); assertTrue(keyIndex1 instanceof RangeIndex); IndexStatistics keyIndex1Stats = keyIndex1.getStatistics(); // Initial stats test (keys, values & updates) assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(200, keyIndex1Stats.getNumberOfValues()); assertEquals(200, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(200, keyIndex1Stats.getNumberOfValues()); assertEquals(400, keyIndex1Stats.getNumUpdates()); // IndexUsed stats test String queryStr = "select * from /portfolio p, p.positions.values pos where pos.secId = 'YHOO'"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(50, keyIndex1Stats.getTotalUses()); assertEquals(0, keyIndex1Stats.getReadLockCount()); // NumOfValues should be reduced. for (int i = 0; i < 50; i++) { region.invalidate(Integer.toString(i)); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(450, keyIndex1Stats.getNumUpdates()); // Should not have any effect as invalidated values are destroyed for (int i = 0; i < 50; i++) { region.destroy(Integer.toString(i)); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(450, keyIndex1Stats.getNumUpdates()); // NumOfKeys should get zero as all values are destroyed for (int i = 50; i < 100; i++) { region.destroy(Integer.toString(i)); } assertEquals(500, keyIndex1Stats.getNumUpdates()); assertEquals(0, keyIndex1Stats.getNumberOfKeys()); qs.removeIndex(keyIndex1); } @Test public void testStatsForRangeIndexAfterRecreate() throws Exception { keyIndex2 = (IndexProtocol) qs.createIndex("multiKeyIndex2", IndexType.FUNCTIONAL, "pos.secId", "/portfolio p, p.positions.values pos"); assertTrue(keyIndex2 instanceof RangeIndex); IndexStatistics keyIndex1Stats = keyIndex2.getStatistics(); // Initial stats test (keys, values & updates) assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(200, keyIndex1Stats.getNumberOfValues()); assertEquals(200, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } String queryStr = "select * from /portfolio p, p.positions.values pos where pos.secId = 'YHOO'"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(200, keyIndex1Stats.getNumberOfValues()); assertEquals(400, keyIndex1Stats.getNumUpdates()); assertEquals(50, keyIndex1Stats.getTotalUses()); region.clear(); assertEquals(0, keyIndex1Stats.getNumberOfKeys()); assertEquals(0, keyIndex1Stats.getNumberOfValues()); assertEquals(800, keyIndex1Stats.getNumUpdates()); assertEquals(50, keyIndex1Stats.getTotalUses()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(200, keyIndex1Stats.getNumberOfValues()); assertEquals(1000, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(100, keyIndex1Stats.getTotalUses()); qs.removeIndex(keyIndex2); } /** * Test CompactRenageIndex IndexStatistics for keys, values, updates and uses. * * @throws Exception */ @Test public void testStatsForCompactRangeIndex() throws Exception { keyIndex2 = (IndexProtocol) qs.createIndex("multiKeyIndex2", IndexType.FUNCTIONAL, "ID", "/portfolio "); assertTrue(keyIndex2 instanceof CompactRangeIndex); IndexStatistics keyIndex1Stats = keyIndex2.getStatistics(); // Initial stats test (keys, values & updates) assertEquals(100, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(100, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(100, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(200, keyIndex1Stats.getNumUpdates()); // IndexUsed stats test String queryStr = "select * from /portfolio where ID > 0"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(0, keyIndex1Stats.getReadLockCount()); assertEquals(50, keyIndex1Stats.getTotalUses()); // NumOfValues should be reduced. for (int i = 0; i < 50; i++) { region.invalidate(Integer.toString(i)); } assertEquals(50, keyIndex1Stats.getNumberOfKeys()); assertEquals(50, keyIndex1Stats.getNumberOfValues()); assertEquals(250, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 50; i++) { region.destroy(Integer.toString(i)); } assertEquals(50, keyIndex1Stats.getNumberOfKeys()); assertEquals(50, keyIndex1Stats.getNumberOfValues()); assertEquals(250, keyIndex1Stats.getNumUpdates()); // NumOfKeys should get zero as all values are destroyed for (int i = 50; i < 100; i++) { region.destroy(Integer.toString(i)); } assertEquals(300, keyIndex1Stats.getNumUpdates()); assertEquals(0, keyIndex1Stats.getNumberOfKeys()); qs.removeIndex(keyIndex2); } @Test public void testStatsForCompactRangeIndexAfterRecreate() throws Exception { keyIndex2 = (IndexProtocol) qs.createIndex("multiKeyIndex2", IndexType.FUNCTIONAL, "ID", "/portfolio "); assertTrue(keyIndex2 instanceof CompactRangeIndex); IndexStatistics keyIndex1Stats = keyIndex2.getStatistics(); // Initial stats test (keys, values & updates) assertEquals(100, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(100, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } String queryStr = "select * from /portfolio where ID > 0"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(100, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(200, keyIndex1Stats.getNumUpdates()); assertEquals(50, keyIndex1Stats.getTotalUses()); region.clear(); assertEquals(0, keyIndex1Stats.getNumberOfKeys()); assertEquals(0, keyIndex1Stats.getNumberOfValues()); assertEquals(400, keyIndex1Stats.getNumUpdates()); assertEquals(50, keyIndex1Stats.getTotalUses()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(100, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(500, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(100, keyIndex1Stats.getTotalUses()); qs.removeIndex(keyIndex2); } /** * Test CompactMapRenageIndex IndexStatistics for keys, values, updates and uses. * * @throws Exception */ @Test public void testStatsForCompactMapRangeIndex() throws Exception { keyIndex3 = (IndexProtocol) qs.createIndex("multiKeyIndex3", IndexType.FUNCTIONAL, "positions['DELL', 'YHOO']", "/portfolio p"); assertTrue(keyIndex3 instanceof CompactMapRangeIndex); Object[] indexes = ((CompactMapRangeIndex) keyIndex3).getRangeIndexHolderForTesting().values().toArray(); assertTrue(indexes[0] instanceof CompactRangeIndex); assertTrue(indexes[1] instanceof CompactRangeIndex); IndexStatistics keyIndexStats = keyIndex3.getStatistics(); assertEquals(2, keyIndexStats.getNumberOfMapIndexKeys()); assertEquals(100, keyIndexStats.getNumberOfKeys()); assertEquals(100, keyIndexStats.getNumberOfKeys()); assertEquals(100, keyIndexStats.getNumberOfValues()); assertEquals(100, keyIndexStats.getNumUpdates()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(2, keyIndexStats.getNumberOfMapIndexKeys()); assertEquals(100, keyIndexStats.getNumberOfKeys()); assertEquals(100, keyIndexStats.getNumberOfValues()); assertEquals(200, keyIndexStats.getNumUpdates()); String queryStr = "select * from /portfolio where positions['DELL'] != NULL OR positions['YHOO'] != NULL"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(0, keyIndexStats.getReadLockCount()); assertEquals(100, keyIndexStats.getTotalUses()); for (int i = 0; i < 50; i++) { region.invalidate(Integer.toString(i)); } assertEquals(2, keyIndexStats.getNumberOfMapIndexKeys()); assertEquals(50, keyIndexStats.getNumberOfKeys()); assertEquals(50, keyIndexStats.getNumberOfValues()); assertEquals(250, keyIndexStats.getNumUpdates()); for (int i = 0; i < 50; i++) { region.destroy(Integer.toString(i)); } assertEquals(2, keyIndexStats.getNumberOfMapIndexKeys()); assertEquals(50, keyIndexStats.getNumberOfKeys()); assertEquals(50, keyIndexStats.getNumberOfValues()); assertEquals(250, keyIndexStats.getNumUpdates()); for (int i = 50; i < 100; i++) { region.destroy(Integer.toString(i)); } assertEquals(300, keyIndexStats.getNumUpdates()); assertEquals(2, keyIndexStats.getNumberOfMapIndexKeys()); assertEquals(0, keyIndexStats.getNumberOfKeys()); qs.removeIndex(keyIndex3); region.destroyRegion(); } /** * Test MapRenageIndex IndexStatistics for keys, values, updates and uses. * * @throws Exception */ @Test public void testStatsForMapRangeIndex() throws Exception { IndexManager.TEST_RANGEINDEX_ONLY = true; keyIndex3 = (IndexProtocol) qs.createIndex("multiKeyIndex3", IndexType.FUNCTIONAL, "positions['DELL', 'YHOO']", "/portfolio"); assertTrue(keyIndex3 instanceof MapRangeIndex); Object[] indexes = ((MapRangeIndex) keyIndex3).getRangeIndexHolderForTesting().values().toArray(); assertTrue(indexes[0] instanceof RangeIndex); assertTrue(indexes[1] instanceof RangeIndex); IndexStatistics mapIndexStats = keyIndex3.getStatistics(); assertEquals(2, mapIndexStats.getNumberOfMapIndexKeys()); assertEquals(100, mapIndexStats.getNumberOfKeys()); assertEquals(100, mapIndexStats.getNumberOfValues()); assertEquals(100, mapIndexStats.getNumUpdates()); Position.cnt = 0; for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(2, mapIndexStats.getNumberOfMapIndexKeys()); assertEquals(100, mapIndexStats.getNumberOfKeys()); assertEquals(100, mapIndexStats.getNumberOfValues()); assertEquals(200, mapIndexStats.getNumUpdates()); String queryStr = "select * from /portfolio where positions['DELL'] != NULL OR positions['YHOO'] != NULL"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(0, mapIndexStats.getReadLockCount()); assertEquals(100, mapIndexStats.getTotalUses()); for (int i = 0; i < 50; i++) { region.invalidate(Integer.toString(i)); } assertEquals(2, mapIndexStats.getNumberOfMapIndexKeys()); assertEquals(50, mapIndexStats.getNumberOfKeys()); assertEquals(50, mapIndexStats.getNumberOfValues()); assertEquals(300, mapIndexStats.getNumUpdates()); for (int i = 0; i < 50; i++) { region.destroy(Integer.toString(i)); } assertEquals(2, mapIndexStats.getNumberOfMapIndexKeys()); assertEquals(50, mapIndexStats.getNumberOfKeys()); assertEquals(50, mapIndexStats.getNumberOfValues()); assertEquals(300, mapIndexStats.getNumUpdates()); for (int i = 50; i < 100; i++) { region.destroy(Integer.toString(i)); } assertEquals(400, mapIndexStats.getNumUpdates()); assertEquals(2, mapIndexStats.getNumberOfMapIndexKeys()); assertEquals(0, mapIndexStats.getNumberOfKeys()); qs.removeIndex(keyIndex3); } /** * Test RenageIndex IndexStatistics for keys, values, updates and uses. * * @throws Exception */ @Test public void testStatsForRangeIndexBeforeRegionCreation() throws Exception { // Destroy region region.clear(); assertEquals(0, region.size()); Position.cnt = 0; keyIndex1 = (IndexProtocol) qs.createIndex("multiKeyIndex4", IndexType.FUNCTIONAL, "pos.secId", "/portfolio p, p.positions.values pos"); // Recreate all entries in the region for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertTrue(keyIndex1 instanceof RangeIndex); IndexStatistics keyIndex1Stats = keyIndex1.getStatistics(); // Initial stats test (keys, values & updates) assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(200, keyIndex1Stats.getNumberOfValues()); assertEquals(200, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(200, keyIndex1Stats.getNumberOfValues()); assertEquals(400, keyIndex1Stats.getNumUpdates()); // IndexUsed stats test String queryStr = "select * from /portfolio p, p.positions.values pos where pos.secId = 'YHOO'"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(50, keyIndex1Stats.getTotalUses()); // NumOfValues should be reduced. for (int i = 0; i < 50; i++) { region.invalidate(Integer.toString(i)); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(450, keyIndex1Stats.getNumUpdates()); // Should not have any effect as invalidated values are destroyed for (int i = 0; i < 50; i++) { region.destroy(Integer.toString(i)); } assertEquals(4, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(450, keyIndex1Stats.getNumUpdates()); // NumOfKeys should get zero as all values are destroyed for (int i = 50; i < 100; i++) { region.destroy(Integer.toString(i)); } assertEquals(500, keyIndex1Stats.getNumUpdates()); assertEquals(0, keyIndex1Stats.getNumberOfKeys()); qs.removeIndex(keyIndex1); } /** * Test CompactRenageIndex IndexStatistics for keys, values, updates and uses. * * @throws Exception */ @Test public void testStatsForCompactRangeIndexBeforeRegionCreation() throws Exception { // Destroy region region.clear(); assertEquals(0, region.size()); Position.cnt = 0; keyIndex2 = (IndexProtocol) qs.createIndex("multiKeyIndex5", IndexType.FUNCTIONAL, "ID", "/portfolio "); // Recreate all entries in the region for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertTrue(keyIndex2 instanceof CompactRangeIndex); IndexStatistics keyIndex1Stats = keyIndex2.getStatistics(); // Initial stats test (keys, values & updates) assertEquals(100, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(100, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(100, keyIndex1Stats.getNumberOfKeys()); assertEquals(100, keyIndex1Stats.getNumberOfValues()); assertEquals(200, keyIndex1Stats.getNumUpdates()); // IndexUsed stats test String queryStr = "select * from /portfolio where ID > 0"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(50, keyIndex1Stats.getTotalUses()); // NumOfValues should be reduced. for (int i = 0; i < 50; i++) { region.invalidate(Integer.toString(i)); } assertEquals(50, keyIndex1Stats.getNumberOfKeys()); assertEquals(50, keyIndex1Stats.getNumberOfValues()); assertEquals(250, keyIndex1Stats.getNumUpdates()); for (int i = 0; i < 50; i++) { region.destroy(Integer.toString(i)); } assertEquals(50, keyIndex1Stats.getNumberOfKeys()); assertEquals(50, keyIndex1Stats.getNumberOfValues()); assertEquals(250, keyIndex1Stats.getNumUpdates()); // NumOfKeys should get zero as all values are destroyed for (int i = 50; i < 100; i++) { region.destroy(Integer.toString(i)); } assertEquals(300, keyIndex1Stats.getNumUpdates()); assertEquals(0, keyIndex1Stats.getNumberOfKeys()); qs.removeIndex(keyIndex2); } /** * Test MapRenageIndex IndexStatistics for keys, values, updates and uses. * * @throws Exception */ @Test public void testStatsForMapRangeIndexBeforeRegionCreation() throws Exception { // Destroy region IndexManager.TEST_RANGEINDEX_ONLY = true; region.clear(); assertEquals(0, region.size()); Position.cnt = 0; keyIndex3 = (IndexProtocol) qs.createIndex("multiKeyIndex6", IndexType.FUNCTIONAL, "positions['DELL', 'YHOO']", "/portfolio"); Object[] indexes = ((MapRangeIndex) keyIndex3).getRangeIndexHolderForTesting().values().toArray(); assertEquals(indexes.length, 0); // Recreate all entries in the region Position.cnt = 0; for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertTrue(keyIndex3 instanceof MapRangeIndex); indexes = ((MapRangeIndex) keyIndex3).getRangeIndexHolderForTesting().values().toArray(); assertTrue(indexes[0] instanceof RangeIndex); assertTrue(indexes[1] instanceof RangeIndex); IndexStatistics keyIndex1Stats = ((RangeIndex) indexes[0]).getStatistics(); IndexStatistics keyIndex2Stats = ((RangeIndex) indexes[1]).getStatistics(); IndexStatistics mapIndexStats = keyIndex3.getStatistics(); assertEquals(100, mapIndexStats.getNumberOfKeys()); assertEquals(100, mapIndexStats.getNumberOfValues()); assertEquals(100, mapIndexStats.getNumUpdates()); Position.cnt = 0; for (int i = 0; i < 100; i++) { region.put(Integer.toString(i), new Portfolio(i, i)); } assertEquals(100, mapIndexStats.getNumberOfKeys()); assertEquals(100, mapIndexStats.getNumberOfValues()); assertEquals(200, mapIndexStats.getNumUpdates()); String queryStr = "select * from /portfolio where positions['DELL'] != NULL OR positions['YHOO'] != NULL"; Query query = qs.newQuery(queryStr); for (int i = 0; i < 50; i++) { query.execute(); } assertEquals(100, mapIndexStats.getTotalUses()); for (int i = 0; i < 50; i++) { region.invalidate(Integer.toString(i)); } assertEquals(50, mapIndexStats.getNumberOfKeys()); assertEquals(50, mapIndexStats.getNumberOfValues()); assertEquals(300, mapIndexStats.getNumUpdates()); for (int i = 0; i < 50; i++) { region.destroy(Integer.toString(i)); } assertEquals(50, mapIndexStats.getNumberOfKeys()); assertEquals(50, mapIndexStats.getNumberOfValues()); assertEquals(300, mapIndexStats.getNumUpdates()); for (int i = 50; i < 100; i++) { region.destroy(Integer.toString(i)); } assertEquals(400, mapIndexStats.getNumUpdates()); assertEquals(0, mapIndexStats.getNumberOfKeys()); qs.removeIndex(keyIndex3); } @Test public void testCompactRangeIndexNumKeysStats() throws Exception { String regionName = "testCompactRegionIndexNumKeysStats_region"; Region region = CacheUtils.createRegion(regionName, Numbers.class); Index index = qs.createIndex("idIndexName", "r.max1", "/" + regionName + " r"); IndexStatistics stats = index.getStatistics(); // Add an object and check stats Numbers obj1 = new Numbers(1); obj1.max1 = 20; region.put(1, obj1); assertEquals(1, stats.getNumberOfValues()); assertEquals(1, stats.getNumberOfKeys()); // assertIndexDetailsEquals(1, stats.getNumberOfValues(20f)); assertEquals(1, stats.getNumUpdates()); // add a second object with the same index key Numbers obj2 = new Numbers(1); obj2.max1 = 20; region.put(2, obj2); assertEquals(2, stats.getNumberOfValues()); assertEquals(1, stats.getNumberOfKeys()); // assertIndexDetailsEquals(2, stats.getNumberOfValues(20f)); assertEquals(2, stats.getNumUpdates()); // remove the second object and check that keys are 1 region.remove(2); assertEquals(1, stats.getNumberOfValues()); assertEquals(1, stats.getNumberOfKeys()); // assertIndexDetailsEquals(1, stats.getNumberOfValues(20f)); assertEquals(3, stats.getNumUpdates()); // remove the first object and check that keys are 0 region.remove(1); assertEquals(0, stats.getNumberOfValues()); assertEquals(0, stats.getNumberOfKeys()); // assertIndexDetailsEquals(0, stats.getNumberOfValues(20f)); assertEquals(4, stats.getNumUpdates()); // add object with a different key and check results obj2.max1 = 21; region.put(3, obj2); assertEquals(1, stats.getNumberOfValues()); assertEquals(1, stats.getNumberOfKeys()); // assertIndexDetailsEquals(0, stats.getNumberOfValues(20f)); assertEquals(5, stats.getNumUpdates()); // add object with original key and check that num keys are 2 obj1.max1 = 20; region.put(1, obj1); assertEquals(2, stats.getNumberOfValues()); assertEquals(2, stats.getNumberOfKeys()); // assertIndexDetailsEquals(1, stats.getNumberOfValues(20f)); assertEquals(6, stats.getNumUpdates()); } @Test public void testReadLockCountStatsinRR() throws Exception { verifyReadLockCountStatsForCompactRangeIndex(false); verifyReadLockCountStatsForRangeIndex(false); } @Test public void testReadLockCountStatsinPR() throws Exception { verifyReadLockCountStatsForCompactRangeIndex(true); verifyReadLockCountStatsForRangeIndex(true); } public void verifyReadLockCountStatsForCompactRangeIndex(boolean isPr) throws Exception { QueryObserverImpl observer = new QueryObserverImpl(); QueryObserver old = QueryObserverHolder.setInstance(observer); String regionName = "exampleRegion"; String name = "/" + regionName; final Cache cache = CacheUtils.getCache(); Region r1 = null; if (isPr) { r1 = cache.createRegionFactory(RegionShortcut.PARTITION).create(regionName); } else { r1 = cache.createRegionFactory(RegionShortcut.REPLICATE).create(regionName); } QueryService qs = cache.getQueryService(); Index statusIndex = qs.createIndex("status", "status", name); assertEquals(cache.getQueryService().getIndexes().size(), 1); for (int i = 0; i < 3; i++) { r1.put("key-" + i, new Portfolio(i)); } String query = "select distinct * from " + name + " where status = 'active'"; final Query q = cache.getQueryService().newQuery(query); SelectResults sr = (SelectResults) q.execute(); assertEquals("Read locks should have been taken by the query ", 1, observer.readLockCount); assertEquals("Read lock count should have been released by the query ", 0, statusIndex.getStatistics().getReadLockCount()); QueryObserverHolder.setInstance(old); qs.removeIndexes(); } public void verifyReadLockCountStatsForRangeIndex(boolean isPr) throws Exception { QueryObserverImpl observer = new QueryObserverImpl(); QueryObserver old = QueryObserverHolder.setInstance(observer); String regionName = "exampleRegion"; String name = "/" + regionName; final Cache cache = CacheUtils.getCache(); Region r1 = cache.getRegion(regionName); QueryService qs = cache.getQueryService(); Index secIdIndex = qs.createIndex("secId", "pos.secId", name + " p, p.positions.values pos"); assertEquals(cache.getQueryService().getIndexes().size(), 1); for (int i = 0; i < 10; i++) { r1.put("key-" + i, new Portfolio(i)); } String query = "select distinct * from " + name + " p, p.positions.values pos where pos.secId = 'IBM' "; final Query q = cache.getQueryService().newQuery(query); SelectResults sr = (SelectResults) q.execute(); assertEquals("Read locks should have been taken by the query ", 1, observer.readLockCount); assertEquals("Read lock count should have been released by the query ", 0, secIdIndex.getStatistics().getReadLockCount()); QueryObserverHolder.setInstance(old); qs.removeIndexes(); } public static class QueryObserverImpl extends QueryObserverAdapter { int readLockCount = 0; public void beforeIndexLookup(Index index, int oper, Object key) { readLockCount = index.getStatistics().getReadLockCount(); } } }