diff --git a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/QueryServiceRegressionTest.java b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/QueryServiceRegressionTest.java index 2c2812384b7d..d2a509d3d49d 100644 --- a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/QueryServiceRegressionTest.java +++ b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/QueryServiceRegressionTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.Serializable; import java.util.ArrayList; @@ -339,7 +341,9 @@ public void testBugResultMismatch() throws Exception { SelectResults rs1 = (SelectResults) q1.execute(); SelectResults rs2 = (SelectResults) q2.execute(); - assertThatCode(() -> QueryUtils.union(rs1, rs2, null)).doesNotThrowAnyException(); + ExecutionContext context = mock(ExecutionContext.class); + when(context.getObserver()).thenReturn(new QueryObserverAdapter()); + assertThatCode(() -> QueryUtils.union(rs1, rs2, context)).doesNotThrowAnyException(); } /** diff --git a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/OrderByComparatorJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/OrderByComparatorJUnitTest.java index dbcd3e8b831e..fdeef18a2985 100644 --- a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/OrderByComparatorJUnitTest.java +++ b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/OrderByComparatorJUnitTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.lang.reflect.Field; import java.util.Collection; @@ -209,6 +211,8 @@ public void testCompareThrowsClassCastException() throws Exception { private OrderByComparator createComparator() throws Exception { StructTypeImpl objType = new StructTypeImpl(); - return new OrderByComparator(null, objType, null); + ExecutionContext context = mock(ExecutionContext.class); + when(context.getObserver()).thenReturn(new QueryObserverAdapter()); + return new OrderByComparator(null, objType, context); } } diff --git a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryObserverCallbacksTest.java b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryObserverCallbacksTest.java index 624267526f4d..98932af387c1 100644 --- a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryObserverCallbacksTest.java +++ b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryObserverCallbacksTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -41,6 +42,7 @@ import org.apache.geode.cache.query.data.Address; import org.apache.geode.cache.query.data.Employee; import org.apache.geode.cache.query.data.Portfolio; +import org.apache.geode.cache.query.internal.index.IndexManager; import org.apache.geode.test.junit.categories.OQLQueryTest; import org.apache.geode.test.junit.rules.ServerStarterRule; @@ -85,6 +87,7 @@ public void setUp() throws Exception { @After public void tearDown() { QueryObserverHolder.reset(); + IndexManager.TEST_RANGEINDEX_ONLY = false; } @SuppressWarnings("unchecked") @@ -243,6 +246,59 @@ public void beforeAggregationsAndGroupByShouldBeCalledForAggregateFunctions() th verify(myQueryObserver, times(queries.size())).beforeAggregationsAndGroupBy(any()); } + @Test + public void testBeforeAndAfterIterationEvaluateNoWhere() throws Exception { + Query query = queryService.newQuery( + "select count(*) from " + SEPARATOR + "portfolio p"); + + query.execute(); + verify(myQueryObserver, never()).beforeIterationEvaluation(any(), any()); + verify(myQueryObserver, never()).afterIterationEvaluation(any()); + } + + @Test + public void testBeforeAndAfterIterationEvaluateWithoutIndex() throws Exception { + Query query = queryService.newQuery( + "select count(*) from " + SEPARATOR + "portfolio p where p.isActive = true "); + + query.execute(); + verify(myQueryObserver, times(4)).beforeIterationEvaluation(any(), any()); + verify(myQueryObserver, times(4)).afterIterationEvaluation(any()); + } + + @Test + public void testBeforeAndAfterIterationEvaluateWithCompactRangeIndex() throws Exception { + Query query = queryService.newQuery( + "select count(*) from " + SEPARATOR + "portfolio p where p.isActive = true "); + queryService.createIndex("isActiveIndex", "isActive", SEPARATOR + "portfolio"); + + query.execute(); + verify(myQueryObserver, times(2)).beforeIterationEvaluation(any(), any()); + verify(myQueryObserver, times(2)).afterIterationEvaluation(any()); + assertThat(myQueryObserver.dbIndx[2] == myQueryObserver.usedIndx) + .as("Validate callback of Indexes").isTrue(); + assertThat(myQueryObserver.unusedIndx == myQueryObserver.dbIndx[0] + || myQueryObserver.unusedIndx == myQueryObserver.dbIndx[1]) + .as("Validate callback of Indexes").isTrue(); + } + + @Test + public void testBeforeAndAfterIterationEvaluateWithRangeIndex() throws Exception { + IndexManager.TEST_RANGEINDEX_ONLY = true; + Query query = queryService.newQuery( + "select count(*) from " + SEPARATOR + "portfolio p where p.description = 'XXXX' "); + queryService.createIndex("descriptionIndex", "description", SEPARATOR + "portfolio"); + + query.execute(); + verify(myQueryObserver, times(2)).beforeIterationEvaluation(any(), any()); + verify(myQueryObserver, times(2)).afterIterationEvaluation(any()); + assertThat(myQueryObserver.dbIndx[2] == myQueryObserver.usedIndx) + .as("Validate callback of Indexes").isTrue(); + assertThat(myQueryObserver.unusedIndx == myQueryObserver.dbIndx[0] + || myQueryObserver.unusedIndx == myQueryObserver.dbIndx[1]) + .as("Validate callback of Indexes").isTrue(); + } + private static class MyQueryObserverImpl extends QueryObserverAdapter { private int j = 0; private Index usedIndx = null; diff --git a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryTraceJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryTraceJUnitTest.java index c02b96a6af65..07e0e46fe9be 100644 --- a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryTraceJUnitTest.java +++ b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/QueryTraceJUnitTest.java @@ -15,6 +15,7 @@ package org.apache.geode.cache.query.internal; import static org.apache.geode.cache.Region.SEPARATOR; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -60,10 +61,12 @@ public class QueryTraceJUnitTest { @Before public void setUp() throws Exception { CacheUtils.startCache(); + DefaultQuery.testHook = new BeforeQueryExecutionHook(); } @After public void tearDown() throws Exception { + DefaultQuery.testHook = null; CacheUtils.closeCache(); } @@ -104,7 +107,11 @@ public void testTraceOnPartitionedRegionWithTracePrefix() throws Exception { assertTrue(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertTrue(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -141,7 +148,11 @@ public void testTraceOnLocalRegionWithTracePrefix() throws Exception { assertTrue(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertTrue(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -183,7 +194,11 @@ public void testNegTraceOnPartitionedRegionWithTracePrefix() throws Exception { assertFalse(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertFalse(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should not have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isNotInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -223,7 +238,11 @@ public void testNegTraceOnLocalRegionWithTracePrefix() throws Exception { assertFalse(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertFalse(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should not have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isNotInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -262,7 +281,11 @@ public void testTraceOnPartitionedRegionWithTracePrefixNoComments() throws Excep assertTrue(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertTrue(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -296,7 +319,11 @@ public void testTraceOnLocalRegionWithTracePrefixNoComments() throws Exception { assertTrue(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertTrue(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -331,7 +358,11 @@ public void testTraceOnPartitionedRegionWithSmallTracePrefixNoComments() throws assertTrue(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertTrue(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -366,7 +397,11 @@ public void testTraceOnLocalRegionWithSmallTracePrefixNoComments() throws Except assertTrue(((DefaultQuery) query).isTraced()); SelectResults results = (SelectResults) query.execute(); - assertTrue(QueryObserverHolder.getInstance() instanceof IndexTrackingQueryObserver); + + // The IndexTrackingObserver should have been set + BeforeQueryExecutionHook hook = (BeforeQueryExecutionHook) DefaultQuery.testHook; + assertThat(hook.getObserver()).isInstanceOf(IndexTrackingQueryObserver.class); + // The query should return all elements in region. assertEquals(region.size(), results.size()); QueryObserverHolder.reset(); @@ -438,4 +473,21 @@ public void testQueryFailLocalRegionWithSmallTracePrefixNoSpace() throws Excepti } } + private class BeforeQueryExecutionHook implements DefaultQuery.TestHook { + private QueryObserver observer = null; + + @Override + public void doTestHook(final SPOTS spot, final DefaultQuery _ignored, + final ExecutionContext executionContext) { + switch (spot) { + case BEFORE_QUERY_EXECUTION: + observer = executionContext.getObserver(); + break; + } + } + + public QueryObserver getObserver() { + return observer; + } + } } diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/AbstractGroupOrRangeJunction.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/AbstractGroupOrRangeJunction.java index f0090ae9f11e..6b97a51aa1b3 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/AbstractGroupOrRangeJunction.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/AbstractGroupOrRangeJunction.java @@ -383,7 +383,7 @@ private SelectResults auxIterateEvaluate(CompiledValue operand, ExecutionContext resultSet = QueryUtils.createResultCollection(context, elementType); } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); try { observer.startIteration(intermediateResults, operand); Iterator iResultsIter = intermediateResults.iterator(); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/AllGroupJunction.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/AllGroupJunction.java index 54cde5b0c964..dc64f83f108f 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/AllGroupJunction.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/AllGroupJunction.java @@ -169,7 +169,7 @@ private SelectResults evaluateAndJunction(ExecutionContext context) iterOperandsToSend = new CompiledJunction(cv, this.operator); } } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); observer.beforeCartesianOfGroupJunctionsInAnAllGroupJunctionOfType_AND(results); resultsSet = QueryUtils.cartesian(results, itrsForResultFields, expansionList, finalList, context, iterOperandsToSend); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledComparison.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledComparison.java index 17ed5b16ffb6..497bb38b7536 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledComparison.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledComparison.java @@ -373,7 +373,7 @@ private SelectResults singleBaseCollectionFilterEvaluate(ExecutionContext contex // before the index lookup int op = reflectOnOperator(indexInfo._key()); // actual index lookup - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); List projAttrib = null; /* * Asif : First obtain the match level of index resultset. If the match level happens to be zero @@ -535,7 +535,7 @@ private SelectResults doubleBaseCollectionFilterEvaluate(ExecutionContext contex // each of the // one dimensional array can be either genuine result object or StructImpl // object. - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); context.cachePut(CompiledValue.INDEX_INFO, indxInfo); /* * Asif : If the independent Group of iterators passed is not null or the independent Group of diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledGroupBySelect.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledGroupBySelect.java index 951c867d350a..f8516443a8ea 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledGroupBySelect.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledGroupBySelect.java @@ -155,7 +155,7 @@ private void mapOriginalOrderByColumns(ExecutionContext context) public SelectResults evaluate(ExecutionContext context) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { SelectResults selectResults = super.evaluate(context); - QueryObserverHolder.getInstance().beforeAggregationsAndGroupBy(selectResults); + context.getObserver().beforeAggregationsAndGroupBy(selectResults); return this.applyAggregateAndGroupBy(selectResults, context); } diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledIn.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledIn.java index b7e28b1b25e3..b982c658325e 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledIn.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledIn.java @@ -524,7 +524,7 @@ SelectResults singleBaseCollectionFilterEvaluate(ExecutionContext context, } } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); try { Object evalColln = evaluateColln(context); observer.beforeIndexLookup(indexInfo._index, TOK_EQ, evalColln); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledJunction.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledJunction.java index fb0425fcd8aa..28cf9afd62fa 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledJunction.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledJunction.java @@ -368,7 +368,7 @@ SelectResults auxIterateEvaluate(CompiledValue operand, ExecutionContext context } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); try { observer.startIteration(intermediateResults, operand); Iterator iResultsIter = intermediateResults.iterator(); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledSelect.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledSelect.java index 694c50ed77ab..956be369b96d 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledSelect.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledSelect.java @@ -537,7 +537,7 @@ public SelectResults evaluate(ExecutionContext context) throws FunctionDomainExc result = ((Filter) this.whereClause).filterEvaluate(context, null); if (!(context.cacheGet(RESULT_TYPE) instanceof Boolean)) { - QueryObserverHolder.getInstance() + context.getObserver() .beforeApplyingProjectionOnFilterEvaluatedResults(result); result = applyProjectionOnCollection(result, context, !needsTopLevelOrdering); } @@ -691,7 +691,7 @@ private SelectResults doIterationEvaluate(ExecutionContext context, boolean eval for (Iterator itr = tmpResults.iterator(); itr.hasNext();) { Object currObj = itr.next(); rIter.setCurrent(currObj); - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); observer.beforeIterationEvaluation(rIter, currObj); applyProjectionAndAddToResultSet(context, results, this.orderByAttrs == null); } @@ -773,7 +773,7 @@ private int doNestedIterations(int level, SelectResults results, ExecutionContex boolean addToResults = true; if (evaluateWhereClause) { Object result = this.whereClause.evaluate(context); - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); observer.afterIterationEvaluation(result); if (result == null) { addToResults = false; @@ -839,7 +839,7 @@ private int doNestedIterations(int level, SelectResults results, ExecutionContex Object currObj = aSr; rIter.setCurrent(currObj); - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); observer.beforeIterationEvaluation(rIter, currObj); numElementsInResult = doNestedIterations(level + 1, results, context, evaluateWhereClause, numElementsInResult); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledUndefined.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledUndefined.java index 6f8d9e6d4fb5..677c2549cfba 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledUndefined.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledUndefined.java @@ -100,7 +100,7 @@ public SelectResults filterEvaluate(ExecutionContext context, SelectResults inte } int op = _is_defined ? TOK_NE : TOK_EQ; Object key = QueryService.UNDEFINED; - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); try { observer.beforeIndexLookup(idxInfo[0]._index, op, key); context.cachePut(CompiledValue.INDEX_INFO, idxInfo[0]); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompositeGroupJunction.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompositeGroupJunction.java index 4e77d2ebd235..53b616c9d286 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompositeGroupJunction.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompositeGroupJunction.java @@ -309,7 +309,7 @@ private SelectResults evaluateAndJunction(ExecutionContext context) } // Do the cartesian of the different group junction results. // TODO:Asif Remove the time - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); observer.beforeCartesianOfGroupJunctionsInCompositeGroupJunctionOfType_AND(results); SelectResults grpCartRs = QueryUtils.cartesian(results, itrsForResultFields, expansionList, finalList, context, iterOp); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java index 5003e20b3575..1f2704debab1 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java @@ -134,6 +134,8 @@ public class DefaultQuery implements Query { private static final ThreadLocal>> pdxClassToFieldsMap = ThreadLocal.withInitial(HashMap::new); + private QueryObserver oldQueryObserver = null; + static Map> getPdxClasstofieldsmap() { return pdxClassToFieldsMap.get(); } @@ -231,7 +233,7 @@ public Object execute(Object[] params) throws FunctionDomainException, TypeMisma try { // Setting the readSerialized flag for local queries this.cache.setPdxReadSerializedOverride(true); - indexObserver = this.startTrace(); + indexObserver = this.startTrace(context); if (qe != null) { if (DefaultQuery.testHook != null) { DefaultQuery.testHook.doTestHook(DefaultQuery.TestHook.SPOTS.BEFORE_QUERY_EXECUTION, @@ -335,7 +337,7 @@ private Object executeOnServer(Object[] parameters) { public Object executeUsingContext(ExecutionContext context) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); long startTime = statisticsClock.getTime(); TXStateProxy tx = ((TXManagerImpl) this.cache.getCacheTransactionManager()).pauseTransaction(); try { @@ -742,12 +744,12 @@ public Object execute(RegionFunctionContext context, Object[] params) Object result = null; try { - indexObserver = startTrace(); + final ExecutionContext executionContext = new ExecutionContext(null, cache); + indexObserver = startTrace(executionContext); if (qe != null) { LocalDataSet localDataSet = (LocalDataSet) PartitionRegionHelper.getLocalDataForContext(context); Set buckets = localDataSet.getBucketSet(); - final ExecutionContext executionContext = new ExecutionContext(null, cache); result = qe.executeQuery(this, executionContext, params, buckets); return result; } else { @@ -770,7 +772,7 @@ public boolean isQueryWithFunctionContext() { return this.isQueryWithFunctionContext; } - public QueryObserver startTrace() { + public QueryObserver startTrace(ExecutionContext context) { QueryObserver queryObserver = null; if (this.traceOn && this.cache != null) { @@ -779,7 +781,8 @@ public QueryObserver startTrace() { queryObserver = qo; } else if (!QueryObserverHolder.hasObserver()) { queryObserver = new IndexTrackingQueryObserver(); - QueryObserverHolder.setInstance(queryObserver); + oldQueryObserver = QueryObserverHolder.setInstance(queryObserver); + context.setObserver(queryObserver); } else { queryObserver = qo; } @@ -800,6 +803,9 @@ public void endTrace(QueryObserver indexObserver, long startTime, Object result) DefaultQuery.getLogMessage(indexObserver, startTime, resultSize, this.queryString); logger.info(queryVerboseMsg); } + if (oldQueryObserver != null) { + QueryObserverHolder.setInstance(oldQueryObserver); + } } public void endTrace(QueryObserver indexObserver, long startTime, Collection result) { @@ -816,6 +822,9 @@ public void endTrace(QueryObserver indexObserver, long startTime, Collection _instance = + new AtomicReference<>(NO_OBSERVER); /** * Set the given observer to be notified of query events. Returns the current observer. */ public static QueryObserver setInstance(QueryObserver observer) { Support.assertArg(observer != null, "setInstance expects a non-null argument!"); - QueryObserver oldObserver = _instance; - _instance = observer; - return oldObserver; + return _instance.getAndSet(observer); } public static boolean hasObserver() { - return _instance != NO_OBSERVER; + return _instance.get() != NO_OBSERVER; } /** Return the current QueryObserver instance */ public static QueryObserver getInstance() { - return _instance; + return _instance.get(); } /** * Only for test purposes. */ public static void reset() { - _instance = NO_OBSERVER; + _instance.set(NO_OBSERVER); } } diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java index 70e956c55ae8..8f4c614c0048 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java @@ -63,8 +63,9 @@ public class QueryUtils { * c1 or c2. */ public static SelectResults intersection(SelectResults c1, SelectResults c2, - ExecutionContext contextOrNull) { - QueryObserverHolder.getInstance().invokedQueryUtilsIntersection(c1, c2); + ExecutionContext context) { + QueryObserver observer = context.getObserver(); + observer.invokedQueryUtilsIntersection(c1, c2); assertCompatible(c1, c2); if (c1.isEmpty()) { return c1; @@ -74,9 +75,9 @@ public static SelectResults intersection(SelectResults c1, SelectResults c2, } // iterate on the smallest one if (c1.size() < c2.size()) { - return sizeSortedIntersection(c1, c2, contextOrNull); + return sizeSortedIntersection(c1, c2, context); } else { - return sizeSortedIntersection(c2, c1, contextOrNull); + return sizeSortedIntersection(c2, c1, context); } } @@ -85,14 +86,15 @@ public static SelectResults intersection(SelectResults c1, SelectResults c2, * c2. */ public static SelectResults union(SelectResults c1, SelectResults c2, - ExecutionContext contextOrNull) { - QueryObserverHolder.getInstance().invokedQueryUtilsUnion(c1, c2); + ExecutionContext context) { + QueryObserver observer = context.getObserver(); + observer.invokedQueryUtilsUnion(c1, c2); assertCompatible(c1, c2); // iterate on the smallest one if (c1.size() < c2.size()) { - return sizeSortedUnion(c1, c2, contextOrNull); + return sizeSortedUnion(c1, c2, context); } else { - return sizeSortedUnion(c2, c1, contextOrNull); + return sizeSortedUnion(c2, c1, context); } } @@ -181,7 +183,7 @@ private static boolean isBag(SelectResults coln) { // the number of occurrences in the intersection equal to the // minimum number between the two bags private static SelectResults sizeSortedIntersection(SelectResults small, SelectResults large, - ExecutionContext contextOrNull) { + ExecutionContext context) { // if one is a set and one is a bag, then treat the set like a bag (and return a bag) boolean smallModifiable = small.isModifiable() && (isBag(small) || !isBag(large)); boolean largeModifiable = large.isModifiable() && (isBag(large) || !isBag(small)); @@ -222,13 +224,8 @@ private static SelectResults sizeSortedIntersection(SelectResults small, SelectR } } - SelectResults rs; - if (contextOrNull != null) { - rs = contextOrNull.isDistinct() ? new ResultsSet(small) - : new ResultsBag(small, contextOrNull.getCachePerfStats()); - } else { - rs = new ResultsBag(small, null); - } + SelectResults rs = context.isDistinct() ? new ResultsSet(small) + : new ResultsBag(small, context.getCachePerfStats()); for (Iterator itr = rs.iterator(); itr.hasNext();) { Object element = itr.next(); @@ -246,7 +243,7 @@ private static SelectResults sizeSortedIntersection(SelectResults small, SelectR // Is this Ok? There may be tuples which are actually common to both set so // union in such cases should not increase count. right.? private static SelectResults sizeSortedUnion(SelectResults small, SelectResults large, - ExecutionContext contextOrNull) { + ExecutionContext context) { // if one is a set and one is a bag, then treat the set like a bag (and return a bag) boolean smallModifiable = small.isModifiable() && (isBag(small) || !isBag(large)); boolean largeModifiable = large.isModifiable() && (isBag(large) || !isBag(small)); @@ -276,13 +273,8 @@ private static SelectResults sizeSortedUnion(SelectResults small, SelectResults // didn't succeed because small is actually unmodifiable } } - SelectResults rs; - if (contextOrNull != null) { - rs = contextOrNull.isDistinct() ? new ResultsSet(large) - : new ResultsBag(large, contextOrNull.getCachePerfStats()); - } else { - rs = new ResultsBag(large, null); - } + SelectResults rs = context.isDistinct() ? new ResultsSet(large) + : new ResultsBag(large, context.getCachePerfStats()); for (Iterator itr = small.iterator(); itr.hasNext();) { Object element = itr.next(); @@ -1033,7 +1025,7 @@ static SelectResults getConditionedIndexResults(SelectResults indexResults, Inde } newExpList.addAll(ich.expansionList); ich.expansionList = newExpList; - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); try { observer.beforeCutDownAndExpansionOfSingleIndexResult(indexInfo._index, indexResults); indexResults = @@ -1046,7 +1038,7 @@ static SelectResults getConditionedIndexResults(SelectResults indexResults, Inde IndexConditioningHelper ich = new IndexConditioningHelper(indexInfo, context, indexFieldsSize, completeExpansion, iterOperands, grpIndpndntItr != null ? grpIndpndntItr[0] : null); if (ich.shufflingNeeded) { - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); try { observer.beforeCutDownAndExpansionOfSingleIndexResult(indexInfo._index, indexResults); indexResults = QueryUtils.cutDownAndExpandIndexResults(indexResults, @@ -1181,7 +1173,7 @@ static SelectResults getRelationshipIndexResultsMergedWithIntermediateResults( singleUsableICH = null; } } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); if (noOfIndexesToUse == 2) { List data = null; try { @@ -1249,7 +1241,7 @@ static SelectResults getRelationshipIndexResultsMergedWithIntermediateResults( new IndexCutDownExpansionHelper(ich2.checkList, context)}; ListIterator expansionListIterator = totalExpList.listIterator(); if (dataItr.hasNext()) { - observer = QueryObserverHolder.getInstance(); + observer = context.getObserver(); try { observer.beforeMergeJoinOfDoubleIndexResults(indxInfo[0]._index, indxInfo[1]._index, data); @@ -1333,7 +1325,7 @@ static SelectResults getRelationshipIndexResultsMergedWithIntermediateResults( } // iterate over the intermediate structset Iterator intrmdtRsItr = intermediateResults.iterator(); - observer = QueryObserverHolder.getInstance(); + observer = context.getObserver(); try { observer.beforeIndexLookup(singleUsblIndex, OQLLexerTokenTypes.TOK_EQ, null); observer.beforeIterJoinOfSingleIndexResults(singleUsblIndex, nonUsableICH.indxInfo._index); @@ -1501,7 +1493,7 @@ static SelectResults getConditionedRelationshipIndexResultsExpandedToTopOrCGJLev new IndexCutDownExpansionHelper(ich2.checkList, context)}; ListIterator expansionListIterator = totalExpList.listIterator(); if (dataItr.hasNext()) { - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); try { observer.beforeMergeJoinOfDoubleIndexResults(ich1.indxInfo._index, ich2.indxInfo._index, data); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/RangeJunction.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/RangeJunction.java index e879166d1706..8db88154635c 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/RangeJunction.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/RangeJunction.java @@ -751,7 +751,7 @@ public SelectResults filterEvaluate(ExecutionContext context, SelectResults iter indexFieldsSize = 1; } // actual index lookup - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); /* * Asif : First obtain the match level of index resultset. If the match level happens to be * zero , this implies that we just have to change the StructType ( again if only the Index @@ -945,7 +945,7 @@ public SelectResults filterEvaluate(ExecutionContext context, SelectResults iter indexFieldsSize = 1; } // actual index lookup - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); /* * Asif : First obtain the match level of index resultset. If the match level happens to be * zero , this implies that we just have to change the StructType ( again if only the Index @@ -1086,7 +1086,7 @@ public SelectResults filterEvaluate(ExecutionContext context, SelectResults iter // Shobhit: Limit can not be applied at index level for RangeJunction as // other conditions are applied after coming out of index query method. context.cachePut(CompiledValue.CAN_APPLY_LIMIT_AT_INDEX, Boolean.FALSE); - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); /* * Asif : First obtain the match level of index resultset. If the match level happens to be * zero , this implies that we just have to change the StructType ( again if only the Index diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/AbstractIndex.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/AbstractIndex.java index 79676954972d..aef2d0332923 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/AbstractIndex.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/AbstractIndex.java @@ -53,6 +53,7 @@ import org.apache.geode.cache.query.internal.IndexInfo; import org.apache.geode.cache.query.internal.QRegion; import org.apache.geode.cache.query.internal.QueryMonitor; +import org.apache.geode.cache.query.internal.QueryObserver; import org.apache.geode.cache.query.internal.QueryUtils; import org.apache.geode.cache.query.internal.RuntimeIterator; import org.apache.geode.cache.query.internal.StructFields; @@ -1802,6 +1803,7 @@ void addValuesToCollection(Collection result, CompiledValue iterOp, RuntimeItera return; } + QueryObserver observer = context.getObserver(); for (Object o : this.map.entrySet()) { // Check if query execution on this thread is canceled. QueryMonitor.throwExceptionIfQueryOnCurrentThreadIsCanceled(); @@ -1822,14 +1824,8 @@ void addValuesToCollection(Collection result, CompiledValue iterOp, RuntimeItera synchronized (value) { for (Object o1 : ((Iterable) value)) { boolean ok = true; - if (reUpdateInProgress) { - // Compare the value in index with value in RegionEntry. - ok = verifyEntryAndIndexValue(entry, o1, context); - } - if (ok && runtimeItr != null) { - runtimeItr.setCurrent(o1); - ok = QueryUtils.applyCondition(iterOp, context); - } + ok = applyCondition(iterOp, runtimeItr, context, observer, o1, entry, + reUpdateInProgress, ok); if (ok) { applyProjection(projAttrib, context, result, o1, intermediateResults, isIntersection); @@ -1842,14 +1838,8 @@ void addValuesToCollection(Collection result, CompiledValue iterOp, RuntimeItera } else { for (Object o1 : ((Iterable) value)) { boolean ok = true; - if (reUpdateInProgress) { - // Compare the value in index with value in RegionEntry. - ok = verifyEntryAndIndexValue(entry, o1, context); - } - if (ok && runtimeItr != null) { - runtimeItr.setCurrent(o1); - ok = QueryUtils.applyCondition(iterOp, context); - } + ok = applyCondition(iterOp, runtimeItr, context, observer, o1, entry, + reUpdateInProgress, ok); if (ok) { applyProjection(projAttrib, context, result, o1, intermediateResults, isIntersection); @@ -1861,14 +1851,8 @@ void addValuesToCollection(Collection result, CompiledValue iterOp, RuntimeItera } } else { boolean ok = true; - if (reUpdateInProgress) { - // Compare the value in index with in RegionEntry. - ok = verifyEntryAndIndexValue(entry, value, context); - } - if (ok && runtimeItr != null) { - runtimeItr.setCurrent(value); - ok = QueryUtils.applyCondition(iterOp, context); - } + ok = applyCondition(iterOp, runtimeItr, context, observer, value, entry, + reUpdateInProgress, ok); if (ok) { if (context.isCqQueryContext()) { result.add(new CqEntry(((RegionEntry) e.getKey()).getKey(), value)); @@ -1882,6 +1866,26 @@ void addValuesToCollection(Collection result, CompiledValue iterOp, RuntimeItera } } + private boolean applyCondition(CompiledValue iterOp, RuntimeIterator runtimeItr, + ExecutionContext context, QueryObserver observer, Object value, RegionEntry entry, + boolean reUpdateInProgress, boolean ok) throws FunctionDomainException, + TypeMismatchException, NameResolutionException, QueryInvocationTargetException { + if (reUpdateInProgress) { + // Compare the value in index with in RegionEntry. + ok = verifyEntryAndIndexValue(entry, value, context); + } + try { + if (ok && runtimeItr != null) { + runtimeItr.setCurrent(value); + observer.beforeIterationEvaluation(iterOp, value); + ok = QueryUtils.applyCondition(iterOp, context); + } + } finally { + observer.afterIterationEvaluation(ok); + } + return ok; + } + private boolean verifyLimit(Collection result, int limit, ExecutionContext context) { if (limit > 0) { if (!context.isDistinct()) { diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/CompactRangeIndex.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/CompactRangeIndex.java index 632ea0c4f95b..91d9b32e2d5c 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/CompactRangeIndex.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/CompactRangeIndex.java @@ -746,7 +746,13 @@ private void addToResultsFromEntries(Object lowerBoundKey, Object upperBoundKey, throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer; + if (context != null) { + observer = context.getObserver(); + } else { + observer = QueryObserverHolder.getInstance(); + } + boolean limitApplied = false; if (entriesIter == null || (limitApplied = verifyLimit(result, limit))) { if (limitApplied) { @@ -799,13 +805,7 @@ private void addToResultsFromEntries(Object lowerBoundKey, Object upperBoundKey, value = iterator.next(); if (value != null) { boolean ok = true; - - if (runtimeItr != null) { - runtimeItr.setCurrent(value); - } - if (ok && runtimeItr != null && iterOps != null) { - ok = QueryUtils.applyCondition(iterOps, context); - } + ok = applyCondition(iterOps, runtimeItr, context, observer, value, ok); if (ok) { applyCqOrProjection(projAttrib, context, result, value, intermediateResults, isIntersection, indexEntry.getDeserializedRegionKey()); @@ -834,12 +834,7 @@ private void addToResultsFromEntries(Object lowerBoundKey, Object upperBoundKey, ok = evaluateEntry((IndexInfo) indexInfo, context, null); } - if (runtimeItr != null) { - runtimeItr.setCurrent(value); - } - if (ok && runtimeItr != null && iterOps != null) { - ok = QueryUtils.applyCondition(iterOps, context); - } + ok = applyCondition(iterOps, runtimeItr, context, observer, value, ok); if (ok) { if (context != null && context.isCqQueryContext()) { result.add(new CqEntry(indexEntry.getDeserializedRegionKey(), value)); @@ -863,6 +858,24 @@ private void addToResultsFromEntries(Object lowerBoundKey, Object upperBoundKey, } } + private boolean applyCondition(CompiledValue iterOps, RuntimeIterator runtimeItr, + ExecutionContext context, QueryObserver observer, Object value, boolean ok) + throws FunctionDomainException, TypeMismatchException, NameResolutionException, + QueryInvocationTargetException { + if (runtimeItr != null) { + runtimeItr.setCurrent(value); + } + try { + if (ok && runtimeItr != null) { + observer.beforeIterationEvaluation(iterOps, value); + ok = QueryUtils.applyCondition(iterOps, context); + } + } finally { + observer.afterIterationEvaluation(ok); + } + return ok; + } + public List expandValue(ExecutionContext context, Object lowerBoundKey, Object upperBoundKey, int lowerBoundOperator, int upperBoundOperator, Object value) { try { diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/HashIndex.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/HashIndex.java index 1bc2591ded29..d1fb2dc14684 100755 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/HashIndex.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/HashIndex.java @@ -55,7 +55,6 @@ import org.apache.geode.cache.query.internal.QRegion; import org.apache.geode.cache.query.internal.QueryMonitor; import org.apache.geode.cache.query.internal.QueryObserver; -import org.apache.geode.cache.query.internal.QueryObserverHolder; import org.apache.geode.cache.query.internal.QueryUtils; import org.apache.geode.cache.query.internal.RuntimeIterator; import org.apache.geode.cache.query.internal.Support; @@ -598,7 +597,7 @@ private void addToResultsFromEntries(Iterator entriesIter, Collection result, SelectResults intermediateResults, boolean isIntersection, int limit, Set keysToRemove, boolean applyOrderBy, boolean asc, long iteratorCreationTime) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); if (result == null || limit != -1 && result.size() == limit) { return; } diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/PrimaryKeyIndex.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/PrimaryKeyIndex.java index 6edcc591f9bd..4e0b42570121 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/PrimaryKeyIndex.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/PrimaryKeyIndex.java @@ -35,7 +35,6 @@ import org.apache.geode.cache.query.internal.ExecutionContext; import org.apache.geode.cache.query.internal.QueryMonitor; import org.apache.geode.cache.query.internal.QueryObserver; -import org.apache.geode.cache.query.internal.QueryObserverHolder; import org.apache.geode.cache.query.internal.QueryUtils; import org.apache.geode.cache.query.internal.RuntimeIterator; import org.apache.geode.cache.query.internal.Support; @@ -106,7 +105,7 @@ void lockedQuery(Object key, int operator, Collection results, Set keysToRemove, if (applyLimit != null && applyLimit) { limit = (Integer) context.cacheGet(CompiledValue.RESULT_LIMIT); } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); if (limit != -1 && results.size() == limit) { observer.limitAppliedAtIndexLevel(this, limit, results); return; @@ -177,7 +176,7 @@ void lockedQuery(Object key, int operator, Collection results, CompiledValue ite SelectResults intermediateResults, boolean isIntersection) throws TypeMismatchException, FunctionDomainException, NameResolutionException, QueryInvocationTargetException { - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); int limit = -1; Boolean applyLimit = (Boolean) context.cacheGet(CompiledValue.CAN_APPLY_LIMIT_AT_INDEX); diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/RangeIndex.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/RangeIndex.java index 5970ec89ee83..c2ac9c3b48a8 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/RangeIndex.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/index/RangeIndex.java @@ -46,7 +46,6 @@ import org.apache.geode.cache.query.internal.CompiledValue; import org.apache.geode.cache.query.internal.ExecutionContext; import org.apache.geode.cache.query.internal.QueryObserver; -import org.apache.geode.cache.query.internal.QueryObserverHolder; import org.apache.geode.cache.query.internal.RuntimeIterator; import org.apache.geode.cache.query.internal.index.IndexManager.TestHook; import org.apache.geode.cache.query.internal.index.IndexStore.IndexStoreEntry; @@ -1001,7 +1000,7 @@ private void addValuesToResult(Object entriesMap, Collection result, Set keysToR if (entriesMap == null || result == null) { return; } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); if (verifyLimit(result, limit)) { observer.limitAppliedAtIndexLevel(this, limit, result); return; @@ -1058,7 +1057,7 @@ private void addValuesToResultSingleKeyToRemove(Object entriesMap, Collection re if (entriesMap == null || result == null) { return; } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); if (verifyLimit(result, limit)) { observer.limitAppliedAtIndexLevel(this, limit, result); return; @@ -1091,14 +1090,14 @@ private void addValuesToResult(Object entriesMap, Collection result, Object keyT boolean limitApplied = false; if (entriesMap == null || result == null) { if (verifyLimit(result, limit)) { - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); if (observer != null) { observer.limitAppliedAtIndexLevel(this, limit, result); } } return; } - QueryObserver observer = QueryObserverHolder.getInstance(); + QueryObserver observer = context.getObserver(); if (entriesMap instanceof SortedMap) { Iterator entriesIter = ((Map) entriesMap).entrySet().iterator(); Map.Entry entry = null; diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalDataSet.java b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalDataSet.java index c2025b630c8f..b02bd9c582b7 100755 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalDataSet.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalDataSet.java @@ -188,7 +188,7 @@ public Object executeQuery(DefaultQuery query, startTime = NanoTimer.getTime(); } - QueryObserver indexObserver = query.startTrace(); + QueryObserver indexObserver = query.startTrace(executionContext); try { result = this.proxy.executeQuery(query, executionContext, parameters, buckets); diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/QueryMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/QueryMessage.java index 108a65d5cc6e..b271da4b2d8a 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/QueryMessage.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/QueryMessage.java @@ -180,7 +180,7 @@ protected boolean operateOnPartitionedRegion(ClusterDistributionManager dm, Part pr.getCache().setPdxReadSerializedOverride(true); // In case of "select *" queries we can keep the results in serialized form and send query.setRemoteQuery(true); - QueryObserver indexObserver = query.startTrace(); + QueryObserver indexObserver = query.startTrace(executionContext); boolean isQueryTraced = false; List queryTraceList = null; diff --git a/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledInJUnitTest.java b/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledInJUnitTest.java index 90037309c8a0..6b896dc30c61 100644 --- a/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledInJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledInJUnitTest.java @@ -45,6 +45,7 @@ public void setup() { context = mock(ExecutionContext.class); elm = mock(CompiledValue.class); colln = mock(CompiledValue.class); + when(context.getObserver()).thenReturn(new QueryObserverAdapter()); } @Test diff --git a/geode-core/src/test/java/org/apache/geode/cache/query/internal/StructSetJUnitTest.java b/geode-core/src/test/java/org/apache/geode/cache/query/internal/StructSetJUnitTest.java index ef489cdd0d18..bc10f2df8b1c 100644 --- a/geode-core/src/test/java/org/apache/geode/cache/query/internal/StructSetJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/cache/query/internal/StructSetJUnitTest.java @@ -21,6 +21,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.util.Iterator; @@ -60,7 +62,9 @@ public void testIntersectionAndRetainAll() { assertTrue(!set1.retainAll(set2)); assertEquals(2, set1.size()); assertEquals(2, set2.size()); - SelectResults sr = QueryUtils.intersection(set1, set2, null); + ExecutionContext context = mock(ExecutionContext.class); + when(context.getObserver()).thenReturn(new QueryObserverAdapter()); + SelectResults sr = QueryUtils.intersection(set1, set2, context); assertEquals(2, sr.size()); } } diff --git a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java index 18d0ca22a4f9..f5ba23d112b8 100644 --- a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java +++ b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java @@ -205,12 +205,13 @@ private DataCommandResult select(InternalCache cache, Object principal, String q Query query = qs.newQuery(queryString); DefaultQuery tracedQuery = (DefaultQuery) query; WrappedIndexTrackingQueryObserver queryObserver = null; + QueryObserver oldQueryObserver = null; String queryVerboseMsg = null; long startTime = -1; if (tracedQuery.isTraced()) { startTime = NanoTimer.getTime(); queryObserver = new WrappedIndexTrackingQueryObserver(); - QueryObserverHolder.setInstance(queryObserver); + oldQueryObserver = QueryObserverHolder.setInstance(queryObserver); } List list = new ArrayList<>(); @@ -237,6 +238,9 @@ private DataCommandResult select(InternalCache cache, Object principal, String q if (queryObserver != null) { QueryObserverHolder.reset(); } + if (tracedQuery.isTraced()) { + QueryObserverHolder.setInstance(oldQueryObserver); + } } } diff --git a/geode-junit/src/main/java/org/apache/geode/cache/query/functional/StructSetOrResultsSet.java b/geode-junit/src/main/java/org/apache/geode/cache/query/functional/StructSetOrResultsSet.java index b328cfe7d288..417fab24ca5b 100755 --- a/geode-junit/src/main/java/org/apache/geode/cache/query/functional/StructSetOrResultsSet.java +++ b/geode-junit/src/main/java/org/apache/geode/cache/query/functional/StructSetOrResultsSet.java @@ -49,7 +49,6 @@ import org.apache.geode.cache.query.internal.ExecutionContext; import org.apache.geode.cache.query.internal.OrderByComparator; import org.apache.geode.cache.query.internal.QueryObserverAdapter; -import org.apache.geode.cache.query.internal.QueryObserverHolder; import org.apache.geode.cache.query.types.ObjectType; import org.apache.geode.internal.util.ArrayUtils; @@ -237,11 +236,10 @@ public int compare(Struct o1, Struct o2) { } final Comparator secondLevelComparator = baseComparator; final Comparator finalComparator = new Comparator() { - @Override public int compare(Object o1, Object o2) { final boolean[] orderByColsEqual = new boolean[] {false}; - QueryObserverHolder.setInstance(new QueryObserverAdapter() { + context.setObserver(new QueryObserverAdapter() { @Override public void orderByColumnsEqual() { orderByColsEqual[0] = true;