All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.frameworkset.spi.remote.BaseRPCIOHandler Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2008 biaoping.yin
 *
 *  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 org.frameworkset.spi.remote;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.frameworkset.spi.security.SecurityContext;
import org.frameworkset.thread.ThreadPoolExecutor;
import org.frameworkset.thread.ThreadPoolManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import bboss.org.jgroups.util.Buffer;

/**
 * 

* Title: BaseIOHandler.java *

*

* Description: *

*

* bboss workgroup *

*

* Copyright (c) 2008 *

* * @Date 2009-11-9 下午12:52:30 * @author biaoping.yin * @version 1.0 */ public abstract class BaseRPCIOHandler implements RPCIOHandler { private ThreadPoolExecutor reqest_threadpool ; /** * 用来标识是否采用对象结果类型 */ public static final boolean useOOB = true; // public static ThreadPoolExecutor response_threadpool = ThreadPoolManagerFactory // .getThreadPoolExecutor("RPCIOHandler.response.Threadpool"); public ThreadPoolExecutor getReqestThreadpool() { if(reqest_threadpool != null) { return reqest_threadpool; } synchronized(this) { if(reqest_threadpool != null) { return reqest_threadpool; } reqest_threadpool = ThreadPoolManagerFactory .getThreadPoolExecutor("RPCIOHandler.request.Threadpool"); } return reqest_threadpool; } protected String name; public String getName() { return name; } protected static final Logger log = LoggerFactory.getLogger(BaseRPCIOHandler.class); /** * The table of pending requests (keys=Long (request IDs), values= * RequestEntry) */ protected final ConcurrentMap requests = new ConcurrentHashMap(); /** * The handler for the incoming requests. It is called from inside the * dispatcher thread */ protected RequestHandler request_handler = null; // protected boolean asyn_request = false; protected String localaddress = null; /** * 客服端标识id,作为服务器返回给本客服端的响应消息的特殊标识 */ protected RPCAddress src_address; public RPCAddress getLocalAddress() { return this.src_address; } // protected String webservice_server_type = "cxf"; public BaseRPCIOHandler(String name, RequestHandler handler,String localaddress) { this.name = name; this.request_handler = handler; // this.asyn_request = asyn_request; this.localaddress = localaddress; // this.webservice_server_type = webservice_server_type; // this.local_addr = local_addr; } /** * Add an association of:
* ID -> RspCollector */ protected void addEntry(long id, ResponseCollector coll) { requests.putIfAbsent(id, coll); } /** * Remove the request entry associated with the given ID * * @param id * the id of the RequestEntry to remove */ private void removeEntry(long id) { Long id_obj = new Long(id); // changed by bela Feb 28 2003 (bug fix for 690606) // changed back to use synchronization by bela June 27 2003 (bug fix for // #761804), // we can do this because we now copy for iteration (viewChange() and // suspect()) requests.remove(id_obj); } public void done(long id) { removeEntry(id); } protected abstract BaseFutureCall buildBaseFutureCall(RPCMessage srcmsg, RPCAddress address); /** * Send a request to a group. If no response collector is given, no * responses are expected (making the call asynchronous). * * @param id * The request ID. Must be unique for this JVM (e.g. current time * in millisecs) * @param dest_mbrs * The list of members who should receive the call. Usually a * group RPC is sent via multicast, but a receiver drops the * request if its own address is not in this list. Will not be * used if it is null. * @param msg * The request to be sent. The body of the message carries the * request data * * @param coll * A response collector (usually the object that invokes this * method). Its methods receiveResponse() and * suspect() will be invoked when a message has been * received or a member is suspected, respectively. */ public void sendRequest(long id, List dest_mbrs, RPCMessage msg, ResponseCollector coll) throws Exception { Header hdr; // i. Create the request correlator header and add it to the // msg // ii. If a reply is expected (sync call / 'coll != null'), add a // coresponding entry in the pending requests table // iii. If deadlock detection is enabled, set/update the call stack // iv. Pass the msg down to the protocol layer below hdr = new Header(Header.REQ, id, (coll != null), getName()); // hdr.dest_mbrs = dest_mbrs; if (coll != null) { addEntry(hdr.getId(), coll); } msg.putHeader(getName(), hdr); if (dest_mbrs.size() > 1) { for (Iterator it = dest_mbrs.iterator(); it.hasNext();) { final RPCAddress mbr = it.next(); final RPCMessage copy = msg.copy(true); final RemoteException e = new RemoteException(); this.getReqestThreadpool().execute(new java.lang.Runnable() { public void run() { copy.setDest(mbr); try { BaseFutureCall future = buildBaseFutureCall(copy, mbr); // if (asyn_request) // { // FutureTask fr = new // FutureTask(future); // new Thread(fr).start(); // // RPCMessage ret = fr.get(); // //同步调用系统(webservice,rmi,ejb等)一般会直接返回调用结果,异步(mina,jms)系统将返回空值, // //因此异步调用协议(mina,jms)情况下无需直接调用handler.messageReceived(ret);进行消息处理 // // if(ret != // null)//mina协议处理时返回null值,webservice返回其调用结果 // messageReceived(ret); // } // else { RPCMessage ret = future.call(); // 同步调用系统(webservice,rmi,ejb等)一般会直接返回调用结果,异步(mina,jms)系统将返回空值, // 因此异步调用协议(mina,jms)情况下无需直接调用handler.messageReceived(ret);进行消息处理 if (ret != null)// mina协议处理时返回null值,webservice返回其调用结果 messageReceived(ret); } } catch (RemoteException e_) { try { e.setErrorcode(e_.getErrorcode()); e.setMessage(e_.getRPCMessage()); e.initCause(e_.getCause()); exceptionReceived(e); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (RuntimeException e_) { try { e.setMessage(copy); e.initCause(e_); exceptionReceived(e); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (Exception e_) { try { e.setMessage(copy); e.initCause(e_); exceptionReceived(e); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }); } } else { final RPCAddress mbr = dest_mbrs.get(0); final RPCMessage copy = msg; // System.out.println(mbr); final RemoteException e = new RemoteException(); //e.printStackTrace(); this.getReqestThreadpool().execute(new java.lang.Runnable() { public void run() { copy.setDest(mbr); try { BaseFutureCall future = buildBaseFutureCall(copy, mbr); // if (asyn_request) // { // FutureTask fr = new // FutureTask(future); // new Thread(fr).start(); // RPCMessage ret = fr.get(); // //同步调用系统(webservice,rmi,ejb等)一般会直接返回调用结果,异步(mina,jms)系统将返回空值, // //因此异步调用协议(mina,jms)情况下无需直接调用handler.messageReceived(ret);进行消息处理 // // if (ret != null)//mina协议处理时返回null值,webservice返回其调用结果 // messageReceived(ret); // } // else { RPCMessage ret = future.call(); // 同步调用系统(webservice,rmi,ejb等)一般会直接返回调用结果,异步(mina,jms)系统将返回空值, // 因此异步调用协议(mina,jms)情况下无需直接调用handler.messageReceived(ret);进行消息处理 if (ret != null)// mina协议处理时返回null值,webservice返回其调用结果 messageReceived(ret); } } catch (RemoteException e_) { try { e.setMessage(e_.getRPCMessage()); e.setErrorcode(e_.getErrorcode()); e.initCause(e_.getCause()); exceptionReceived(e); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (RuntimeException e_) { try { e.setMessage(copy); e.initCause(e_); exceptionReceived(e); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (Exception e_) { try { e.setMessage(copy); e.initCause(e_); exceptionReceived(e); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }); // } // else // { // future.call(); // } // FutureTask fr=new FutureTask(new // FutureCall(copy,mbr,this)); // new Thread(fr).start(); // ClinentTransport transport = // ClinentTransport.getClinentTransport(mbr, this); // if (!MinaRPCServer.defaultlongconnection) // coll.registConnection(transport); // transport.write(copy); /** * webservice call */ } } protected void assertMessage(Object message) throws IllegalMessage { if (message instanceof RPCMessage || message instanceof String) { } else throw new IllegalMessage(message.toString()); } /** * 服务器端接收到请求后,对请求进行处理,将处理的结果返回给客服端 * * @param req * @param hdr * @return */ protected RPCMessage handleRequest(RPCMessage req, Header hdr) { Object retval; Object rsp_buf; // either byte[] or Buffer Header rsp_hdr; RPCMessage rsp = null; // i. Get the request correlator header from the msg and pass it to // the registered handler // // ii. If a reply is expected, pack the return value from the request // handler to a reply msg and send it back. The reply msg has the same // ID as the request and the name of the sender request correlator // if(log.isTraceEnabled()) { // log.trace(new StringBuilder("calling (").append((request_handler != // null? request_handler.getClass().getName() : "null")). // append(") with request ").append(hdr.id)); // } try { retval = request_handler.handle(req); } catch (Throwable t) { // if(log.isErrorEnabled()) log.error("error invoking method", t); retval = t; } if (!hdr.isRsp_expected()) // asynchronous call, we don't need to send a // response; terminate call here return null; // // if(transport == null) { // if(log.isErrorEnabled()) // log.error("failure sending response; no transport available"); // return; // } if(!useOOB) { // changed (bela Feb 20 2004): catch exception and return exception try { // retval could be an exception, or a real value rsp_buf = Util.objectToByteBuffer(retval); } catch (Throwable t) { try { // this call should succeed (all exceptions are serializable) rsp_buf = Util.objectToByteBuffer(t); } catch (Throwable tt) { // if(log.isErrorEnabled()) // log.error("failed sending rsp: return value (" + retval + // ") is not serializable"); return null; } } rsp = req.makeReply(); boolean encrypt = SecurityContext.getSecurityManager().enableEncrypt(); rsp.setEncrypt(encrypt); // rsp.setFlag(Message.OOB); if (rsp_buf instanceof Buffer) { // rsp.setBuffer(((Buffer) rsp_buf).getBuf()); // byte[] temp = null; // try { // temp = RequestCorrelator.encrypt((Buffer) rsp_buf); // } catch (Exception e) { // rsp.setEncrypt(false); // temp = ((Buffer) rsp_buf).getBuf(); // } try { rsp.setBuffer(((Buffer) rsp_buf).getBuf()); } catch (Exception e) { rsp.setEncrypt(false); } } else if (rsp_buf instanceof byte[]) try { rsp.setBuffer((byte[]) rsp_buf); } catch (Exception e) { rsp.setEncrypt(false); } } else { rsp = req.makeReply(); rsp.setResultSerial(RPCMessage.OOB); rsp.setData(retval); } rsp_hdr = new Header(Header.RSP, hdr.getId(), false, name); rsp.putHeader(name, rsp_hdr); return rsp; } protected Marshaller2 marshaller = null; public class ReceiveFuture implements Callable { RPCMessage message_; Header hdr; public ReceiveFuture(RPCMessage message_, Header hdr) { this.message_ = message_; this.hdr = hdr; } public RPCMessage call() throws Exception { return handleRequest(message_, hdr); } } /** * 客服端接收到服务器的响应后,对接收到得结果集进行处理,同时也对请求进行转发 * * @param message_ * @throws Exception */ public RPCMessage messageReceived(RPCMessage message_) throws Exception { Header hdr = message_.getHeader(name); switch (hdr.getType()) { case Header.REQ: if (request_handler == null) { // if (log.isWarnEnabled()) { log.warn("there is no request handler installed to deliver request !"); } return null; } // ReceiveFuture future = new ReceiveFuture(message_, hdr); // FutureTask fr = new FutureTask(future); // response_threadpool.execute(fr); return this.handleRequest(message_, hdr); // return fr.get(); case Header.RSP: message_.getHeader(name); ResponseCollector coll = requests.get(Long.valueOf(hdr.getId())); if (coll != null) { RPCAddress sender = message_.getSrc_addr(); Object retval = null; if(message_.getResultSerial() != RPCMessage.OOB) { byte[] buf = message_.getBuffer(); int offset = message_.getOffset(), length = message_.getLength(); try { retval = marshaller != null ? marshaller.objectFromByteBuffer(buf, offset, length) : Util .objectFromByteBuffer(buf, offset, length); } catch (Exception e) { log.error("failed unmarshalling buffer into return value", e); retval = e; } } else { retval = message_.getData(); } coll.receiveResponse(retval, sender); } return null; default: message_.getHeader(name); // if (log.isErrorEnabled()) log.error("header's type is neither REQ nor RSP !"); return null; } } /** * 客服端接收到服务器的响应后,对接收到得结果集进行处理,同时也对请求进行转发 * * @param message_ * @throws Exception */ public void exceptionReceived(RemoteException message_) throws Exception { Header hdr = message_.getRPCMessage().getHeader(name); ResponseCollector coll = requests.get(Long.valueOf(hdr.getId())); if (coll != null) { RPCAddress sender = message_.getRPCMessage().getDest(); Throwable cause = message_.getCause(); if(cause == null) { cause = new ServerUnreachableException(sender.toString()); cause.initCause(message_); } coll.receiveResponse(message_, sender); } } public interface Marshaller { byte[] objectToByteBuffer(Object obj) throws Exception; Object objectFromByteBuffer(byte[] buf) throws Exception; } public interface Marshaller2 extends Marshaller { /** * Marshals the object into a byte[] buffer and returns a Buffer with a * ref to the underlying byte[] buffer, offset and length.
* * Note that the underlying byte[] buffer must not be changed as this would change the buffer of a message which * potentially can get retransmitted, and such a retransmission would then carry a ref to a changed byte[] buffer ! * * * @param obj * @return * @throws Exception */ Buffer objectToBuffer(Object obj) throws Exception; Object objectFromByteBuffer(byte[] buf, int offset, int length) throws Exception; } /** * Used to provide a Marshaller2 interface to a Marshaller. This class is * for internal use only, and will be removed in 3.0 when Marshaller and * Marshaller2 get merged. Do not use, but provide an implementation of * Marshaller directly, e.g. in setRequestMarshaller(). */ public static class MarshallerAdapter implements Marshaller2 { private final Marshaller marshaller; public MarshallerAdapter(Marshaller marshaller) { this.marshaller = marshaller; } public byte[] objectToByteBuffer(Object obj) throws Exception { return marshaller.objectToByteBuffer(obj); } public Object objectFromByteBuffer(byte[] buf) throws Exception { return buf == null ? null : marshaller.objectFromByteBuffer(buf); } public Buffer objectToBuffer(Object obj) throws Exception { byte[] buf = marshaller.objectToByteBuffer(obj); return new Buffer(buf, 0, buf.length); } public Object objectFromByteBuffer(byte[] buf, int offset, int length) throws Exception { if (buf == null || (offset == 0 && length == buf.length)) return marshaller.objectFromByteBuffer(buf); byte[] tmp = new byte[length]; System.arraycopy(buf, offset, tmp, 0, length); return marshaller.objectFromByteBuffer(tmp); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy