Search in sources :

Example 1 with RTimerTree

use of org.apache.solr.util.RTimerTree in project lucene-solr by apache.

the class SearchHandler method handleRequestBody.

@Override
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
    List<SearchComponent> components = getComponents();
    ResponseBuilder rb = new ResponseBuilder(req, rsp, components);
    if (rb.requestInfo != null) {
        rb.requestInfo.setResponseBuilder(rb);
    }
    boolean dbg = req.getParams().getBool(CommonParams.DEBUG_QUERY, false);
    rb.setDebug(dbg);
    if (dbg == false) {
        //if it's true, we are doing everything anyway.
        SolrPluginUtils.getDebugInterests(req.getParams().getParams(CommonParams.DEBUG), rb);
    }
    final RTimerTree timer = rb.isDebug() ? req.getRequestTimer() : null;
    // creates a ShardHandler object only if it's needed
    final ShardHandler shardHandler1 = getAndPrepShardHandler(req, rb);
    if (timer == null) {
        // non-debugging prepare phase
        for (SearchComponent c : components) {
            c.prepare(rb);
        }
    } else {
        // debugging prepare phase
        RTimerTree subt = timer.sub("prepare");
        for (SearchComponent c : components) {
            rb.setTimer(subt.sub(c.getName()));
            c.prepare(rb);
            rb.getTimer().stop();
        }
        subt.stop();
    }
    if (!rb.isDistrib) {
        // a normal non-distributed request
        long timeAllowed = req.getParams().getLong(CommonParams.TIME_ALLOWED, -1L);
        if (timeAllowed > 0L) {
            SolrQueryTimeoutImpl.set(timeAllowed);
        }
        try {
            // it makes sense to have two control loops
            if (!rb.isDebug()) {
                // Process
                for (SearchComponent c : components) {
                    c.process(rb);
                }
            } else {
                // Process
                RTimerTree subt = timer.sub("process");
                for (SearchComponent c : components) {
                    rb.setTimer(subt.sub(c.getName()));
                    c.process(rb);
                    rb.getTimer().stop();
                }
                subt.stop();
                // add the timing info
                if (rb.isDebugTimings()) {
                    rb.addDebugInfo("timing", timer.asNamedList());
                }
            }
        } catch (ExitableDirectoryReader.ExitingReaderException ex) {
            log.warn("Query: " + req.getParamString() + "; " + ex.getMessage());
            SolrDocumentList r = (SolrDocumentList) rb.rsp.getResponse();
            if (r == null)
                r = new SolrDocumentList();
            r.setNumFound(0);
            rb.rsp.addResponse(r);
            if (rb.isDebug()) {
                NamedList debug = new NamedList();
                debug.add("explain", new NamedList());
                rb.rsp.add("debug", debug);
            }
            rb.rsp.getResponseHeader().add(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE);
        } finally {
            SolrQueryTimeoutImpl.reset();
        }
    } else {
        if (rb.outgoing == null) {
            rb.outgoing = new LinkedList<>();
        }
        rb.finished = new ArrayList<>();
        int nextStage = 0;
        do {
            rb.stage = nextStage;
            nextStage = ResponseBuilder.STAGE_DONE;
            // call all components
            for (SearchComponent c : components) {
                // the next stage is the minimum of what all components report
                nextStage = Math.min(nextStage, c.distributedProcess(rb));
            }
            // check the outgoing queue and send requests
            while (rb.outgoing.size() > 0) {
                // submit all current request tasks at once
                while (rb.outgoing.size() > 0) {
                    ShardRequest sreq = rb.outgoing.remove(0);
                    sreq.actualShards = sreq.shards;
                    if (sreq.actualShards == ShardRequest.ALL_SHARDS) {
                        sreq.actualShards = rb.shards;
                    }
                    // presume we'll get a response from each shard we send to
                    sreq.responses = new ArrayList<>(sreq.actualShards.length);
                    // TODO: map from shard to address[]
                    for (String shard : sreq.actualShards) {
                        ModifiableSolrParams params = new ModifiableSolrParams(sreq.params);
                        // not a top-level request
                        params.remove(ShardParams.SHARDS);
                        // not a top-level request
                        params.set(DISTRIB, "false");
                        params.remove("indent");
                        params.remove(CommonParams.HEADER_ECHO_PARAMS);
                        // a sub (shard) request
                        params.set(ShardParams.IS_SHARD, true);
                        params.set(ShardParams.SHARDS_PURPOSE, sreq.purpose);
                        // so the shard knows what was asked
                        params.set(ShardParams.SHARD_URL, shard);
                        if (rb.requestInfo != null) {
                            // we could try and detect when this is needed, but it could be tricky
                            params.set("NOW", Long.toString(rb.requestInfo.getNOW().getTime()));
                        }
                        String shardQt = params.get(ShardParams.SHARDS_QT);
                        if (shardQt != null) {
                            params.set(CommonParams.QT, shardQt);
                        } else {
                            // for distributed queries that don't include shards.qt, use the original path
                            // as the default but operators need to update their luceneMatchVersion to enable
                            // this behavior since it did not work this way prior to 5.1
                            String reqPath = (String) req.getContext().get(PATH);
                            if (!"/select".equals(reqPath)) {
                                params.set(CommonParams.QT, reqPath);
                            }
                        // else if path is /select, then the qt gets passed thru if set
                        }
                        shardHandler1.submit(sreq, shard, params);
                    }
                }
                // now wait for replies, but if anyone puts more requests on
                // the outgoing queue, send them out immediately (by exiting
                // this loop)
                boolean tolerant = rb.req.getParams().getBool(ShardParams.SHARDS_TOLERANT, false);
                while (rb.outgoing.size() == 0) {
                    ShardResponse srsp = tolerant ? shardHandler1.takeCompletedIncludingErrors() : shardHandler1.takeCompletedOrError();
                    // no more requests to wait for
                    if (srsp == null)
                        break;
                    // Was there an exception?  
                    if (srsp.getException() != null) {
                        // If things are not tolerant, abort everything and rethrow
                        if (!tolerant) {
                            shardHandler1.cancelAll();
                            if (srsp.getException() instanceof SolrException) {
                                throw (SolrException) srsp.getException();
                            } else {
                                throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, srsp.getException());
                            }
                        } else {
                            if (rsp.getResponseHeader().get(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY) == null) {
                                rsp.getResponseHeader().add(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE);
                            }
                        }
                    }
                    rb.finished.add(srsp.getShardRequest());
                    // let the components see the responses to the request
                    for (SearchComponent c : components) {
                        c.handleResponses(rb, srsp.getShardRequest());
                    }
                }
            }
            for (SearchComponent c : components) {
                c.finishStage(rb);
            }
        // we are done when the next stage is MAX_VALUE
        } while (nextStage != Integer.MAX_VALUE);
    }
    // SOLR-5550: still provide shards.info if requested even for a short circuited distrib request
    if (!rb.isDistrib && req.getParams().getBool(ShardParams.SHARDS_INFO, false) && rb.shortCircuitedURL != null) {
        NamedList<Object> shardInfo = new SimpleOrderedMap<Object>();
        SimpleOrderedMap<Object> nl = new SimpleOrderedMap<Object>();
        if (rsp.getException() != null) {
            Throwable cause = rsp.getException();
            if (cause instanceof SolrServerException) {
                cause = ((SolrServerException) cause).getRootCause();
            } else {
                if (cause.getCause() != null) {
                    cause = cause.getCause();
                }
            }
            nl.add("error", cause.toString());
            StringWriter trace = new StringWriter();
            cause.printStackTrace(new PrintWriter(trace));
            nl.add("trace", trace.toString());
        } else {
            nl.add("numFound", rb.getResults().docList.matches());
            nl.add("maxScore", rb.getResults().docList.maxScore());
        }
        nl.add("shardAddress", rb.shortCircuitedURL);
        // elapsed time of this request so far
        nl.add("time", req.getRequestTimer().getTime());
        int pos = rb.shortCircuitedURL.indexOf("://");
        String shardInfoName = pos != -1 ? rb.shortCircuitedURL.substring(pos + 3) : rb.shortCircuitedURL;
        shardInfo.add(shardInfoName, nl);
        rsp.getValues().add(ShardParams.SHARDS_INFO, shardInfo);
    }
}
Also used : SolrServerException(org.apache.solr.client.solrj.SolrServerException) ExitableDirectoryReader(org.apache.lucene.index.ExitableDirectoryReader) SimpleOrderedMap(org.apache.solr.common.util.SimpleOrderedMap) ModifiableSolrParams(org.apache.solr.common.params.ModifiableSolrParams) StringWriter(java.io.StringWriter) SolrException(org.apache.solr.common.SolrException) PrintWriter(java.io.PrintWriter) NamedList(org.apache.solr.common.util.NamedList) SolrDocumentList(org.apache.solr.common.SolrDocumentList) RTimerTree(org.apache.solr.util.RTimerTree)

Aggregations

PrintWriter (java.io.PrintWriter)1 StringWriter (java.io.StringWriter)1 ExitableDirectoryReader (org.apache.lucene.index.ExitableDirectoryReader)1 SolrServerException (org.apache.solr.client.solrj.SolrServerException)1 SolrDocumentList (org.apache.solr.common.SolrDocumentList)1 SolrException (org.apache.solr.common.SolrException)1 ModifiableSolrParams (org.apache.solr.common.params.ModifiableSolrParams)1 NamedList (org.apache.solr.common.util.NamedList)1 SimpleOrderedMap (org.apache.solr.common.util.SimpleOrderedMap)1 RTimerTree (org.apache.solr.util.RTimerTree)1