public SendState(Socket s, SendParameters sendParams) { this.SendSocket = s; this.SendParameters = sendParams; }
/// <summary> /// Queue the send to the Socket buffer with no further delay. /// </summary> /// <param name="buffer"></param> /// <param name="length"></param> /// <param name="s"></param> private void SendNow(SendParameters sendItem) { Synchronizer.AssertLockIsHeld(m_SendQueue); AsyncCallback ac = new AsyncCallback(SendCallback); Socket s = null; while (true) { try { s = null; using (Synchronizer.Lock(this.m_SocketMap)) { if (m_SocketMap.ContainsKey(sendItem.Id)) { s = (Socket)m_SocketMap[sendItem.Id]; } else { //I believe this should never happen. Debug.Assert(false, "TCPServerSender.SendNow thinks there is a missing socket map entry for client id: " + sendItem.Id.ToString()); } } using (Synchronizer.Lock(m_SendingParticipants)) { if (m_SendingParticipants.ContainsKey(sendItem.Id)) { ((ReferenceCounter)m_SendingParticipants[sendItem.Id]).Increment(); } else { m_SendingParticipants.Add(sendItem.Id, new ReferenceCounter()); } ++m_PendingOutboundMessageCount; s.BeginSend(sendItem.Buffer, 0, sendItem.Length, SocketFlags.None, ac, new SendState(s, sendItem)); //BeginSend won't block. } break; } catch (Exception e) { using (Synchronizer.Lock(m_SendingParticipants)) { if (m_SendingParticipants.ContainsKey(sendItem.Id)) { ((ReferenceCounter)m_SendingParticipants[sendItem.Id]).Decrement(); } --m_PendingOutboundMessageCount; Debug.Assert(m_PendingOutboundMessageCount >= 0, "TCPServerSender.SendNow found negative pending message count"); } if (e is SocketException) { SocketException se = (SocketException)e; if (se.ErrorCode == 10055) { //Note that this shouldn't happen since we manually control the queue length. Trace.WriteLine("!!!Server Send queue is full. Sleeping 50 mS", this.GetType().ToString()); Thread.Sleep(50); //Note that sleeping here could cause various bad performance because other threads may be waiting on us.. } else { Trace.WriteLine("Send socket exception: " + se.ToString() + " Error code: " + se.ErrorCode.ToString(), this.GetType().ToString()); this.DisableClient(sendItem.Id); break; } } else if (e is ObjectDisposedException) { ObjectDisposedException ode = (ObjectDisposedException)e; this.DisableClient(sendItem.Id); Trace.WriteLine(ode.Message, this.GetType().ToString()); break; } else { Trace.WriteLine(e.ToString(), this.GetType().ToString()); break; } } } }
/// <summary> /// This has priority over other: return less than zero. /// Other has priority over this: return greater than zero. /// </summary> /// <param name="other"></param> /// <param name="currentSlideID"></param> /// <returns></returns> /// order: /// public node GuidEmpty /// public node current slide /// other node guid empty /// other node current slide /// lowest sequence number public int CompareTo(SendParameters other, Guid currentSlideID) { //If other is null, this has priority if (other == null) return -1; //Note: Guid.Empty indicates a message of global significance. //First priority for public node global or current slide message if (this.IsPublicNode != other.IsPublicNode) { if (this.IsPublicNode) { if ((this.Tags.SlideID == Guid.Empty) || (this.Tags.SlideID == currentSlideID)) return -1; } else { if ((other.Tags.SlideID == Guid.Empty) || (other.Tags.SlideID == currentSlideID)) return 1; } } //Second priority for global message if (this.Tags.SlideID == Guid.Empty) { if (other.Tags.SlideID == Guid.Empty) { return (this.SequenceNumber < other.SequenceNumber) ? -1 : 1; } else return -1; } else if (other.Tags.SlideID==Guid.Empty) return 1; //Third priority goes to messages for the current slide. if (this.Tags.SlideID == currentSlideID) { if (other.Tags.SlideID == currentSlideID) return (this.SequenceNumber < other.SequenceNumber) ? -1 : 1; else return -1; } else if (other.Tags.SlideID==currentSlideID) return 1; //finally just prioritize by sequence number. return (this.SequenceNumber < other.SequenceNumber) ? -1 : 1; }
/// <summary> /// Undo a dequeue operation. /// </summary> /// <param name="sp"></param> private void Requeue(SendParameters sp) { lock (this) { LinkedListNode<SendParameters> newNode = new LinkedListNode<SendParameters>(sp); LinkedListNode<SendParameters> n = m_List.First; while (true) { if (n == null) { m_List.AddLast(newNode); break; } if (newNode.Value.SequenceNumber < n.Value.SequenceNumber) { m_List.AddBefore(n, newNode); break; } n = n.Next; } if (!m_SlideQueues.ContainsKey(sp.Tags.SlideID)) m_SlideQueues.Add(sp.Tags.SlideID, new SlideQueue()); ((SlideQueue)m_SlideQueues[sp.Tags.SlideID]).Requeue(newNode); } }
public void Enqueue(SendParameters sp) { lock (this) { LinkedListNode<SendParameters> node = new LinkedListNode<SendParameters>(sp); m_List.AddLast(node); if (!m_SlideQueues.ContainsKey(sp.Tags.SlideID)) m_SlideQueues.Add(sp.Tags.SlideID, new SlideQueue()); ((SlideQueue)m_SlideQueues[sp.Tags.SlideID]).Enqueue(node); } }
/// <summary> /// Set the SequenceNumber property for the specified item, then enqueue it. /// </summary> /// <param name="sp"></param> public void Enqueue(SendParameters sp, ParticipantModel participant) { lock (this) { sp.SequenceNumber = m_NextSequenceNumber; m_NextSequenceNumber++; if (m_QueueList.ContainsKey(sp.Id)) { ((ClientQueue)m_QueueList[sp.Id]).Enqueue(sp); } else { ClientQueue cq = new ClientQueue(sp.Id, participant); cq.Enqueue(sp); m_QueueList.Add(sp.Id, cq); } //Trace.WriteLine("Enqueue guid=" + sp.Tags.SlideID.ToString() + "; seq =" + sp.SequenceNumber.ToString(), this.GetType().ToString()); } }