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

org.frameworkset.spi.remote.RPCRequest 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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.frameworkset.spi.remote.annotations.GuardedBy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 

* Title: RPCRequest.java *

*

* Description: *

*

* bboss workgroup *

*

* Copyright (c) 2007 *

* * @Date 2009-10-7 下午05:35:32 * @author biaoping.yin * @version 1.0 */ public class RPCRequest implements java.io.Serializable, ResponseCollector { private static final Logger log = LoggerFactory.getLogger(RPCRequest.class); /** return only first response */ public static final int GET_FIRST = 1; /** return all responses */ public static final int GET_ALL = 2; /** return majority (of all non-faulty members) */ public static final int GET_MAJORITY = 3; /** return majority (of all members, may block) */ public static final int GET_ABS_MAJORITY = 4; /** return n responses (may block) */ public static final int GET_N = 5; /** return no response (async call) */ public static final int GET_NONE = 6; private long id; /** to generate unique request IDs (see getRequestId()) */ private static long last_req_id = 1; protected final int rsp_mode; protected final int expected_mbrs; private RPCAddress caller; /** Map. Maps requests and responses */ @GuardedBy("lock") private final Map requests = new HashMap(); /** bounded queue of suspected members */ @GuardedBy("lock") private final List suspects = new ArrayList(); RPCMessage msg; RPCIOHandler corr; long timeout; protected volatile boolean done = false; /** list of members, changed by viewChange() */ @GuardedBy("lock") private final List members = new ArrayList(); public RPCRequest(RPCMessage msg, RPCIOHandler corr, List mbrs, int rsp_mode, long timeout, int expected_mbrs) { this.msg = msg; this.rsp_mode = rsp_mode; this.timeout = timeout; this.id = getRequestId(); this.corr = corr; this.expected_mbrs = expected_mbrs; if (mbrs != null) { for (RPCAddress mbr : mbrs) { requests.put(mbr, new RPCResponse(mbr)); } this.members.clear(); this.members.addAll(mbrs); } } // public RPCRequest() // { // this.id = getRequestId(); // } /** Generates a new unique request ID */ private static synchronized long getRequestId() { long result = System.currentTimeMillis(); if (result <= last_req_id) { result = last_req_id + 1; } last_req_id = result; return result; } public long getId() { // TODO Auto-generated method stub return id; } public void setResponseFilter(ResponseFilter filter) { rsp_filter = filter; } protected ResponseFilter rsp_filter = null; public void receiveResponse(Object response_value, RPCAddress sender) { lock.lock(); try { if (done) { // if(log.isTraceEnabled()) // log.trace("command is done; cannot add response !"); } // else if (suspects.contains(sender)) // { // // if(log.isWarnEnabled()) // // log.warn("received response from suspected member " + sender // // + "; discarding"); // } else { // try // { // ClinentTransport transport = this.addresss.remove(sender); // if(transport != null) // transport.disconnect(); // } // catch (Exception e) // { // log.error("transport.disconnect()", e); // } try { RPCResponse rsp = requests.get(sender); if (rsp != null) { if (!rsp.wasReceived()) { boolean responseReceived = (rsp_filter == null) || rsp_filter.isAcceptable(response_value, sender); rsp.setValue(response_value); rsp.setReceived(responseReceived); if (log.isTraceEnabled()) log.trace(new StringBuilder("received response for request ").append(id) .append(", sender=").append(sender).append(", val=").append(response_value).toString()); } done = rsp_filter != null && !rsp_filter.needMoreResponses(); } } catch(Exception e) { e.printStackTrace(); } } } finally { completed.signalAll(); // wakes up execute() lock.unlock(); } } /** keep suspects vector bounded */ private static final int MAX_SUSPECTS = 40; // /** // * Adds a member to the 'suspects' list. Removes oldest elements from // * 'suspects' list to keep the list bounded ('max_suspects' number of // * elements), Requires lock to be held // */ // @GuardedBy("lock") // private void addSuspect(RPCAddress suspected_mbr) // { // if (!suspects.contains(suspected_mbr)) // { // suspects.add(suspected_mbr); // while (suspects.size() >= MAX_SUSPECTS && !suspects.isEmpty()) // suspects.remove(0); // keeps queue bounded // } // } // public void suspect(RPCAddress suspected_member) // { // // if (suspected_member == null) // return; // // lock.lock(); // try // { // addSuspect(suspected_member); // RPCResponse rsp = requests.get(suspected_member); // if (rsp != null) // { // rsp.setSuspected(true); // rsp.setValue(null); // completed.signalAll(); // } // } // finally // { // lock.unlock(); // } // // } // public void viewChange(View new_view) // { // // // TODO Auto-generated method stub // // } private final Lock lock = new ReentrantLock(); /** Is set as soon as the request has received all required responses */ private final Condition completed = lock.newCondition(); public RPCResponseList getResults() { lock.lock(); try { // List rsps = requests.values(); return new RPCResponseList(requests); } finally { // this.closeShortConnection(); lock.unlock(); } } public void setCaller(RPCAddress local_addr) { this.caller = local_addr; // TODO Auto-generated method stub } public boolean execute() throws Exception { this.corr.sendRequest(this.id, members, this.msg, this); lock.lock(); try { done = false; boolean retval = collectResponses(timeout); // if(retval == false && log.isTraceEnabled()) // log.trace("call did not execute correctly, request is " + // this.toString()); return retval; } finally { done = true; lock.unlock(); } } // /** // * 关闭短连接 // */ // private void closeShortConnection() // { // Collection ss = this.addresss.values(); // if(ss != null) // { // for(Iterator ts = ss.iterator();ts.hasNext();) // { // ClinentTransport t = ts.next(); // t.disconnect(); // } // } // // } @GuardedBy("lock") private boolean collectResponses(long timeout) throws Exception { if (timeout <= 0) { while (true) { /* Wait for responses: */ // adjustMembership(); // may not be necessary, just to make // sure... if (responsesComplete()) { if (corr != null) { corr.done(id); } // if(log.isTraceEnabled() && rsp_mode != GET_NONE) { // log.trace("received all responses: " + toString()); // } return true; } try { completed.await(); // System.out.println(""); } catch (Exception e) { } } } else { long start_time = System.currentTimeMillis(); long timeout_time = start_time + timeout; while (timeout > 0) { /* Wait for responses: */ if (responsesComplete()) { if (corr != null) corr.done(id); // if(log.isTraceEnabled() && rsp_mode != GET_NONE) { // log.trace("received all responses: " + toString()); // } return true; } timeout = timeout_time - System.currentTimeMillis(); if (timeout > 0) { try { completed.await(timeout, TimeUnit.MILLISECONDS); // System.out.println(""); } catch (Exception e) { } } } if (corr != null) { corr.done(id); } // if(log.isTraceEnabled()) // log.trace("timed out waiting for responses"); return false; } } @GuardedBy("lock") private boolean responsesComplete() { int num_received = 0, num_not_received = 0, num_suspected = 0; final int num_total = requests.size(); if (done) return true; for (RPCResponse rsp : requests.values()) { if (rsp.wasReceived()) { num_received++; } else { if (rsp.wasSuspected()) { num_suspected++; } else { num_not_received++; } } } switch (rsp_mode) { case GET_FIRST: if (num_received > 0) return true; if (num_suspected >= num_total) // e.g. 2 members, and both suspected return true; break; case GET_ALL: return num_received + num_suspected >= num_total; case GET_MAJORITY: int majority = determineMajority(num_total); if (num_received + num_suspected >= majority) return true; break; case GET_ABS_MAJORITY: majority = determineMajority(num_total); if (num_received >= majority) return true; break; case GET_N: if (expected_mbrs >= num_total) { return responsesComplete(); } return num_received >= expected_mbrs || num_received + num_not_received < expected_mbrs && num_received + num_suspected >= expected_mbrs; case GET_NONE: return true; default: // if(log.isErrorEnabled()) log.error("rsp_mode " + rsp_mode + // " unknown !"); break; } return false; } private static int determineMajority(int i) { return i < 2 ? i : (i / 2) + 1; } // private transient Map addresss= new // HashMap(); // public void registConnection(ClinentTransport transport) // { // addresss.put(transport.getRpcaddress(), transport); // // TODO Auto-generated method stub // // } public String toString() { return msg.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy