/** * Dianping.com Inc. * Copyright (c) 2003-2013 All Rights Reserved. */ package com.dianping.pigeon.remoting.invoker.process.filter; import com.dianping.pigeon.log.Logger; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.monitor.MonitorLoader; import com.dianping.pigeon.monitor.MonitorTransaction; import com.dianping.pigeon.remoting.common.monitor.trace.InvokerMonitorData; import com.dianping.pigeon.remoting.common.domain.CallMethod; import com.dianping.pigeon.remoting.common.domain.InvocationContext.TimePhase; import com.dianping.pigeon.remoting.common.domain.InvocationContext.TimePoint; import com.dianping.pigeon.remoting.common.domain.InvocationRequest; import com.dianping.pigeon.remoting.common.domain.InvocationResponse; import com.dianping.pigeon.remoting.common.exception.BadRequestException; import com.dianping.pigeon.remoting.common.process.ServiceInvocationHandler; import com.dianping.pigeon.remoting.invoker.Client; import com.dianping.pigeon.remoting.invoker.concurrent.CallbackFuture; import com.dianping.pigeon.remoting.invoker.concurrent.FutureFactory; import com.dianping.pigeon.remoting.invoker.concurrent.InvocationCallback; import com.dianping.pigeon.remoting.invoker.concurrent.ServiceCallbackWrapper; import com.dianping.pigeon.remoting.invoker.concurrent.ServiceFutureImpl; import com.dianping.pigeon.remoting.invoker.config.InvokerConfig; import com.dianping.pigeon.remoting.invoker.domain.DefaultInvokerContext; import com.dianping.pigeon.remoting.invoker.domain.InvokerContext; import com.dianping.pigeon.remoting.invoker.route.region.Region; import com.dianping.pigeon.remoting.invoker.util.InvokerHelper; import com.dianping.pigeon.remoting.invoker.util.InvokerUtils; /** * 执行实际的Remote Call,包括Sync, Future,Callback,Oneway * * @author danson.liu */ public class RemoteCallInvokeFilter extends InvocationInvokeFilter { private static final Logger logger = LoggerLoader.getLogger(RemoteCallInvokeFilter.class); private static final InvocationResponse NO_RETURN_RESPONSE = InvokerUtils.createNoReturnResponse(); @Override public InvocationResponse invoke(ServiceInvocationHandler handler, InvokerContext invocationContext) throws Throwable { invocationContext.getTimeline().add(new TimePoint(TimePhase.Q)); Client client = invocationContext.getClient(); InvocationRequest request = invocationContext.getRequest(); InvokerConfig<?> invokerConfig = invocationContext.getInvokerConfig(); byte callMethodCode = invokerConfig.getCallMethod(invocationContext.getMethodName()); beforeInvoke(invocationContext); boolean isCancel = InvokerHelper.getCancel(); if (isCancel) { return InvokerUtils.createDefaultResponse(InvokerHelper.getDefaultResult()); } InvocationResponse response = null; Integer timeoutThreadLocal = InvokerHelper.getTimeout(); if (timeoutThreadLocal != null) { request.setTimeout(timeoutThreadLocal.intValue()); } MonitorTransaction transaction = MonitorLoader.getMonitor().getCurrentCallTransaction(); if (transaction != null) { transaction.addData("CurrentTimeout", request.getTimeout()); } CallMethod callMethod = CallMethod.getCallMethod(callMethodCode); InvokerMonitorData monitorData = (InvokerMonitorData) invocationContext.getMonitorData(); if (monitorData != null) { monitorData.setCallMethod(callMethodCode); monitorData.setSerialize(request.getSerialize()); monitorData.setTimeout(request.getTimeout()); Region region = client.getRegion(); monitorData.setRegion(region == null ? null : region.getName()); monitorData.add(); } try { switch (callMethod) { case SYNC: CallbackFuture future = new CallbackFuture(); response = InvokerUtils.sendRequest(client, invocationContext.getRequest(), future); invocationContext.getTimeline().add(new TimePoint(TimePhase.Q)); if (response == null) { response = future.getResponse(request.getTimeout()); } break; case CALLBACK: InvocationCallback callback = invokerConfig.getCallback(); InvocationCallback tlCallback = InvokerHelper.getCallback(); if (tlCallback != null) { callback = tlCallback; InvokerHelper.clearCallback(); } InvokerUtils.sendRequest(client, invocationContext.getRequest(), new ServiceCallbackWrapper( invocationContext, callback)); response = NO_RETURN_RESPONSE; invocationContext.getTimeline().add(new TimePoint(TimePhase.Q)); break; case FUTURE: ServiceFutureImpl futureImpl = new ServiceFutureImpl(invocationContext, request.getTimeout()); InvokerUtils.sendRequest(client, invocationContext.getRequest(), futureImpl); FutureFactory.setFuture(futureImpl); response = InvokerUtils.createFutureResponse(futureImpl); invocationContext.getTimeline().add(new TimePoint(TimePhase.Q)); break; case ONEWAY: InvokerUtils.sendRequest(client, invocationContext.getRequest(), null); response = NO_RETURN_RESPONSE; invocationContext.getTimeline().add(new TimePoint(TimePhase.Q)); break; default: throw new BadRequestException("Call type[" + callMethod.getName() + "] is not supported!"); } ((DefaultInvokerContext) invocationContext).setResponse(response); afterInvoke(invocationContext); } catch (Throwable t) { afterThrowing(invocationContext, t); throw t; } return response; } }