/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.collector.cluster.route;
import com.navercorp.pinpoint.collector.cluster.ClusterPointLocator;
import com.navercorp.pinpoint.collector.cluster.TargetClusterPoint;
import com.navercorp.pinpoint.collector.cluster.route.filter.RouteFilter;
import com.navercorp.pinpoint.rpc.Future;
import com.navercorp.pinpoint.rpc.ResponseMessage;
import com.navercorp.pinpoint.thrift.dto.command.TCommandTransferResponse;
import com.navercorp.pinpoint.thrift.dto.command.TRouteResult;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.thrift.TBase;
/**
* @author koo.taejin
* @author HyunGil Jeong
*/
public class DefaultRouteHandler extends AbstractRouteHandler<RequestEvent> {
private final RouteFilterChain<RequestEvent> requestFilterChain;
private final RouteFilterChain<ResponseEvent> responseFilterChain;
public DefaultRouteHandler(ClusterPointLocator<TargetClusterPoint> targetClusterPointLocator,
RouteFilterChain<RequestEvent> requestFilterChain,
RouteFilterChain<ResponseEvent> responseFilterChain) {
super(targetClusterPointLocator);
this.requestFilterChain = requestFilterChain;
this.responseFilterChain = responseFilterChain;
}
@Override
public void addRequestFilter(RouteFilter<RequestEvent> filter) {
this.requestFilterChain.addLast(filter);
}
@Override
public void addResponseFilter(RouteFilter<ResponseEvent> filter) {
this.responseFilterChain.addLast(filter);
}
@Override
public TCommandTransferResponse onRoute(RequestEvent event) {
requestFilterChain.doEvent(event);
TCommandTransferResponse routeResult = onRoute0(event);
responseFilterChain.doEvent(new ResponseEvent(event, event.getRequestId(), routeResult));
return routeResult;
}
private TCommandTransferResponse onRoute0(RequestEvent event) {
TBase<?,?> requestObject = event.getRequestObject();
if (requestObject == null) {
return createResponse(TRouteResult.EMPTY_REQUEST);
}
TargetClusterPoint clusterPoint = findClusterPoint(event.getDeliveryCommand());
if (clusterPoint == null) {
return createResponse(TRouteResult.NOT_FOUND);
}
if (!clusterPoint.isSupportCommand(requestObject)) {
return createResponse(TRouteResult.NOT_SUPPORTED_REQUEST);
}
Future<ResponseMessage> future = clusterPoint.request(event.getDeliveryCommand().getPayload());
boolean isCompleted = future.await();
if (!isCompleted) {
return createResponse(TRouteResult.TIMEOUT);
}
ResponseMessage responseMessage = future.getResult();
if (responseMessage == null) {
return createResponse(TRouteResult.EMPTY_RESPONSE);
}
final byte[] responsePayload = responseMessage.getMessage();
if (ArrayUtils.isEmpty(responsePayload)) {
return createResponse(TRouteResult.EMPTY_RESPONSE, new byte[0]);
}
return createResponse(TRouteResult.OK, responsePayload);
}
private TCommandTransferResponse createResponse(TRouteResult result) {
return createResponse(result, new byte[0]);
}
private TCommandTransferResponse createResponse(TRouteResult result, byte[] payload) {
TCommandTransferResponse response = new TCommandTransferResponse();
response.setRouteResult(result);
response.setPayload(payload);
return response;
}
}