예제 #1
0
        public bool EnqueueOutgoing(OutgoingPacket packet)
        {
            int category = (int)packet.Category;

            if (category >= 0 && category < m_packetOutboxes.Length)
            {
                OpenSim.Framework.LocklessQueue <OutgoingPacket> queue = m_packetOutboxes[category];
                TokenBucket bucket = m_throttleCategories[category];

                if (bucket.RemoveTokens(packet.Buffer.DataLength))
                {
                    // Enough tokens were removed from the bucket, the packet will not be queued
                    return(false);
                }
                else
                {
                    // Not enough tokens in the bucket, queue this packet
                    queue.Enqueue(packet);
                    return(true);
                }
            }
            else
            {
                // We don't have a token bucket for this category, so it will not be queued
                return(false);
            }
        }
예제 #2
0
        public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority)
        {
            int category = (int)packet.Category;

            if (category >= 0 && category < m_packetOutboxes.Length)
            {
                DoubleLocklessQueue <OutgoingPacket> queue = m_packetOutboxes[category];

                if (m_deliverPackets == false)
                {
                    queue.Enqueue(packet, highPriority);
                    return(true);
                }

                TokenBucket bucket = m_throttleCategories[category];

                // Don't send this packet if queue is not empty
                if (queue.Count > 0 || m_nextPackets[category] != null)
                {
                    queue.Enqueue(packet, highPriority);
                    return(true);
                }

                if (!forceQueue && bucket.CheckTokens(packet.Buffer.DataLength))
                {
                    // enough tokens so it can be sent imediatly by caller
                    bucket.RemoveTokens(packet.Buffer.DataLength);
                    return(false);
                }
                else
                {
                    // Force queue specified or not enough tokens in the bucket, queue this packet
                    queue.Enqueue(packet, highPriority);
                    return(true);
                }
            }
            else
            {
                // We don't have a token bucket for this category, so it will not be queued
                return(false);
            }
        }
예제 #3
0
        /// <summary>
        /// Queue an outgoing packet if appropriate.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="forceQueue">Always queue the packet if at all possible.</param>
        /// <returns>
        /// true if the packet has been queued,
        /// false if the packet has not been queued and should be sent immediately.
        /// </returns>
        public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
        {
            int category = (int)packet.Category;

            if (category >= 0 && category < m_packetOutboxes.Length)
            {
                OpenSim.Framework.LocklessQueue <OutgoingPacket> queue = m_packetOutboxes[category];
                TokenBucket bucket = m_throttleCategories[category];

                // Don't send this packet if there is already a packet waiting in the queue
                // even if we have the tokens to send it, tokens should go to the already
                // queued packets
                if (queue.Count > 0)
                {
                    queue.Enqueue(packet);
                    return(true);
                }


                if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
                {
                    // Enough tokens were removed from the bucket, the packet will not be queued
                    return(false);
                }
                else
                {
                    // Force queue specified or not enough tokens in the bucket, queue this packet
                    queue.Enqueue(packet);
                    return(true);
                }
            }
            else
            {
                // We don't have a token bucket for this category, so it will not be queued
                return(false);
            }
        }
예제 #4
0
        /// <summary>
        /// Loops through all of the packet queues for this client and tries to send
        /// an outgoing packet from each, obeying the throttling bucket limits
        /// </summary>
        /// 
        /// Packet queues are inspected in ascending numerical order starting from 0.  Therefore, queues with a lower 
        /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have
        /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the
        /// wind queue).
        /// 
        /// <remarks>This function is only called from a synchronous loop in the
        /// UDPServer so we don't need to bother making this thread safe</remarks>
        /// <returns>True if any packets were sent, otherwise false</returns>
        public bool DequeueOutgoing (int MaxNPacks)
        {
            OutgoingPacket packet;
            bool packetSent = false;
            ThrottleOutPacketTypeFlags emptyCategories = 0;

            if (m_nextOutPackets != null)
            {
                OutgoingPacket nextPacket = m_nextOutPackets;
                if (m_throttle.RemoveTokens (nextPacket.Buffer.DataLength))
                {
                    // Send the packet
                    m_udpServer.SendPacketFinal (nextPacket);
                    m_nextOutPackets = null;
                    packetSent = true;
                    this.PacketsSent++;
                }
            }
            else
            {
                // No dequeued packet waiting to be sent, try to pull one off
                // this queue
                if (m_outbox.Dequeue (out packet))
                {
                    // A packet was pulled off the queue. See if we have
                    // enough tokens in the bucket to send it out
                    if (packet.Category == ThrottleOutPacketType.OutBand || m_throttle.RemoveTokens (packet.Buffer.DataLength))
                    {
                        // Send the packet
                        m_udpServer.SendPacketFinal (packet);
                        packetSent = true;

                        if (m_throttle.MaxBurst < TotalRateRequested)
                        {
                            float tmp = (float)m_throttle.MaxBurst * 1.005f;
                            m_throttle.DripRate = (int)tmp;
                            m_throttle.MaxBurst = (int)tmp;
                        }

                        this.PacketsSent++;
                    }
                    else
                    {
                        m_nextOutPackets = packet;
                    }
                }
                else
                {
                    emptyCategories = (ThrottleOutPacketTypeFlags)0xffff;
                }
            }

            if (m_outbox.count < 100)
            {
                emptyCategories = (ThrottleOutPacketTypeFlags)0xffff;
                BeginFireQueueEmpty (emptyCategories);
            }
            /*
                        if (emptyCategories != 0)
                            BeginFireQueueEmpty(emptyCategories);
                        else
                            {
                            int i = MapCatsToPriority[(int)ThrottleOutPacketType.Texture]; // hack to keep textures flowing for now
                            if (m_outbox.queues[i].Count < 30)
                                {
                                emptyCategories |= ThrottleOutPacketTypeFlags.Texture;
                                }
                            }
            */

            //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
            return packetSent;
            /*
  
                         OutgoingPacket packet;
                        OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
                        TokenBucket bucket;
                        bool packetSent = false;
                        ThrottleOutPacketTypeFlags emptyCategories = 0;

                        //string queueDebugOutput = String.Empty; // Serious debug business
                        int npacksTosent = MaxNPacks;

                        int i = m_lastthrottleCategoryChecked;
                        for (int j = 0; j < (int)ThrottleOutPacketType.OutBand; j++) // don't check OutBand
                        {

                            bucket = m_throttleCategories[i];
                            //queueDebugOutput += m_packetOutboxes[i].Count + " ";  // Serious debug business

                            if (m_nextPackets[i] != null)
                            {
                                // This bucket was empty the last time we tried to send a packet,
                                // leaving a dequeued packet still waiting to be sent out. Try to
                                // send it again
                                OutgoingPacket nextPacket = m_nextPackets[i];
                                if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
                                {
                                    // Send the packet
                                    m_udpServer.SendPacketFinal(nextPacket);
                                    m_nextPackets[i] = null;
                                    packetSent = true;
                                    this.PacketsSent++;
                                }
                            }
                            else
                            {
                                // No dequeued packet waiting to be sent, try to pull one off
                                // this queue
                                queue = m_packetOutboxes[i];
                                if (queue.Dequeue(out packet))
                                {
                                    // A packet was pulled off the queue. See if we have
                                    // enough tokens in the bucket to send it out
                                    if (bucket.RemoveTokens(packet.Buffer.DataLength))
                                    {
                                        // Send the packet
                                        m_udpServer.SendPacketFinal(packet);
                                        packetSent = true;
                                        this.PacketsSent++;
                                    }
                                    else
                                    {
                                        // Save the dequeued packet for the next iteration
                                        m_nextPackets[i] = packet;
                                    }

                                    // If the queue is empty after this dequeue, fire the queue
                                    // empty callback now so it has a chance to fill before we 
                                    // get back here
                                    if (queue.Count == 0)
                                        emptyCategories |= CategoryToFlag(i);
                                }
                                else
                                {
                                    // No packets in this queue. Fire the queue empty callback
                                    // if it has not been called recently
                                    emptyCategories |= CategoryToFlag(i);
                                }
                            }

                            if (++i >= (int)ThrottleOutPacketType.OutBand)
                                i = 0;

                            if (--npacksTosent <= 0)
                                break;
                        }

                        m_lastthrottleCategoryChecked = i;

                        // send at least one outband packet 

                        if (npacksTosent <= 0)
                            npacksTosent = 1;

                        i = (int)ThrottleOutPacketType.OutBand;

                        while (npacksTosent > 0)
                        {
                            //outband has no tokens checking and no throttle
                            // No dequeued packet waiting to be sent, try to pull one off
                            // this queue
                            queue = m_packetOutboxes[i];
                            if (queue.Dequeue(out packet))
                            {
                                // A packet was pulled off the queue. See if we have
                                // enough tokens in the bucket to send it out

                                //                        if (bucket.RemoveTokens(packet.Buffer.DataLength))
                                //                            {
                                // Send the packet
                                m_udpServer.SendPacketFinal(packet);
                                packetSent = true;
                                this.PacketsSent++;
                                //                            }
            //                                            else
            //                                                {
                                                            // Save the dequeued packet for the next iteration
            //                                                m_nextPackets[i] = packet;
            //                                                }

                                // If the queue is empty after this dequeue, fire the queue
                                // empty callback now so it has a chance to fill before we 
                                // get back here
                                if (queue.Count == 0)
                                    emptyCategories |= CategoryToFlag(i);
                            }
                            else
                            {
                                // No packets in this queue. Fire the queue empty callback
                                // if it has not been called recently
                                emptyCategories |= CategoryToFlag(i);
                                break;
                            }
                            npacksTosent--;
                        }

                        if (emptyCategories != 0)
                            BeginFireQueueEmpty(emptyCategories);

                        //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
                        return packetSent;
             */

        }
예제 #5
0
        /// <summary>
        /// Loops through all of the packet queues for this client and tries to send
        /// an outgoing packet from each, obeying the throttling bucket limits
        /// </summary>
        ///
        /// Packet queues are inspected in ascending numerical order starting from 0.  Therefore, queues with a lower
        /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have
        /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the
        /// wind queue).
        ///
        /// <remarks>This function is only called from a synchronous loop in the
        /// UDPServer so we don't need to bother making this thread safe</remarks>
        /// <returns>True if any packets were sent, otherwise false</returns>
        public bool DequeueOutgoing(int MaxNPacks)
        {
            OutgoingPacket packet;
            bool           packetSent = false;

            for (int i = 0; i < MaxNPacks; i++)
            {
                if (m_nextOutPackets != null)
                {
                    OutgoingPacket nextPacket = m_nextOutPackets;
                    if (m_throttle.RemoveTokens(nextPacket.Buffer.DataLength))
                    {
                        // Send the packet
                        m_udpServer.SendPacketFinal(nextPacket);
                        m_nextOutPackets = null;
                        packetSent       = true;
                        this.PacketsSent++;
                    }
                    else
                    {
                        int prio = MapCatsToPriority[(int)nextPacket.Category];
                        prio++;
                        if (prio > MapCatsToPriority.Length)
                        {
                            prio--;
                        }
                        m_outbox.Enqueue(prio, nextPacket);
                        m_nextOutPackets = null;
                    }
                }
                else
                {
                    // No dequeued packet waiting to be sent, try to pull one off
                    // this queue
                    if (m_outbox.Dequeue(out packet))
                    {
                        // A packet was pulled off the queue. See if we have
                        // enough tokens in the bucket to send it out
                        if (packet.Category == ThrottleOutPacketType.OutBand || m_throttle.RemoveTokens(packet.Buffer.DataLength))
                        {
                            // Send the packet
                            m_udpServer.SendPacketFinal(packet);
                            packetSent = true;

                            if (m_throttle.MaxBurst < TotalRateRequested)
                            {
                                float tmp = (float)m_throttle.MaxBurst * 1.005f;
                                m_throttle.DripRate = (int)tmp;
                                m_throttle.MaxBurst = (int)tmp;
                            }

                            this.PacketsSent++;
                        }
                        else
                        {
                            m_nextOutPackets = packet;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (m_outbox.count < 100 || m_lastEmptyUpdates > 10)
            {
                //if(m_outbox.count > 100)
                //    MainConsole.Instance.Output(m_outbox.count.ToString(), log4net.Core.Level.Alert);
                m_lastEmptyUpdates = 0;
                BeginFireQueueEmpty();
            }
            else
            {
                m_lastEmptyUpdates++;
            }

            //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
            return(packetSent);

            /*
             *
             *           OutgoingPacket packet;
             *          OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
             *          TokenBucket bucket;
             *          bool packetSent = false;
             *          ThrottleOutPacketTypeFlags emptyCategories = 0;
             *
             *          //string queueDebugOutput = String.Empty; // Serious debug business
             *          int npacksTosent = MaxNPacks;
             *
             *          int i = m_lastthrottleCategoryChecked;
             *          for (int j = 0; j < (int)ThrottleOutPacketType.OutBand; j++) // don't check OutBand
             *          {
             *
             *              bucket = m_throttleCategories[i];
             *              //queueDebugOutput += m_packetOutboxes[i].Count + " ";  // Serious debug business
             *
             *              if (m_nextPackets[i] != null)
             *              {
             *                  // This bucket was empty the last time we tried to send a packet,
             *                  // leaving a dequeued packet still waiting to be sent out. Try to
             *                  // send it again
             *                  OutgoingPacket nextPacket = m_nextPackets[i];
             *                  if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
             *                  {
             *                      // Send the packet
             *                      m_udpServer.SendPacketFinal(nextPacket);
             *                      m_nextPackets[i] = null;
             *                      packetSent = true;
             *                      this.PacketsSent++;
             *                  }
             *              }
             *              else
             *              {
             *                  // No dequeued packet waiting to be sent, try to pull one off
             *                  // this queue
             *                  queue = m_packetOutboxes[i];
             *                  if (queue.Dequeue(out packet))
             *                  {
             *                      // A packet was pulled off the queue. See if we have
             *                      // enough tokens in the bucket to send it out
             *                      if (bucket.RemoveTokens(packet.Buffer.DataLength))
             *                      {
             *                          // Send the packet
             *                          m_udpServer.SendPacketFinal(packet);
             *                          packetSent = true;
             *                          this.PacketsSent++;
             *                      }
             *                      else
             *                      {
             *                          // Save the dequeued packet for the next iteration
             *                          m_nextPackets[i] = packet;
             *                      }
             *
             *                      // If the queue is empty after this dequeue, fire the queue
             *                      // empty callback now so it has a chance to fill before we
             *                      // get back here
             *                      if (queue.Count == 0)
             *                          emptyCategories |= CategoryToFlag(i);
             *                  }
             *                  else
             *                  {
             *                      // No packets in this queue. Fire the queue empty callback
             *                      // if it has not been called recently
             *                      emptyCategories |= CategoryToFlag(i);
             *                  }
             *              }
             *
             *              if (++i >= (int)ThrottleOutPacketType.OutBand)
             *                  i = 0;
             *
             *              if (--npacksTosent <= 0)
             *                  break;
             *          }
             *
             *          m_lastthrottleCategoryChecked = i;
             *
             *          // send at least one outband packet
             *
             *          if (npacksTosent <= 0)
             *              npacksTosent = 1;
             *
             *          i = (int)ThrottleOutPacketType.OutBand;
             *
             *          while (npacksTosent > 0)
             *          {
             *              //outband has no tokens checking and no throttle
             *              // No dequeued packet waiting to be sent, try to pull one off
             *              // this queue
             *              queue = m_packetOutboxes[i];
             *              if (queue.Dequeue(out packet))
             *              {
             *                  // A packet was pulled off the queue. See if we have
             *                  // enough tokens in the bucket to send it out
             *
             *                  //                        if (bucket.RemoveTokens(packet.Buffer.DataLength))
             *                  //                            {
             *                  // Send the packet
             *                  m_udpServer.SendPacketFinal(packet);
             *                  packetSent = true;
             *                  this.PacketsSent++;
             *                  //                            }
             * //                                            else
             * //                                                {
             *                                              // Save the dequeued packet for the next iteration
             * //                                                m_nextPackets[i] = packet;
             * //                                                }
             *
             *                  // If the queue is empty after this dequeue, fire the queue
             *                  // empty callback now so it has a chance to fill before we
             *                  // get back here
             *                  if (queue.Count == 0)
             *                      emptyCategories |= CategoryToFlag(i);
             *              }
             *              else
             *              {
             *                  // No packets in this queue. Fire the queue empty callback
             *                  // if it has not been called recently
             *                  emptyCategories |= CategoryToFlag(i);
             *                  break;
             *              }
             *              npacksTosent--;
             *          }
             *
             *          if (emptyCategories != 0)
             *              BeginFireQueueEmpty(emptyCategories);
             *
             *          //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
             *          return packetSent;
             */
        }