/// <summary>ConnectionTable.Receiver interface </summary> public virtual void receive(Message msg) { TcpHeader hdr = null; msg.Dest = local_addr; Event evt = new Event(); evt.Arg = msg; evt.Priority = msg.Priority; evt.Type = Event.MSG; HearBeat hrtBeat = msg.removeHeader(HeaderType.KEEP_ALIVE) as HearBeat; if (hrtBeat != null && _keepAlive != null) { _keepAlive.ReceivedHeartBeat(msg.Src, hrtBeat); return; } TOTAL.HDR totalhdr = msg.getHeader(HeaderType.TOTAL) as TOTAL.HDR; if (!asyncPassup) this.receiveUpEvent(evt); else System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolPassup), evt); }
/// <summary> Received an mcast request - Ignore if not the sequencer, else send an /// mcast reply /// /// </summary> /// <param name="msg">the multicast request message /// </param> private void _recvMcastRequest(Message msg) { HDR header; Message repMsg; // i. If blocked, discard the mcast request // ii. Assign a seqID to the message and send it back to the requestor if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("TOTAL._recvMcastRequest()", "hdr = " + Global.CollectionToString(msg.Headers)); if (!addr.Equals(_groupSequencerAddr)) { Stack.NCacheLog.Error("Received mcast request from " + msg.Src.ToString() + " but not a group sequencer"); return; } if (state == BLOCK) { if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("Blocked, discard mcast req"); return; } header = (HDR)msg.getHeader(HeaderType.TOTAL); repMsg = new Message(msg.Src, addr, new byte[0]); repMsg.Priority = msg.Priority; int viewId = -1; try { stateLock.AcquireReaderLock(Timeout.Infinite); viewId = (int)(currentViewId != null ? currentViewId.Id : -1); } finally { stateLock.ReleaseReaderLock(); } HDR reqHdr = new HDR(HDR.REPMCAST, header.localSeqID, NextMCastSeqID, viewId); repMsg.putHeader(HeaderType.TOTAL, reqHdr); repMsg.IsUserMsg = true; repMsg.Type = MsgType.TOKEN_SEEKING; passDown(new Event(Event.MSG, repMsg)); }
/// <summary> /// Handles a message coming from a layer below /// </summary> /// <returns> true if the event should be forwarded further up, otherwise false /// (message was consumed) /// </returns> public virtual bool receiveMessage(Message msg) { object tmpHdr; HDR hdr; RspCollector coll; System.Collections.IList dests; // i. If header is not an instance of request correlator header, ignore // // ii. Check whether the message was sent by a request correlator with // the same name (there may be multiple request correlators in the same // protocol stack...) tmpHdr = msg.getHeader(HeaderType.REQUEST_COORELATOR); if (!(tmpHdr is HDR)) return (true); hdr = (HDR) tmpHdr; // If the header contains a destination list, and we are not part of it, then we discard the // request (was addressed to other members) dests = hdr.dest_mbrs; if (dests != null && local_addr != null && !dests.Contains(local_addr)) { NCacheLog.Debug("RequestCorrelator.receiveMessage()", "discarded request from " + msg.Src + " as we are not part of destination list (local_addr=" + local_addr + ", hdr=" + hdr + ')'); return false; } if (!hdr.doProcess) { NCacheLog.Debug("RequestCorrelator.receiveMessage()", hdr.id + " I should not process"); return false; } if(NCacheLog.IsInfoEnabled) NCacheLog.Info("RequestCorrelator.receiveMessage()", "header is " + hdr); // [HDR.REQ]: // i. If there is no request handler, discard // ii. Check whether priority: if synchronous and call stack contains // address that equals local address -> add priority request. Else // add normal request. // // [HDR.RSP]: // Remove the msg request correlator header and notify the associated // <tt>RspCollector</tt> that a reply has been received switch (hdr.type) { case HDR.GET_REQ_STATUS: case HDR.REQ: if (request_handler == null) return (false); //In case of NHop requests, the response is not sent to the sender of the request. Instead, //response is sent back to a node whose address is informed by the sender. handleRequest(msg,hdr.whomToReply); break; case HDR.NHOP_REQ: handleNHopRequest(msg); break; case HDR.RSP: msg.removeHeader(HeaderType.REQUEST_COORELATOR); coll = findEntry(hdr.id); if (coll != null) { coll.receiveResponse(msg); } break; case HDR.NHOP_RSP: msg.removeHeader(HeaderType.REQUEST_COORELATOR); coll = findEntry(hdr.id); if (coll != null) { if (hdr.expectResponseFrom != null) { if (coll is GroupRequest) { GroupRequest groupRequest = coll as GroupRequest; groupRequest.AddNHop(hdr.expectResponseFrom); groupRequest.AddNHopDefaultStatus(hdr.expectResponseFrom); } } coll.receiveResponse(msg); } break; default: msg.removeHeader(HeaderType.REQUEST_COORELATOR); NCacheLog.Error("RequestCorrelator.receiveMessage()", "header's type is neither REQ nor RSP !"); break; } return (false); }
/// <summary> Receive a multicast message: Put it in the pending up queue and then /// try to deliver above as many messages as possible /// /// </summary> /// <param name="msg">the received broadcast message /// </param> private void _recvMcast(Message msg) { HDR header = (HDR)msg.getHeader(HeaderType.TOTAL); // i. Put the message in the up pending queue only if it's not // already there, as it seems that the event may be received // multiple times before a view change when all members are // negotiating a common set of stable msgs // // ii. Deliver as many messages as possible int existingViewId = -1; try { stateLock.AcquireReaderLock(Timeout.Infinite); existingViewId = (int)(currentViewId != null ? currentViewId.Id : -1); } finally { stateLock.ReleaseReaderLock(); } lock (_mcastUpTbl.SyncRoot) { if (header.seqID <= _mcastSeqID) { if (header.viewId > existingViewId) { //this messages is of latest view therefore we put it into the table. lock (_undeliveredMessages.SyncRoot) { _undeliveredMessages.Add(new Event(Event.MSG, msg, msg.Priority)); } return; } if (Stack.NCacheLog.IsErrorEnabled) Stack.NCacheLog.Error("TOTAL._recvMcast", header.seqID + " is already consumed"); return; } else { if (header.viewId < existingViewId) { //this messages is of an old view therefore we discard it return; } } _mcastUpTbl[(long)header.seqID] = msg; } if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("muds: delivering mcast a message with seq : " + header.seqID); _deliverMcast(); }
/// <summary> Send a request to a group. If no response collector is given, no /// responses are expected (making the call asynchronous). /// /// </summary> /// <param name="id">The request ID. Must be unique for this JVM (e.g. current /// time in millisecs) /// </param> /// <param name="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> /// <param name="msg">The request to be sent. The body of the message carries /// the request data /// /// </param> /// <param name="coll">A response collector (usually the object that invokes /// this method). Its methods <code>ReceiveResponse</code> and /// <code>Suspect</code> will be invoked when a message has been received /// or a member is suspected, respectively. /// </param> public virtual void sendRequest(long id, System.Collections.ArrayList dest_mbrs, Message msg, RspCollector coll, byte hdrType) { HDR hdr = null; if (transport == null) { NCacheLog.Warn("RequestCorrelator.sendRequest()", "transport is not available !"); return ; } // 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 = msg.getHeader(HeaderType.REQUEST_COORELATOR) as RequestCorrelator.HDR; if (hdr == null) { hdr = new HDR(); hdr.type = hdrType; hdr.id = id; hdr.rsp_expected = coll != null ? true : false; hdr.dest_mbrs = dest_mbrs; } if (coll != null) { if (deadlock_detection) { if (local_addr == null) { NCacheLog.Error("RequestCorrelator.sendRequest()", "local address is null !"); return ; } System.Collections.ArrayList new_call_stack = (call_stack != null?(System.Collections.ArrayList) call_stack.Clone():new System.Collections.ArrayList()); new_call_stack.Add(local_addr); hdr.call_stack = new_call_stack; } addEntry(hdr.id, new RequestEntry(coll), dest_mbrs); } msg.putHeader(HeaderType.REQUEST_COORELATOR, hdr); try { if (transport is Protocol) { Event evt = new Event(); evt.Type = Event.MSG; evt.Arg = msg; ((Protocol)transport).passDown(evt); } else if (transport is Transport) ((Transport)transport).send(msg); else NCacheLog.Error("RequestCorrelator.sendRequest()", "transport object has to be either a " + "Transport or a Protocol, however it is a " + transport.GetType()); } catch (System.Exception e) { NCacheLog.Error("RequestCorrelator.sendRequest()",e.ToString()); } }