Java tutorial
/* * Copyright 2008-2009 the original (zyc@hasor.net). * * 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 net.hasor.rsf.remoting.transport.customer; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.util.HashedWheelTimer; import io.netty.util.Timeout; import io.netty.util.Timer; import io.netty.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import net.hasor.core.Provider; import net.hasor.rsf.RsfBindInfo; import net.hasor.rsf.RsfFilter; import net.hasor.rsf.RsfFilterChain; import net.hasor.rsf.RsfFuture; import net.hasor.rsf.RsfRequest; import net.hasor.rsf.RsfResponse; import net.hasor.rsf.RsfSettings; import net.hasor.rsf.SendLimitPolicy; import net.hasor.rsf.adapter.AbstractClientManager; import net.hasor.rsf.adapter.AbstractRequestManager; import net.hasor.rsf.adapter.AbstractRsfClient; import net.hasor.rsf.adapter.AbstractRsfContext; import net.hasor.rsf.constants.ProtocolStatus; import net.hasor.rsf.constants.RsfException; import net.hasor.rsf.constants.RsfTimeoutException; import net.hasor.rsf.remoting.transport.component.RsfFilterHandler; import net.hasor.rsf.remoting.transport.component.RsfRequestImpl; import net.hasor.rsf.remoting.transport.component.RsfResponseImpl; import net.hasor.rsf.remoting.transport.protocol.message.RequestMsg; import org.more.future.FutureCallback; import org.more.logger.LoggerHelper; /** * ? RSF ? * @version : 2014912 * @author (zyc@hasor.net) */ public class RsfRequestManager extends AbstractRequestManager { private final AbstractRsfContext rsfContext; private final AbstractClientManager clientManager; private final ConcurrentHashMap<Long, RsfFuture> rsfResponse; private final Timer timer; private final AtomicInteger requestCount; // public RsfRequestManager(AbstractRsfContext rsfContext) { this.rsfContext = rsfContext; this.clientManager = new InnerClientManager(this); this.rsfResponse = new ConcurrentHashMap<Long, RsfFuture>(); this.timer = new HashedWheelTimer(); this.requestCount = new AtomicInteger(0); } /**? {@link AbstractRsfContext}*/ public AbstractRsfContext getRsfContext() { return this.rsfContext; } /**??*/ public AbstractClientManager getClientManager() { return this.clientManager; } /**?*/ public RsfFuture getRequest(long requestID) { return this.rsfResponse.get(requestID); } // private int validateTimeout(int timeout) { if (timeout <= 0) timeout = this.getRsfContext().getSettings().getDefaultTimeout(); return timeout; } private RsfFuture removeRsfFuture(long requestID) { RsfFuture rsfFuture = this.rsfResponse.remove(requestID); if (rsfFuture != null) { this.requestCount.decrementAndGet();// i--; } return rsfFuture; } /**Response?*/ public void putResponse(long requestID, RsfResponse response) { RsfFuture rsfFuture = this.removeRsfFuture(requestID); if (rsfFuture != null) { LoggerHelper.logFinest("received response(%s) status = %s", requestID, response.getResponseStatus()); rsfFuture.completed(response); } else { LoggerHelper.logWarn("give up the response,requestID(%s) ,maybe because timeout! ", requestID); } } /**Response?*/ public void putResponse(long requestID, Throwable e) { RsfFuture rsfFuture = this.removeRsfFuture(requestID); if (rsfFuture != null) { LoggerHelper.logSevere("received error ,requestID(%s) status = %s", requestID, e.getMessage()); rsfFuture.failed(e); } else { LoggerHelper.logWarn("give up the response,requestID(%s) ,maybe because timeout! ", requestID); } } /**???*/ public void tryAgain(long requestID) { this.putResponse(requestID, new RsfException(ProtocolStatus.ChooseOther, "Server response ChooseOther!")); System.out.println("RequestID:" + requestID + " -> ChooseOther"); // } // /**?*/ private void startRequest(RsfFuture rsfFuture) { this.requestCount.incrementAndGet();// i++; this.rsfResponse.put(rsfFuture.getRequest().getRequestID(), rsfFuture); final RsfRequestImpl request = (RsfRequestImpl) rsfFuture.getRequest(); TimerTask timeTask = new TimerTask() { public void run(Timeout timeoutObject) throws Exception { // RsfFuture rsfCallBack = RsfRequestManager.this.getRequest(request.getRequestID()); if (rsfCallBack == null) return; //?Response String errorInfo = "timeout is reached on client side:" + request.getTimeout(); LoggerHelper.logWarn(errorInfo); //Response RsfRequestManager.this.putResponse(request.getRequestID(), new RsfTimeoutException(errorInfo)); } }; // int reqTimeout = validateTimeout(request.getTimeout()); this.timer.newTimeout(timeTask, reqTimeout, TimeUnit.MILLISECONDS); }; /**??*/ public RsfFuture sendRequest(RsfRequest rsfRequest, FutureCallback<RsfResponse> listener) { final RsfFuture rsfFuture = new RsfFuture(rsfRequest, listener); RsfRequestImpl req = (RsfRequestImpl) rsfFuture.getRequest(); RsfResponseImpl res = req.buildResponse(); // try { RsfBindInfo<?> bindInfo = req.getBindInfo(); Provider<RsfFilter>[] rsfFilter = this.getRsfContext().getFilters(bindInfo); /*??? -> rsfFiltersendRequest??*/ new InnterRsfFilterHandler(rsfFilter, new RsfFilterChain() { public void doFilter(RsfRequest request, RsfResponse response) throws Throwable { sendRequest(rsfFuture);//?? } }).doFilter(req, res); } catch (Throwable e) { rsfFuture.failed(e); } // if (res.isResponse()) { rsfFuture.completed(res); } return rsfFuture; } /**???*/ private void sendRequest(RsfFuture rsfFuture) { //??? RsfSettings rsfSettings = this.getRsfContext().getSettings(); if (this.requestCount.get() >= rsfSettings.getMaximumRequest()) { SendLimitPolicy sendPolicy = rsfSettings.getSendLimitPolicy(); String errorMessage = "maximum number of requests, apply SendPolicy = " + sendPolicy.name(); LoggerHelper.logWarn(errorMessage); if (sendPolicy == SendLimitPolicy.Reject) { throw new RsfException(ProtocolStatus.ClientError, errorMessage); } else { try { Thread.sleep(1000); } catch (InterruptedException e) { } } } //RsfFilter final RsfRequestImpl request = (RsfRequestImpl) rsfFuture.getRequest(); final RequestMsg rsfMessage = request.getMsg(); //?? final AbstractRsfClient rsfClient = this.getClientManager().getClient(request.getBindInfo()); final long beginTime = System.currentTimeMillis(); final long timeout = rsfMessage.getClientTimeout(); // if (rsfClient == null) { rsfFuture.failed(new IllegalStateException("The lack of effective service provider.")); return; } if (rsfClient.isActive() == false) { rsfFuture.failed(new IllegalStateException("client is closed.")); return; } this.startRequest( rsfFuture);/* timeout ???request*/ // ChannelFuture future = rsfClient.getChannel().writeAndFlush(rsfMessage); /*sendData???*/ future.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { return; } String errorMsg = null; // if (System.currentTimeMillis() - beginTime >= timeout) { errorMsg = "send request too long time(" + (System.currentTimeMillis() - beginTime) + "),requestID:" + rsfMessage.getRequestID(); } //? if (future.isCancelled()) { errorMsg = "send request to cancelled by user,requestID:" + rsfMessage.getRequestID(); } // if (!future.isSuccess()) { if (rsfClient.isActive()) { // maybe some exception, so close the channel getClientManager().unRegistered(rsfClient.getHostAddress()); } errorMsg = "send request error " + future.cause(); } LoggerHelper.logSevere(RsfRequestManager.this + ":" + errorMsg); //Response putResponse(request.getRequestID(), new RsfException(ProtocolStatus.ClientError, errorMsg)); } }); } // private class InnterRsfFilterHandler extends RsfFilterHandler { public InnterRsfFilterHandler(Provider<RsfFilter>[] rsfFilters, RsfFilterChain rsfChain) { super(rsfFilters, rsfChain); } public void doFilter(RsfRequest request, RsfResponse response) throws Throwable { try { super.doFilter(request, response); } finally { } } } }