/** * This software is licensed to you under the Apache License, Version 2.0 (the * "Apache License"). * * LinkedIn's contributions are made under the Apache License. If you contribute * to the Software, the contributions will be deemed to have been made under the * Apache License, unless you expressly indicate otherwise. Please do not make any * contributions that would be inconsistent with the Apache License. * * You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, this software * distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache * License for the specific language governing permissions and limitations for the * software governed under the Apache License. * * © 2012 LinkedIn Corp. All Rights Reserved. */ package com.senseidb.search.node; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; import com.linkedin.norbert.javacompat.cluster.Node; import com.linkedin.norbert.network.ResponseIterator; import com.linkedin.norbert.javacompat.network.ScatterGatherHandler; import com.senseidb.search.req.AbstractSenseiRequest; import com.senseidb.search.req.AbstractSenseiResult; import com.senseidb.search.req.ErrorType; import com.senseidb.search.req.SenseiError; public abstract class AbstractSenseiScatterGatherHandler<REQUEST extends AbstractSenseiRequest, RESULT extends AbstractSenseiResult> implements ScatterGatherHandler<REQUEST, RESULT, RESULT, Integer> { private final static Logger logger = Logger.getLogger(AbstractSenseiScatterGatherHandler.class); private final static long DEFAULT_TIMEOUT_MILLIS = 8000L; private final REQUEST _request; protected final long _timeoutMillis; public AbstractSenseiScatterGatherHandler(REQUEST request, long timeoutMillis) { _request = request; _timeoutMillis = timeoutMillis; } /** * Merge results on the client/broker side. It likely works differently from * the one in the search node. * * @param resultList * the list of results from all the requested partitions. * @return one single result instance that is merged from the result list. */ public abstract RESULT mergeResults(REQUEST request, List<RESULT> resultList); public abstract REQUEST customizeRequest(REQUEST request, Node node, Set<Integer> partitions); /* * (non-Javadoc) * * @see * com.linkedin.norbert.network.javaapi.ScatterGatherHandler#gatherResponses * (com.google.protobuf.Message, * com.linkedin.norbert.network.ResponseIterator) */ @Override public RESULT gatherResponses(ResponseIterator<RESULT> iter) throws Exception { boolean debugmode = logger.isDebugEnabled(); int timeOuts = 0;; List<RESULT> boboBrowseList = new ArrayList<RESULT>(); while (iter.hasNext()) { RESULT result = iter.next(_timeoutMillis > 0 ? _timeoutMillis : Long.MAX_VALUE, TimeUnit.MILLISECONDS); if (result == null) { timeOuts++; logger.error("Request Timed Out"); } else { boboBrowseList.add(result); } } RESULT res = mergeResults(_request, boboBrowseList); res.addError(new SenseiError("Request timeout", ErrorType.BrokerTimeout)); if (debugmode) { logger.debug("merged results: " + res); logger.debug("Merging the sensei Results for the input senseiRequest"); } return res; } }