Repository: geode Updated Branches: refs/heads/feature/GEODE-2825 [created] fb01b37ce
GEODE-2825: Lucene query waits for defined index to be created * If an index is in a defined state but not yet created, the query will now wait until the index is created or no longer defined. Instead of throwing an exception and possibly getting a stack overflow Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/fb01b37c Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/fb01b37c Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/fb01b37c Branch: refs/heads/feature/GEODE-2825 Commit: fb01b37ce8b7acda184daabc40de969a15c933c4 Parents: 42a7d5f Author: Jason Huynh <[email protected]> Authored: Wed Apr 26 11:13:53 2017 -0700 Committer: Jason Huynh <[email protected]> Committed: Wed Apr 26 11:15:18 2017 -0700 ---------------------------------------------------------------------- .../distributed/LuceneQueryFunction.java | 24 ++++--------- .../LuceneQueryFunctionJUnitTest.java | 36 ++++++++++++++++---- 2 files changed, 37 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/fb01b37c/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java index 9ad69ac..b429510 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java @@ -133,29 +133,18 @@ public class LuceneQueryFunction implements Function, InternalEntity { try { index = (LuceneIndexImpl) service.getIndex(searchContext.getIndexName(), region.getFullPath()); - if (index == null && service instanceof LuceneServiceImpl) { - if (((LuceneServiceImpl) service).getDefinedIndex(searchContext.getIndexName(), - region.getFullPath()) != null) { - // The node may be in the process of recovering, where we have the index defined but yet - // to be recovered - // If we retry fast enough, we could get a stack overflow based on the way function - // execution is currently written - // Instead we will add an artificial sleep to slow down the retry at this point - // Hopefully in the future, the function execution would retry without adding to the stack - // and this can be removed - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - throw new InternalFunctionInvocationTargetException( - "Defined Lucene Index has not been created"); + if (index == null) { + while (service instanceof LuceneServiceImpl && (((LuceneServiceImpl) service) + .getDefinedIndex(searchContext.getIndexName(), region.getFullPath()) != null)) { } + index = + (LuceneIndexImpl) service.getIndex(searchContext.getIndexName(), region.getFullPath()); } } catch (CacheClosedException e) { throw new InternalFunctionInvocationTargetException( "Cache is closed when attempting to retrieve index:" + region.getFullPath(), e); } + return index; } @@ -181,3 +170,4 @@ public class LuceneQueryFunction implements Function, InternalEntity { return true; } } + http://git-wip-us.apache.org/repos/asf/geode/blob/fb01b37c/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunctionJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunctionJUnitTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunctionJUnitTest.java index 6690850..fb3f225 100644 --- a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunctionJUnitTest.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunctionJUnitTest.java @@ -54,6 +54,8 @@ import org.junit.Test; import org.junit.experimental.categories.Category; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; @Category(UnitTest.class) public class LuceneQueryFunctionJUnitTest { @@ -224,19 +226,40 @@ public class LuceneQueryFunctionJUnitTest { function.execute(mockContext); } - @Test(expected = InternalFunctionInvocationTargetException.class) - public void whenServiceReturnsNullIndexButHasDefinedLuceneIndexDuringQueryExecutionInternalFunctionExceptionShouldBeThrown() + @Test + public void whenServiceReturnsNullIndexButHasDefinedLuceneIndexDuringQueryExecutionShouldBlockUntilAvailable() throws Exception { LuceneServiceImpl mockServiceImpl = mock(LuceneServiceImpl.class); when(mockCache.getService(any())).thenReturn(mockServiceImpl); - when(mockServiceImpl.getIndex(eq("indexName"), eq(regionPath))).thenReturn(null); - when(mockServiceImpl.getDefinedIndex(eq("indexName"), eq(regionPath))) - .thenReturn(mock(LuceneIndexCreationProfile.class)); + when(mockServiceImpl.getIndex(eq("indexName"), eq(regionPath))).thenAnswer(new Answer() { + private boolean calledFirstTime = false; + + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable { + if (calledFirstTime == false) { + calledFirstTime = true; + return null; + } else { + return mockIndex; + } + } + }); + when(mockServiceImpl.getDefinedIndex(eq("indexName"), eq(regionPath))).thenAnswer(new Answer() { + private int count = 10; + + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable { + if (count-- > 0) { + return mock(LuceneIndexCreationProfile.class); + } + return null; + } + }); when(mockContext.getDataSet()).thenReturn(mockRegion); when(mockContext.getArguments()).thenReturn(searchArgs); + when(mockContext.<TopEntriesCollector>getResultSender()).thenReturn(mockResultSender); LuceneQueryFunction function = new LuceneQueryFunction(); - when(mockService.getIndex(eq("indexName"), eq(regionPath))).thenReturn(null); function.execute(mockContext); } @@ -336,3 +359,4 @@ public class LuceneQueryFunctionJUnitTest { query = queryProvider.getQuery(mockIndex); } } +
