Example #1
0
        /// <summary>
        /// Process the next packet to be sent on <see cref="channelId"/>.  Return true
        /// if there was a packet to be processed on the channel, or false otherwise.
        /// </summary>
        /// <param name="channelId">the channel to process</param>
        /// <param name="csme">accumulated errors/exceptions</param>
        /// <returns>true if a packet was processed on the channel, or false if there are no packets
        /// to process or some error/exception arose</returns>
        protected virtual bool ProcessNextPacket(byte channelId, CannotSendMessagesError csme)
        {
            ChannelSendingState cs = default(ChannelSendingState);
            if (!FindNextPacket(channelId, csme, ref cs)) { return false; }
            Debug.Assert(cs.MarshalledForm != null && cs.MarshalledForm.HasPackets);
            // we could do something here to check if the transport was backlogged...
            TransportPacket tp;
            if(!packetsInProgress.TryGetValue(cs.Transport, out tp) || tp == null)
            {
                tp = packetsInProgress[cs.Transport] = new TransportPacket();
            }
            if (!sentMessages.ContainsKey(cs.Transport)) { sentMessages[cs.Transport] = new List<Message>(); }
            if (!messagesInProgress.ContainsKey(cs.Transport)) { messagesInProgress[cs.Transport] = new List<Message>(); }

            TransportPacket next = cs.MarshalledForm.RemovePacket();
            if (tp.Length + next.Length >= cs.Transport.MaximumPacketSize)
            {
                try
                {
                    cnx.SendPacket(cs.Transport, tp);
                }
                catch(TransportError e)
                {
                    csme.AddAll(e, sentMessages[cs.Transport]);
                    csme.AddAll(e, messagesInProgress[cs.Transport]);
                    sentMessages[cs.Transport].Clear();
                    messagesInProgress[cs.Transport].Clear();
                    packetsInProgress.Remove(cs.Transport);
                    return true;
                }
                NotifyMessagesSent(sentMessages[cs.Transport], cs.Transport);
                sentMessages[cs.Transport].Clear();
                packetsInProgress[cs.Transport] = tp = next;
            }
            else
            {
                tp.Append(next, 0, next.Length);
                next.Dispose();
            }
            if (cs.MarshalledForm.Finished)
            {
                messagesInProgress[cs.Transport].Remove(cs.PendingMessage.Message);
                sentMessages[cs.Transport].Add(cs.PendingMessage.Message);
                pmPool.Return(cs.PendingMessage);
                cs.PendingMessage = null;
                cs.MarshalledForm.Dispose();
                cs.MarshalledForm = null;
            }
            else
            {
                messagesInProgress[cs.Transport].Add(cs.PendingMessage.Message);
            }
            return true;
        }
Example #2
0
 protected virtual void FlushPendingPackets(CannotSendMessagesError csme)
 {
     // And send any pending stuff
     foreach (ITransport t in packetsInProgress.Keys)
     {
         TransportPacket tp;
         if(!packetsInProgress.TryGetValue(t, out tp) || tp == null
             || tp.Length == 0)
         {
             continue;
         }
         try
         {
             cnx.SendPacket(t, tp);
             NotifyMessagesSent(sentMessages[t], t);
             sentMessages[t].Clear();
         }
         catch(TransportError e)
         {
             csme.AddAll(e, sentMessages[t]);
             csme.AddAll(e, messagesInProgress[t]);
         }
         if (disposed) { return; }
     }
     packetsInProgress.Clear();
 }
Example #3
0
        public override void FlushChannelMessages(byte channelId)
        {
            int channelIndex;
            if(!channelIndices.TryGetValue(channelId, out channelIndex))
            {
                return;
            }

            CannotSendMessagesError csme = new CannotSendMessagesError(cnx);
            // Process all the packets on the channel
            while (ProcessNextPacket(channelId, csme)) { /* keep going */ }

            FlushPendingPackets(csme);
            if (csme.IsApplicable)
            {
                NotifyError(new ErrorSummary(Severity.Warning, SummaryErrorCode.MessagesCannotBeSent,
                    "Unable to send messages", csme));
            }
            //Debug.Assert(messagesInProgress.Count == 0);
            Debug.Assert(packetsInProgress.Count == 0);
        }
Example #4
0
 /// <summary>
 /// Find the next packet to be processed; return true if there are packets to 
 /// process on channelId.  The channel sending state is returned in <see cref="cs"/>.
 /// </summary>
 /// <param name="channelId"></param>
 /// <param name="csme"></param>
 /// <param name="cs"></param>
 /// <returns></returns>
 protected virtual bool FindNextPacket(byte channelId, CannotSendMessagesError csme, 
     ref ChannelSendingState cs)
 {
     if (channelSendingStates.TryGetValue(channelId, out cs)) {
         if (cs.MarshalledForm != null)
         {
             if(!cs.MarshalledForm.Finished) { return true; }
             pmPool.Return(cs.PendingMessage);
             cs.PendingMessage = null;
             cs.MarshalledForm.Dispose();
             cs.MarshalledForm = null;
         }
     }
     else
     {
         channelSendingStates[channelId] = cs = new ChannelSendingState();
     }
     PendingMessage pm;
     while (DetermineNextPendingMessage(channelId, out pm))
     {
         try
         {
             ITransport transport = cnx.FindTransport(pm.MDR, pm.CDR);
             IMarshalledResult mr = cnx.Marshal(pm.Message, transport);
             Debug.Assert(!mr.Finished, "Marshallers shouldn't produce an empty result");
             if (mr.Finished)
             {
                 // this shouldn't happen
                 mr.Dispose();
                 pmPool.Return(pm);
                 continue;
             }
             cs.MarshalledForm = mr;
             cs.PendingMessage = pm;
             cs.Transport = transport;
             return true;
         }
         catch(NoMatchingTransport e)
         {
             csme.Add(e, pm);
             continue;
         }
         catch (MarshallingException e)
         {
             csme.Add(e, pm);
             continue;
         }
     }
     // There were no messages for channelId.  So remove it from contention
     // and advance the nextChannelIndex to the next channel (actually, by
     // virtue of removing this channel, nextChannelIndex does point to the
     // next channel, so we only need to check for wrapping)
     channels.Remove(channelId);
     channelIndices.Remove(channelId);
     channelSendingStates.Remove(channelId);
     cs = null;
     if (nextChannelIndex >= channels.Count) { nextChannelIndex = 0; }
     return false;
 }
Example #5
0
        public override void Flush()
        {
            CannotSendMessagesError csme = new CannotSendMessagesError(cnx);
            while (channels.Count > 0)
            {
                byte channelId = channels[nextChannelIndex];

                if(ProcessNextPacket(channelId, csme) && channels.Count > 0)
                {
                    nextChannelIndex = (nextChannelIndex + 1) % channels.Count;
                }
            }

            FlushPendingPackets(csme);
            if (csme.IsApplicable)
            {
                NotifyError(new ErrorSummary(Severity.Warning, SummaryErrorCode.MessagesCannotBeSent,
                    "Unable to send messages", csme));
            }
            Debug.Assert(channels.Count == 0);
            Debug.Assert(pending.Count == 0);
            //Debug.Assert(messagesInProgress.Count == 0);
            Debug.Assert(packetsInProgress.Count == 0);
        }