/// <summary> Sends a message to a single member (destination = msg.dest) and returns the response. The message's destination /// must be non-zero ! /// </summary> public virtual object sendMessage(Message msg, byte mode, long timeout) { RspList rsp_list = null; object dest = msg.Dest; Rsp rsp; GroupRequest _req = null; if (dest == null) return null; ArrayList mbrs = ArrayList.Synchronized(new ArrayList(1)); mbrs.Add(dest); // dummy membership (of destination address) ArrayList clusterMembership = channel.View.Members != null ? (ArrayList)channel.View.Members.Clone() : null; _req = new GroupRequest(msg, corr, mbrs, clusterMembership, mode, timeout, 0, this._ncacheLog); _req.execute(); if (mode == GroupRequest.GET_NONE) { return null; } ((GroupChannel)channel).Stack.perfStatsColl.IncrementClusteredOperationsPerSecStats(); rsp_list = _req.Results; if (rsp_list.size() == 0) { NCacheLog.Warn("MsgDispatcher.sendMessage()", " response list is empty"); return null; } if (rsp_list.size() > 1) { NCacheLog.Warn("MsgDispatcher.sendMessage()", "response list contains more that 1 response; returning first response !"); } rsp = (Rsp) rsp_list.elementAt(0); if (rsp.wasSuspected()) { throw new SuspectedException(dest); } if (!rsp.wasReceived()) { //we verify for the destination whether it is still part of the cluster or not. if (corr.CheckForMembership((Address)rsp.Sender)) throw new Runtime.Exceptions.TimeoutException("operation timeout"); else { rsp.suspected = true; throw new SuspectedException(dest); } } return rsp.Value; }
/// <summary> /// Fetches the request status from the nodes. /// </summary> /// <param name="nodes"></param> /// <returns></returns> public Hashtable FetchRequestStatus(ArrayList nodes, ArrayList clusterMembership, long reqId) { Hashtable result = new Hashtable(); if (nodes != null && nodes.Count > 0) { HDR hdr = new HDR(HDR.GET_REQ_STATUS, NextRequestId,true, null); hdr.status_reqId = reqId; Message msg = new Message(); msg.putHeader(HeaderType.REQUEST_COORELATOR, hdr); msg.Dests = nodes; msg.IsSeqRequired = false; msg.IsUserMsg = true; msg.RequestId = reqId; msg.setBuffer(new byte[0]); GroupRequest req = new GroupRequest(msg, this, nodes, clusterMembership, GroupRequest.GET_ALL, 2000, 0, this._ncacheLog); req.execute(); RspList rspList = req.Results; RequestStatus reqStatus = null; if (rspList != null) { for (int i = 0; i < rspList.size(); i++) { Rsp rsp = rspList.elementAt(i) as Rsp; if (rsp != null) { if (rsp.received) { if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ReqCorrelator.FetchReqStatus", reqId + " status response received from " + rsp.sender); object rspValue = rsp.Value; if (rspValue is byte[]) reqStatus = CompactBinaryFormatter.Deserialize(new MemoryStream((byte[])rspValue), null) as RequestStatus; else reqStatus = rsp.Value as RequestStatus; if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ReqCorrelator.FetchReqStatus", reqId + " status response: " + reqStatus); result[rsp.Sender] = reqStatus; } else { if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ReqCorrelator.FetchReqStatus", reqId + " status response NOT received from " + rsp.sender); result[rsp.Sender] = new RequestStatus(reqId,RequestStatus.NONE); } } } } } return result; }
/// <summary> Cast a message to all members, and wait for <code>mode</code> responses. The responses are returned in a response /// list, where each response is associated with its sender.<p> Uses <code>GroupRequest</code>. /// /// </summary> /// <param name="dests"> The members to which the message is to be sent. If it is null, then the message is sent to all /// members /// </param> /// <param name="msg"> The message to be sent to n members /// </param> /// <param name="mode"> Defined in <code>GroupRequest</code>. The number of responses to wait for: <ol> <li>GET_FIRST: /// return the first response received. <li>GET_ALL: wait for all responses (minus the ones from /// suspected members) <li>GET_MAJORITY: wait for a majority of all responses (relative to the grp /// size) <li>GET_ABS_MAJORITY: wait for majority (absolute, computed once) <li>GET_N: wait for n /// responses (may block if n > group size) <li>GET_NONE: wait for no responses, return immediately /// (non-blocking) </ol> /// </param> /// <param name="timeout">If 0: wait forever. Otherwise, wait for <code>mode</code> responses <em>or</em> timeout time. /// </param> /// <returns> RspList A list of responses. Each response is an <code>Object</code> and associated to its sender. /// </returns> public virtual RspList castMessage(ArrayList dests, Message msg, byte mode, long timeout) { GroupRequest _req = null; ArrayList real_dests; ArrayList clusterMembership = channel.View.Members != null ? (ArrayList)channel.View.Members.Clone() : null; // we need to clone because we don't want to modify the original // (we remove ourselves if LOCAL is false, see below) ! real_dests = dests != null ? (ArrayList)dests.Clone() : clusterMembership; // if local delivery is off, then we should not wait for the message from the local member. // therefore remove it from the membership if (channel != null && channel.getOpt(Channel.LOCAL).Equals(false)) { real_dests.Remove(channel.LocalAddress); } // don't even send the message if the destination list is empty if (NCacheLog.IsInfoEnabled) NCacheLog.Info("MsgDispatcher.castMessage()", "real_dests=" + Global.CollectionToString(real_dests)); if (real_dests == null || real_dests.Count == 0) { if (NCacheLog.IsInfoEnabled) NCacheLog.Info("MsgDispatcher.castMessage()", "destination list is empty, won't send message"); return new RspList(); // return empty response list } _req = new GroupRequest(msg, corr, real_dests, clusterMembership, mode, timeout, 0, this._ncacheLog); _req.execute(); if(mode != GroupRequest.GET_NONE) ((GroupChannel)channel).Stack.perfStatsColl.IncrementClusteredOperationsPerSecStats(); RspList rspList = _req.Results; if(rspList != null) { for(int i = 0; i< rspList.size(); i++) { Rsp rsp = rspList.elementAt(i) as Rsp; if (rsp != null) { if (!rsp.wasReceived() && !rsp.wasSuspected()) { if (corr.CheckForMembership((Address)rsp.sender)) rsp.suspected = true; } } } } return rspList; }