コード例 #1
0
        /// <summary>
        /// Does an early check to see if this queue empty callback is already
        /// running, then asynchronously firing the event
        /// </summary>
        /// <param name="categories">Throttle categories to fire the callback for</param>
        private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
        {
            //            if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
            if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
            {
                m_isQueueEmptyRunning = true;

                int       start           = Environment.TickCount & Int32.MaxValue;
                const int MIN_CALLBACK_MS = 30;

                m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
                if (m_nextOnQueueEmpty == 0)
                {
                    m_nextOnQueueEmpty = 1;
                }

                // Use a value of 0 to signal that FireQueueEmpty is running
                //                m_nextOnQueueEmpty = 0;

                m_categories = categories;

                if (HasUpdates(m_categories))
                {
                    // Asynchronously run the callback
                    Util.FireAndForget(FireQueueEmpty, categories);
                }
                else
                {
                    m_isQueueEmptyRunning = false;
                }
            }
        }
コード例 #2
0
        public bool QueueRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories)
        {
            if (m_requestQueue.Count < m_requestQueue.BoundedCapacity)
            {
//                m_log.DebugFormat(
//                    "[OUTGOING QUEUE REFILL ENGINE]: Adding request for categories {0} for {1} in {2}",
//                    categories, client.AgentID, m_udpServer.Scene.Name);

                m_requestQueue.Add(new RefillRequest(client, categories));

                if (!m_warnOverMaxQueue)
                {
                    m_warnOverMaxQueue = true;
                }

                return(true);
            }
            else
            {
                if (m_warnOverMaxQueue)
                {
                    m_log.WarnFormat(
                        "[OUTGOING QUEUE REFILL ENGINE]: Request queue at maximum capacity, not recording request from {0} in {1}",
                        client.AgentID, m_udpServer.Scene.Name);

                    m_warnOverMaxQueue = false;
                }

                return(false);
            }
        }
コード例 #3
0
        /// <summary>
        /// Fires the OnQueueEmpty callback and sets the minimum time that it
        /// can be called again
        /// </summary>
        /// <param name="o">Throttle categories to fire the callback for,
        /// stored as an object to match the WaitCallback delegate
        /// signature</param>
        private void FireQueueEmpty(object o)
        {
            //            int start = Environment.TickCount & Int32.MaxValue;
            //            const int MIN_CALLBACK_MS = 30;

            //            if (m_udpServer.IsRunningOutbound)
            //            {
            ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
            QueueEmpty callback = OnQueueEmpty;

            if (callback != null)
            {
                //                    if (m_udpServer.IsRunningOutbound)
                //                    {
                try { callback(categories); }
                catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
                //                    }
            }
            //            }

            //            m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
            //            if (m_nextOnQueueEmpty == 0)
            //                m_nextOnQueueEmpty = 1;

            //            }

            m_isQueueEmptyRunning = false;
        }
コード例 #4
0
ファイル: LLUDPClient.cs プロジェクト: ssatguru/opensim
        /// <summary>
        /// Does an early check to see if this queue empty callback is already
        /// running, then asynchronously firing the event
        /// </summary>
        /// <param name="categories">Throttle categories to fire the callback for</param>
        private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
        {
            if (!m_isQueueEmptyRunning)
            {
                if (!HasUpdates(categories))
                {
                    return;
                }

                double start = Util.GetTimeStampMS();
                if (start < m_nextOnQueueEmpty)
                {
                    return;
                }

                m_isQueueEmptyRunning = true;
                m_nextOnQueueEmpty    = start + MIN_CALLBACK_MS;

                // Asynchronously run the callback
                if (m_udpServer.OqrEngine.IsRunning)
                {
                    m_udpServer.OqrEngine.QueueJob(AgentID.ToString(), () => FireQueueEmpty(categories));
                }
                else
                {
                    Util.FireAndForget(FireQueueEmpty, categories, "LLUDPClient.BeginFireQueueEmpty");
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Does an early check to see if this queue empty callback is already
        /// running, then asynchronously firing the event
        /// </summary>
        /// <param name="categories">Throttle categories to fire the callback for</param>
        private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
        {
            int start = Environment.TickCount;

            if (!m_isQueueEmptyRunning && start - m_nextOnQueueEmpty >= 0)
            {
                m_isQueueEmptyRunning = true;

                const int MIN_CALLBACK_MS = 30;

                m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;

                m_categories = categories;

                if (HasUpdates(m_categories))
                {
                    // Asynchronously run the callback
                    Util.FireAndForget(FireQueueEmpty, categories);
                }
                else
                {
                    m_isQueueEmptyRunning = false;
                }
            }
        }
コード例 #6
0
ファイル: LLUDPClient.cs プロジェクト: kow/Aurora-Sim
 /// <summary>
 /// Does an early check to see if this queue empty callback is already
 /// running, then asynchronously firing the event
 /// </summary>
 /// <param name="throttleIndex">Throttle category to fire the callback
 /// for</param>
 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
 {
     if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
     {
         // Use a value of 0 to signal that FireQueueEmpty is running
         m_nextOnQueueEmpty = 0;
         // Asynchronously run the callback
         Util.FireAndForget(FireQueueEmpty, categories);
     }
 }
コード例 #7
0
        /// <summary>
        /// Fires the OnQueueEmpty callback and sets the minimum time that it
        /// can be called again
        /// </summary>
        /// <param name="o">Throttle categories to fire the callback for,
        /// stored as an object to match the WaitCallback delegate
        /// signature</param>
        private void FireQueueEmpty(object o)
        {
            ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
            QueueEmpty callback = OnQueueEmpty;

            if (callback != null)
            {
                try { callback(categories); }
                catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
            }

            m_isQueueEmptyRunning = false;
        }
コード例 #8
0
        /// <summary>
        /// Does an early check to see if this queue empty callback is already
        /// running, then asynchronously firing the event
        /// </summary>
        /// <param name="categories">Throttle categories to fire the callback for</param>
        private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
        {
            if (!QueueEmptyRunning && HasUpdates(categories) && OnQueueEmpty != null)
            {
                double start = Util.GetTimeStampMS();
                if (start < m_nextOnQueueEmpty)
                {
                    return;
                }

                QueueEmptyRunning  = true;
                m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;

                // Asynchronously run the callback
                if (m_udpServer.OqrEngine.IsRunning)
                {
                    LLUDPClient udpcli = this;
                    ThrottleOutPacketTypeFlags cats = categories;
                    Action <LLUDPClient, ThrottleOutPacketTypeFlags> act = delegate
                    {
                        QueueEmpty callback = udpcli.OnQueueEmpty;
                        if (callback != null)
                        {
                            try
                            {
                                callback(cats);
                            }
                            catch { }

                            if (callback != null)
                            {
                                udpcli.QueueEmptyRunning = false;
                            }
                        }
                        udpcli   = null;
                        callback = null;
                    };

                    m_udpServer.OqrEngine.QueueJob(AgentID.ToString(), () => act(udpcli, cats));
                }
                else
                {
                    Util.FireAndForget(FireQueueEmpty, categories, "LLUDPClient.BeginFireQueueEmpty");
                }
            }
        }
コード例 #9
0
ファイル: LLUDPClient.cs プロジェクト: kow/Aurora-Sim
        /// <summary>
        /// Fires the OnQueueEmpty callback and sets the minimum time that it
        /// can be called again
        /// </summary>
        /// <param name="o">Throttle categories to fire the callback for,
        /// stored as an object to match the WaitCallback delegate
        /// signature</param>
        private void FireQueueEmpty(object o)
        {
            const int MIN_CALLBACK_MS = 30;

            ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
            QueueEmpty callback = OnQueueEmpty;
            
            int start = Environment.TickCount & Int32.MaxValue;

            if (callback != null)
            {
                try { callback(categories); }
                catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
            }

            m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
            if (m_nextOnQueueEmpty == 0)
                m_nextOnQueueEmpty = 1;
        }
コード例 #10
0
        /// <summary>
        /// Does an early check to see if this queue empty callback is already
        /// running, then asynchronously firing the event
        /// </summary>
        /// <param name="categories">Throttle categories to fire the callback for</param>
        private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
        {
            if (!m_isQueueEmptyRunning)
            {
                int start = Environment.TickCount & Int32.MaxValue;

                if (start < m_nextOnQueueEmpty)
                {
                    return;
                }

                m_isQueueEmptyRunning = true;

                m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
                if (m_nextOnQueueEmpty == 0)
                {
                    m_nextOnQueueEmpty = 1;
                }

                if (HasUpdates(categories))
                {
                    if (!m_udpServer.OqrEngine.IsRunning)
                    {
                        // Asynchronously run the callback
                        Util.FireAndForget(FireQueueEmpty, categories, "LLUDPClient.BeginFireQueueEmpty");
                    }
                    else
                    {
                        m_udpServer.OqrEngine.QueueJob(AgentID.ToString(), () => FireQueueEmpty(categories));
                    }
                }
                else
                {
                    m_isQueueEmptyRunning = false;
                }
            }
        }
コード例 #11
0
ファイル: LLUDPClient.cs プロジェクト: kf6kjg/halcyon
 /// <summary>
 /// Does an early check to see if this queue empty callback is already
 /// running, then asynchronously firing the event
 /// </summary>
 /// <param name="throttleIndex">Throttle category to fire the callback
 /// for</param>
 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
 {
     if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
     {
         // Use a value of 0 to signal that FireQueueEmpty is running
         m_nextOnQueueEmpty = 0;
         // Asynchronously run the callback
         Util.FireAndForget(FireQueueEmpty, categories);
     }
 }
コード例 #12
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>
        ///
        /// <remarks>
        /// 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).
        ///
        /// 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()
        {
//            if (m_deliverPackets == false) return false;

            OutgoingPacket packet = null;
            DoubleLocklessQueue <OutgoingPacket> queue;
            TokenBucket bucket;
            bool        packetSent = false;
            ThrottleOutPacketTypeFlags emptyCategories = 0;

            //string queueDebugOutput = String.Empty; // Serious debug business

            for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
            {
                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 (nextPacket.Buffer == null)
                    {
                        if (m_packetOutboxes[i].Count < 5)
                        {
                            emptyCategories |= CategoryToFlag(i);
                        }
                        continue;
                    }
                    if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
                    {
                        // Send the packet
                        m_udpServer.SendPacketFinal(nextPacket);
                        m_nextPackets[i] = null;
                        packetSent       = true;

                        if (m_packetOutboxes[i].Count < 5)
                        {
                            emptyCategories |= CategoryToFlag(i);
                        }
                    }
                }
                else
                {
                    // No dequeued packet waiting to be sent, try to pull one off
                    // this queue
                    queue = m_packetOutboxes[i];
                    if (queue != null)
                    {
                        bool success = false;
                        try
                        {
                            success = queue.Dequeue(out packet);
                        }
                        catch
                        {
                            m_packetOutboxes[i] = new DoubleLocklessQueue <OutgoingPacket>();
                        }
                        if (success)
                        {
                            // A packet was pulled off the queue. See if we have
                            // enough tokens in the bucket to send it out
                            if (packet.Buffer == null)
                            {
                                // packet canceled elsewhere (by a ack for example)
                                if (queue.Count < 5)
                                {
                                    emptyCategories |= CategoryToFlag(i);
                                }
                            }
                            else
                            {
                                if (bucket.RemoveTokens(packet.Buffer.DataLength))
                                {
                                    // Send the packet
                                    m_udpServer.SendPacketFinal(packet);
                                    packetSent = true;

                                    if (queue.Count < 5)
                                    {
                                        emptyCategories |= CategoryToFlag(i);
                                    }
                                }
                                else
                                {
                                    // Save the dequeued packet for the next iteration
                                    m_nextPackets[i] = packet;
                                }
                            }
                        }
                        else
                        {
                            // No packets in this queue. Fire the queue empty callback
                            // if it has not been called recently
                            emptyCategories |= CategoryToFlag(i);
                        }
                    }
                    else
                    {
                        m_packetOutboxes[i] = new DoubleLocklessQueue <OutgoingPacket>();
                        emptyCategories    |= CategoryToFlag(i);
                    }
                }
            }

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

            //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
            return(packetSent);
        }
コード例 #13
0
        public bool QueueRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories)
        {
            if (m_requestQueue.Count < m_requestQueue.BoundedCapacity)
            {
//                m_log.DebugFormat(
//                    "[OUTGOING QUEUE REFILL ENGINE]: Adding request for categories {0} for {1} in {2}", 
//                    categories, client.AgentID, m_udpServer.Scene.Name);

                m_requestQueue.Add(new RefillRequest(client, categories));

                if (!m_warnOverMaxQueue)
                    m_warnOverMaxQueue = true;

                return true;
            }
            else
            {
                if (m_warnOverMaxQueue)
                {
                    m_log.WarnFormat(
                        "[OUTGOING QUEUE REFILL ENGINE]: Request queue at maximum capacity, not recording request from {0} in {1}", 
                        client.AgentID, m_udpServer.Scene.Name);

                    m_warnOverMaxQueue = false;
                }

                return false;
            }
        }
コード例 #14
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>
        ///
        /// <remarks>
        /// 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).
        ///
        /// 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()
        {
            OutgoingPacket packet;

            OpenSim.Framework.LocklessQueue <OutgoingPacket> queue;
            TokenBucket bucket;
            bool        packetSent = false;
            ThrottleOutPacketTypeFlags emptyCategories = 0;

            //string queueDebugOutput = String.Empty; // Serious debug business

            for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
            {
                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;
                    }
                }
                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;
                        }
                        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 (emptyCategories != 0)
            {
                BeginFireQueueEmpty(emptyCategories);
            }

            //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
            return(packetSent);
        }
コード例 #15
0
ファイル: LLUDPClient.cs プロジェクト: szielins/opensim
        /// <summary>
        /// Does an early check to see if this queue empty callback is already
        /// running, then asynchronously firing the event
        /// </summary>
        /// <param name="categories">Throttle categories to fire the callback for</param>
        private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
        {
//            if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
            if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
            {
                m_isQueueEmptyRunning = true;

                int start = Environment.TickCount & Int32.MaxValue;
                const int MIN_CALLBACK_MS = 30;

                m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
                if (m_nextOnQueueEmpty == 0)
                    m_nextOnQueueEmpty = 1;

                // Use a value of 0 to signal that FireQueueEmpty is running
//                m_nextOnQueueEmpty = 0;

                m_categories = categories;

                if (HasUpdates(m_categories))
                {
                    if (!m_udpServer.OqrEngine.IsRunning)
                    {
                        // Asynchronously run the callback
                        Util.FireAndForget(FireQueueEmpty, categories, "LLUDPClient.BeginFireQueueEmpty");
                    }
                    else
                    {
                        m_udpServer.OqrEngine.QueueJob(AgentID.ToString(), () => FireQueueEmpty(categories));
                    }
                }
                else
                {
                    m_isQueueEmptyRunning = false;
                }
            }
        }
コード例 #16
0
 public RefillRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories)
 {
     Client = client;
     Categories = categories;
 }
コード例 #17
0
ファイル: LLUDPClient.cs プロジェクト: kow/Aurora-Sim
        /// <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;
             */

        }
コード例 #18
0
        /// <summary>
        /// Does an early check to see if this queue empty callback is already
        /// running, then asynchronously firing the event
        /// </summary>
        /// <param name="categories">Throttle categories to fire the callback for</param>
        private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
        {
            int start = Environment.TickCount;
            if (!m_isQueueEmptyRunning && start - m_nextOnQueueEmpty >= 0)
            {
                m_isQueueEmptyRunning = true;

                const int MIN_CALLBACK_MS = 30;

                m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;

                m_categories = categories;

                if (HasUpdates(m_categories))
                {
                    // Asynchronously run the callback
                    Util.FireAndForget(FireQueueEmpty, categories);
                }
                else
                {
                    m_isQueueEmptyRunning = false;
                }
            }
        }
コード例 #19
0
 public RefillRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories)
 {
     Client     = client;
     Categories = categories;
 }
コード例 #20
0
ファイル: LLUDPClient.cs プロジェクト: ssatguru/opensim
        /// <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>
        ///
        /// <remarks>
        /// 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).
        ///
        /// 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()
        {
//            if (m_deliverPackets == false) return false;

            OutgoingPacket packet = null;
            DoubleLocklessQueue <OutgoingPacket> queue;
            bool packetSent = false;
            ThrottleOutPacketTypeFlags emptyCategories = 0;

            //string queueDebugOutput = String.Empty; // Serious debug business
            // do resends

            packet = m_nextPackets[0];
            if (packet != null)
            {
                if (packet.Buffer != null)
                {
                    if (m_throttleCategories[0].RemoveTokens(packet.Buffer.DataLength))
                    {
                        // Send the packet
                        m_udpServer.SendPacketFinal(packet);
                        packetSent       = true;
                        m_nextPackets[0] = null;
                    }
                }
                else
                {
                    m_nextPackets[0] = null;
                }
            }
            else
            {
                queue = m_packetOutboxes[0];
                if (queue != null)
                {
                    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 (packet.Buffer != null)
                        {
                            if (m_throttleCategories[0].RemoveTokens(packet.Buffer.DataLength))
                            {
                                // Send the packet
                                m_udpServer.SendPacketFinal(packet);
                                packetSent = true;
                            }
                            else
                            {
                                // Save the dequeued packet for the next iteration
                                m_nextPackets[0] = packet;
                            }
                        }
                    }
                }
                else
                {
                    m_packetOutboxes[0] = new DoubleLocklessQueue <OutgoingPacket>();
                }
            }

            if (NeedAcks.Count() > 50)
            {
                Interlocked.Increment(ref AckStalls);
                return(true);
            }

            for (int i = 1; i < THROTTLE_CATEGORY_COUNT; i++)
            {
                //queueDebugOutput += m_packetOutboxes[i].Count + " ";  // Serious debug business

                packet = m_nextPackets[i];
                if (packet != null)
                {
                    if (packet.Buffer == null)
                    {
                        if (m_packetOutboxes[i].Count < 5)
                        {
                            emptyCategories |= CategoryToFlag(i);
                        }
                        m_nextPackets[i] = null;
                        continue;
                    }

                    if (m_throttleCategories[i].RemoveTokens(packet.Buffer.DataLength))
                    {
                        // Send the packet
                        m_udpServer.SendPacketFinal(packet);
                        m_nextPackets[i] = null;
                        packetSent       = true;

                        if (m_packetOutboxes[i].Count < 5)
                        {
                            emptyCategories |= CategoryToFlag(i);
                        }
                    }
                }
                else
                {
                    // No dequeued packet waiting to be sent, try to pull one off
                    // this queue
                    queue = m_packetOutboxes[i];
                    if (queue.Dequeue(out packet))
                    {
                        if (packet.Buffer == null)
                        {
                            // packet canceled elsewhere (by a ack for example)
                            if (queue.Count < 5)
                            {
                                emptyCategories |= CategoryToFlag(i);
                            }
                            continue;
                        }

                        if (m_throttleCategories[i].RemoveTokens(packet.Buffer.DataLength))
                        {
                            // Send the packet
                            m_udpServer.SendPacketFinal(packet);
                            packetSent = true;
                            if (queue.Count < 5)
                            {
                                emptyCategories |= CategoryToFlag(i);
                            }
                        }
                        else
                        {
                            // Save the dequeued packet for the next iteration
                            m_nextPackets[i] = packet;
                        }
                    }
                    else
                    {
                        // No packets in this queue. Fire the queue empty callback
                        // if it has not been called recently
                        emptyCategories |= CategoryToFlag(i);
                    }
                }
            }

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

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