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); } }
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); } }
/// <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); } }
/// <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; */ }
/// <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; */ }