diff --git a/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs index 09edc949a5..31f9580a88 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs @@ -31,9 +31,10 @@ using OpenMetaverse.Packets; using OpenSim.Framework; namespace OpenSim.Region.ClientStack.LindenUDP -{ +{ public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); public delegate void PacketDrop(Packet pack, Object id); + public delegate void QueueEmpty(ThrottleOutPacketType queue); public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, UUID agentID, ThrottleOutPacketType throttlePacketType); /// @@ -44,6 +45,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { event PacketStats OnPacketStats; event PacketDrop OnPacketDrop; + event QueueEmpty OnQueueEmpty; SynchronizeClientHandler SynchronizeClient { set; } int PacketsReceived { get; } @@ -61,7 +63,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Take action depending on the type and contents of an received packet. /// - /// + /// void ProcessInPacket(LLQueItem item); void ProcessOutPacket(LLQueItem item); @@ -76,5 +78,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP void SetClientInfo(ClientInfo info); void AddImportantPacket(PacketType type); void RemoveImportantPacket(PacketType type); + int GetQueueCount(ThrottleOutPacketType queue); } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs index 67ece751ae..37f6ca74c8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs @@ -129,6 +129,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // public event PacketStats OnPacketStats; public event PacketDrop OnPacketDrop; + public event QueueEmpty OnQueueEmpty; //private SynchronizeClientHandler m_SynchronizeClient = null; @@ -172,6 +173,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings); + m_PacketQueue.OnQueueEmpty += TriggerOnQueueEmpty; + m_AckTimer.Elapsed += AckTimerElapsed; m_AckTimer.Start(); } @@ -769,6 +772,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerPacketDrop(packet, id); } + private void TriggerOnQueueEmpty(ThrottleOutPacketType queue) + { + QueueEmpty handlerQueueEmpty = OnQueueEmpty; + + if (handlerQueueEmpty == null) + return; + + handlerQueueEmpty(queue); + } + // Convert the packet to bytes and stuff it onto the send queue // public void ProcessOutPacket(LLQueItem item) @@ -850,5 +863,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_PacketQueue.Close(); Thread.CurrentThread.Abort(); } + + public int GetQueueCount(ThrottleOutPacketType queue) + { + return m_PacketQueue.GetQueueCount(queue); + } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs index 6dd0697d66..d4d654fba3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs @@ -105,6 +105,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private UUID m_agentId; + public event QueueEmpty OnQueueEmpty; + public LLPacketQueue(UUID agentId, ClientStackUserSettings userSettings) { // While working on this, the BlockingQueue had me fooled for a bit. @@ -293,30 +295,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (LandOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Land); } if (WindOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Wind); } if (CloudOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Cloud); } + bool tasksSent = false; if (TaskOutgoingPacketQueue.Count > 0) { + tasksSent = true; SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue()); } if (TaskLowpriorityPacketQueue.Count > 0) { + tasksSent = true; SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue()); } + if (tasksSent) + { + TriggerOnQueueEmpty(ThrottleOutPacketType.Task); + } if (TextureOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Texture); } if (AssetOutgoingPacketQueue.Count > 0) { SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue()); + TriggerOnQueueEmpty(ThrottleOutPacketType.Asset); } } // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); @@ -405,6 +419,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP bool qchanged = true; ResetCounters(); + + List Empty = new List(); // m_log.Info("[THROTTLE]: Entering Throttle"); while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops) { @@ -431,6 +447,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); LandThrottle.AddBytes(qpack.Length); qchanged = true; + + if (LandOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Land); } if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit()) @@ -441,6 +460,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); WindThrottle.AddBytes(qpack.Length); qchanged = true; + + if (WindOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Wind); } if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit()) @@ -451,6 +473,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); CloudThrottle.AddBytes(qpack.Length); qchanged = true; + + if (CloudOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Cloud); } if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit()) @@ -470,6 +495,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); TaskThrottle.AddBytes(qpack.Length); qchanged = true; + + if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Task); } if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit()) @@ -480,6 +508,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); TextureThrottle.AddBytes(qpack.Length); qchanged = true; + + if (TextureOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Texture); } if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit()) @@ -490,12 +521,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP TotalThrottle.AddBytes(qpack.Length); AssetThrottle.AddBytes(qpack.Length); qchanged = true; + + if (AssetOutgoingPacketQueue.Count == 0) + Empty.Add(ThrottleOutPacketType.Asset); } } // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); + + foreach (ThrottleOutPacketType t in Empty) + { + TriggerOnQueueEmpty(t); + } } } + private void TriggerOnQueueEmpty(ThrottleOutPacketType queue) + { + QueueEmpty handlerQueueEmpty = OnQueueEmpty; + + if (handlerQueueEmpty == null) + return; + + handlerQueueEmpty(queue); + } + private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) { // just to change the signature, and that ProcessThrottle @@ -704,5 +753,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP { get { return throttleMultiplier; } } + + public int GetQueueCount(ThrottleOutPacketType queue) + { + switch (queue) + { + case ThrottleOutPacketType.Land: + return LandOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Wind: + return WindOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Cloud: + return CloudOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Task: + return TaskOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Texture: + return TextureOutgoingPacketQueue.Count; + case ThrottleOutPacketType.Asset: + return AssetOutgoingPacketQueue.Count; + } + + return 0; + } } } diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index ffc8e4ce53..d16112db99 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -32,9 +32,11 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Framework.Communications; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; +using OpenMetaverse; namespace OpenSim.Services.Connectors { @@ -79,6 +81,10 @@ namespace OpenSim.Services.Connectors throw new Exception("Asset connector init error"); } m_ServerURI = serviceURI; + + MainConsole.Instance.Commands.AddCommand("asset", false, "dump asset", + "dump asset ", + "dump one cached asset", HandleDumpAsset); } protected void SetCache(IImprovedAssetCache cache) @@ -264,5 +270,43 @@ namespace OpenSim.Services.Connectors } return false; } + + private void HandleDumpAsset(string module, string[] args) + { + if (args.Length != 4) + { + MainConsole.Instance.Output("Syntax: dump asset "); + return; + } + + UUID assetID; + + if (!UUID.TryParse(args[2], out assetID)) + { + MainConsole.Instance.Output("Invalid asset ID"); + return; + } + + if (m_Cache == null) + { + MainConsole.Instance.Output("Instance uses no cache"); + return; + } + + AssetBase asset = asset = m_Cache.Get(assetID.ToString()); + + if (asset == null) + { + MainConsole.Instance.Output("Asset not found in cache"); + return; + } + + string fileName = args[3]; + + FileStream fs = File.Create(fileName); + fs.Write(asset.Data, 0, asset.Data.Length); + + fs.Close(); + } } }