Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faceting using DFS_QUERY_THEN_FETCH fails #4754

Closed
spinscale opened this issue Jan 16, 2014 · 6 comments
Closed

Faceting using DFS_QUERY_THEN_FETCH fails #4754

spinscale opened this issue Jan 16, 2014 · 6 comments
Assignees
Labels

Comments

@spinscale
Copy link
Contributor

Hey,

this came via the ML (there are also some prerequisites listed): https://groups.google.com/d/msg/elasticsearch/ySHfbIW4sBQ/8ozOkBcbWTMJ

Works on master, fails on 0.90

To reproduce (sometimes, not always)

public class BrokenFacetTest extends ElasticsearchIntegrationTest {

    @Test
    @TestLogging("_root:DEBUG")
    public void foo() throws Exception {
        client().prepareIndex("test-index", "test-type")
                .setSource("{ \"id\": 123, \"test-value\": 321 }")
                .setRefresh(true)
                .execute()
                .actionGet();

        SearchResponse searchResponse = client()
                .prepareSearch("test-index")
                .setQuery(new MatchAllQueryBuilder())
                .addFacet(new TermsFacetBuilder("test-facet").field("test-value"))
                .setSearchType(SearchType.DFS_QUERY_AND_FETCH)
                .execute()
                .actionGet();

        assertEquals(searchResponse.getFailedShards(), 0); // Failing!
    }

}

Exception being logged

[2014-01-16 10:13:16,061][DEBUG][org.elasticsearch.action.search.type] [node_2] [2] Failed to execute query phase
org.elasticsearch.ElasticSearchException
    at org.elasticsearch.ExceptionsHelper.convertToRuntime(ExceptionsHelper.java:37)
    at org.elasticsearch.search.SearchService.executeFetchPhase(SearchService.java:360)
    at org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteFetch(SearchServiceTransportAction.java:338)
    at org.elasticsearch.action.search.type.TransportSearchDfsQueryAndFetchAction$AsyncAction.executeSecondPhase(TransportSearchDfsQueryAndFetchAction.java:139)
    at org.elasticsearch.action.search.type.TransportSearchDfsQueryAndFetchAction$AsyncAction$2.run(TransportSearchDfsQueryAndFetchAction.java:123)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.AssertionError
    at org.elasticsearch.common.recycler.ThreadLocalRecycler$TV.release(ThreadLocalRecycler.java:84)
    at org.elasticsearch.search.facet.terms.longs.TermsLongFacetExecutor.buildFacet(TermsLongFacetExecutor.java:122)
    at org.elasticsearch.search.facet.FacetPhase.execute(FacetPhase.java:200)
    at org.elasticsearch.search.query.QueryPhase.execute(QueryPhase.java:129)
    at org.elasticsearch.search.SearchService.executeFetchPhase(SearchService.java:357)
    ... 6 more
@ghost ghost assigned jpountz Jan 16, 2014
@jpountz
Copy link
Contributor

jpountz commented Jan 16, 2014

There is indeed an issue in the case of DFS_QUERY_AND_FETCH because the facet executor is initialized and requests a recycled object in executeDfsPhase while facets are built (and recycled objects released) in executeFetchPhase. For reference, here are a stack trace of allocation and release:

at org.elasticsearch.common.recycler.ThreadLocalRecycler$TV.<init>(ThreadLocalRecycler.java:67)
    at org.elasticsearch.common.recycler.ThreadLocalRecycler.obtain(ThreadLocalRecycler.java:57)
    at org.elasticsearch.common.recycler.Recycler$Sizing.obtain(Recycler.java:47)
    at org.elasticsearch.cache.recycler.CacheRecycler.longIntMap(CacheRecycler.java:236)
    at org.elasticsearch.search.facet.terms.longs.TermsLongFacetExecutor.<init>(TermsLongFacetExecutor.java:71)
    at org.elasticsearch.search.facet.terms.TermsFacetParser.parse(TermsFacetParser.java:214)
    at org.elasticsearch.search.facet.FacetParseElement.parse(FacetParseElement.java:94)
    at org.elasticsearch.search.SearchService.parseSource(SearchService.java:569)
    at org.elasticsearch.search.SearchService.createContext(SearchService.java:484)
    at org.elasticsearch.search.SearchService.createContext(SearchService.java:469)
    at org.elasticsearch.search.SearchService.createAndPutContext(SearchService.java:462)
    at org.elasticsearch.search.SearchService.executeDfsPhase(SearchService.java:168)
    at org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteDfs(SearchServiceTransportAction.java:168)
at org.elasticsearch.action.search.type.TransportSearchDfsQueryAndFetchAction$AsyncAction.sendExecuteFirstPhase(TransportSearchDfsQueryAndFetchAction.java:77)
    at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:216)
    at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:203)
    at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$2.run(TransportSearchTypeAction.java:186)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
at org.elasticsearch.common.recycler.ThreadLocalRecycler$TV.release(ThreadLocalRecycler.java:88)
    at org.elasticsearch.search.facet.terms.longs.TermsLongFacetExecutor.buildFacet(TermsLongFacetExecutor.java:104)
    at org.elasticsearch.search.facet.FacetPhase.execute(FacetPhase.java:200)
    at org.elasticsearch.search.query.QueryPhase.execute(QueryPhase.java:129)
    at org.elasticsearch.search.SearchService.executeFetchPhase(SearchService.java:357)

@jpountz
Copy link
Contributor

jpountz commented Jan 17, 2014

Even though this assertion failure shows that the recycler is not used optimally (the reference is acquired and used in different phases), I think this doesn't break anything. Since facets are going to be progressively replaced by aggregations, I'm wondering if we should just remove the assertion instead of trying to fix the issue?

jpountz added a commit to jpountz/elasticsearch that referenced this issue Jan 17, 2014
Issue elastic#4754 showed that using DFS_QUERY_THEN_FETCH instead of QUERY_THEN_FETCH
might expose interesting bugs.

Close elastic#4793
@s1monw
Copy link
Contributor

s1monw commented Jan 20, 2014

so I don't want to loose the ability to fail if it's not released in the same thread to be honest. can we somehow only special case the broken facet impls?

jpountz added a commit that referenced this issue Jan 21, 2014
Issue #4754 showed that using DFS_QUERY_THEN_FETCH instead of QUERY_THEN_FETCH
might expose interesting bugs.

Close #4793
@javanna javanna added v1.0.2 and removed v1.1.0 labels Feb 24, 2014
@s1monw
Copy link
Contributor

s1monw commented Mar 12, 2014

@jpountz can we actually close this?

jpountz added a commit to jpountz/elasticsearch that referenced this issue Mar 19, 2014
When using DFS-query-then-fetch, some facet data-structures are acquired and
released on a different thread, which is something that is not supported by
the (soft) thread-local cache recycler.

On 1.x, this limitation has been removed, and all recyclers actually support
acquisitions and relases on different threads. This commit makes sure it also
works on 0.90 by making the stack that is used to store pending objects
synchronized. The performance impact of these synchronized blocks is expected
to be very low as there would be very little contention. By the way calls to
acquire/release are synchronized on the default cache recycler on 1.x.

Close elastic#4754
jpountz added a commit that referenced this issue Mar 20, 2014
When using DFS-query-then-fetch, some facet data-structures are acquired and
released on a different thread, which is something that is not supported by
the (soft) thread-local cache recycler.

On 1.x, this limitation has been removed, and all recyclers actually support
acquisitions and relases on different threads. This commit makes sure it also
works on 0.90 by making the stack that is used to store pending objects
synchronized. The performance impact of these synchronized blocks is expected
to be very low as there would be very little contention. By the way calls to
acquire/release are synchronized on the default cache recycler on 1.x.

Close #4754
@jpountz
Copy link
Contributor

jpountz commented Mar 20, 2014

Closed via f7e887b

@jpountz jpountz closed this as completed Mar 20, 2014
@jpountz
Copy link
Contributor

jpountz commented Apr 24, 2014

For reference, the root cause of this issue has been fixed in #5821

mute pushed a commit to mute/elasticsearch that referenced this issue Jul 29, 2015
When using DFS-query-then-fetch, some facet data-structures are acquired and
released on a different thread, which is something that is not supported by
the (soft) thread-local cache recycler.

On 1.x, this limitation has been removed, and all recyclers actually support
acquisitions and relases on different threads. This commit makes sure it also
works on 0.90 by making the stack that is used to store pending objects
synchronized. The performance impact of these synchronized blocks is expected
to be very low as there would be very little contention. By the way calls to
acquire/release are synchronized on the default cache recycler on 1.x.

Close elastic#4754
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants