From dc225e348dd118627af02a1ce66642ba4eaf1b46 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 1 Mar 2020 18:56:07 +0000 Subject: [PATCH] several changes to lludp FetchInventory --- OpenSim/Framework/IClientAPI.cs | 8 +- .../ClientStack/Linden/UDP/LLClientView.cs | 109 +++++++++++------- .../Framework/Scenes/AsyncInventorySender.cs | 97 ++++++++-------- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 8 +- .../Server/IRCClientView.cs | 4 +- .../OptionalModules/World/NPC/NPCAvatar.cs | 4 +- OpenSim/Tests/Common/Mock/TestClient.cs | 4 +- 7 files changed, 137 insertions(+), 97 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 662e47046c..cf5c2559ea 100755 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -223,6 +223,8 @@ namespace OpenSim.Framework UUID RayTargetID, byte RayEndIsIntersection); + public delegate void AgentDataUpdate(IClientAPI remoteClient, UUID itemID, UUID ownerID); + public delegate void RequestGodlikePowers( UUID AgentID, UUID SessionID, UUID token, bool GodLike); @@ -252,7 +254,7 @@ namespace OpenSim.Framework public delegate void PurgeInventoryDescendents( IClientAPI remoteClient, UUID folderID); - public delegate void FetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID); + public delegate void FetchInventory(IClientAPI remoteClient, UUID[] items, UUID[] owner); public delegate void RequestTaskInventory(IClientAPI remoteClient, uint localID); @@ -846,7 +848,7 @@ namespace OpenSim.Framework event Action OnRequestAvatarsData; event AddNewPrim OnAddPrim; - event FetchInventory OnAgentDataUpdateRequest; + event AgentDataUpdate OnAgentDataUpdateRequest; event TeleportLocationRequest OnSetStartLocationRequest; event RequestGodlikePowers OnRequestGodlikePowers; @@ -1208,7 +1210,7 @@ namespace OpenSim.Framework List folders, int version, bool fetchFolders, bool fetchItems); - void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item); + void SendInventoryItemDetails(InventoryItemBase[] items); /// /// Tell the client that we have created the item it requested. diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0d016a5b58..e87f6db0c6 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -136,7 +136,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event TeleportCancel OnTeleportCancel; public event RequestAvatarProperties OnRequestAvatarProperties; public event SetAlwaysRun OnSetAlwaysRun; - public event FetchInventory OnAgentDataUpdateRequest; + public event AgentDataUpdate OnAgentDataUpdateRequest; public event TeleportLocationRequest OnSetStartLocationRequest; public event UpdateAvatarProperties OnUpdateAvatarProperties; public event CreateNewInventoryItem OnCreateNewInventoryItem; @@ -2496,50 +2496,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP return descend; } - public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) + public void SendInventoryItemDetails(InventoryItemBase[] items) { // Fudge this value. It's only needed to make the CRC anyway const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff; FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply); - // TODO: don't create new blocks if recycling an old packet inventoryReply.AgentData.AgentID = AgentId; - inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1]; - inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock(); - inventoryReply.InventoryData[0].ItemID = item.ID; - inventoryReply.InventoryData[0].AssetID = item.AssetID; - inventoryReply.InventoryData[0].CreatorID = item.CreatorIdAsUuid; - inventoryReply.InventoryData[0].BaseMask = item.BasePermissions; - inventoryReply.InventoryData[0].CreationDate = item.CreationDate; - inventoryReply.InventoryData[0].Description = Util.StringToBytes256(item.Description); - inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions; - inventoryReply.InventoryData[0].FolderID = item.Folder; - inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType; - inventoryReply.InventoryData[0].Name = Util.StringToBytes256(item.Name); - inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions; - inventoryReply.InventoryData[0].OwnerID = item.Owner; - inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions; - inventoryReply.InventoryData[0].Type = (sbyte)item.AssetType; + int total = items.Length; + int count = 0; + for(int i = 0; i < items.Length; ++i) + { + if(count == 0) + { + if(total < 10) + { + inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[total]; + total = 0; + } + else + { + inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[10]; + total -= 10; + } + } - inventoryReply.InventoryData[0].GroupID = item.GroupID; - inventoryReply.InventoryData[0].GroupOwned = item.GroupOwned; - inventoryReply.InventoryData[0].GroupMask = item.GroupPermissions; - inventoryReply.InventoryData[0].Flags = item.Flags; - inventoryReply.InventoryData[0].SalePrice = item.SalePrice; - inventoryReply.InventoryData[0].SaleType = item.SaleType; + inventoryReply.InventoryData[count] = new FetchInventoryReplyPacket.InventoryDataBlock(); + FetchInventoryReplyPacket.InventoryDataBlock data = inventoryReply.InventoryData[count]; - inventoryReply.InventoryData[0].CRC = - Helpers.InventoryCRC( - 1000, 0, inventoryReply.InventoryData[0].InvType, - inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID, - inventoryReply.InventoryData[0].GroupID, 100, - inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID, - inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID, - FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, - FULL_MASK_PERMISSIONS); - inventoryReply.Header.Zerocoded = true; - OutPacket(inventoryReply, ThrottleOutPacketType.Asset); + data.ItemID = items[i].ID; + data.AssetID = items[i].AssetID; + data.CreatorID = items[i].CreatorIdAsUuid; + data.BaseMask = items[i].BasePermissions; + data.CreationDate = items[i].CreationDate; + + data.Description = Util.StringToBytes256(items[i].Description); + data.EveryoneMask = items[i].EveryOnePermissions; + data.FolderID = items[i].Folder; + data.InvType = (sbyte)items[i].InvType; + data.Name = Util.StringToBytes256(items[i].Name); + data.NextOwnerMask = items[i].NextPermissions; + data.OwnerID = items[i].Owner; + data.OwnerMask = items[i].CurrentPermissions; + data.Type = (sbyte)items[i].AssetType; + + data.GroupID = items[i].GroupID; + data.GroupOwned = items[i].GroupOwned; + data.GroupMask = items[i].GroupPermissions; + data.Flags = items[i].Flags; + data.SalePrice = items[i].SalePrice; + data.SaleType = items[i].SaleType; + + data.CRC = Helpers.InventoryCRC( + 1000, 0, data.InvType, data.Type, data.AssetID, + data.GroupID, 100, data.OwnerID, data.CreatorID, + data.ItemID, data.FolderID, FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + + ++count; + if(count == 10 || total == 0) + { + inventoryReply.Header.Zerocoded = true; + OutPacket(inventoryReply, ThrottleOutPacketType.Asset); + if(total == 0) + break; + count = 0; + } + } } protected void SendBulkUpdateInventoryFolder(InventoryFolderBase folderBase) @@ -10146,11 +10170,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (FetchInventoryx.AgentData.SessionID != SessionId || FetchInventoryx.AgentData.AgentID != AgentId) return; - for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) + FetchInventoryPacket.InventoryDataBlock[] data = FetchInventoryx.InventoryData; + + UUID[] items = new UUID[data.Length]; + UUID[] owners = new UUID[data.Length]; + + for (int i = 0; i < data.Length; ++i) { - OnFetchInventory?.Invoke(this, FetchInventoryx.InventoryData[i].ItemID, - FetchInventoryx.InventoryData[i].OwnerID); + items[i] =data[i].ItemID; + owners[i] = data[i].OwnerID; } + + OnFetchInventory?.Invoke(this, items, owners); } private void HandleFetchInventoryDescendents(Packet Pack) diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs index c874fdbfc9..976a205897 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs @@ -27,7 +27,8 @@ using System; using System.Collections.Generic; -using System.Reflection; +using System.Collections.Concurrent; +//using System.Reflection; using System.Threading; using log4net; using OpenMetaverse; @@ -39,12 +40,14 @@ namespace OpenSim.Region.Framework.Scenes class FetchHolder { public IClientAPI Client { get; private set; } - public UUID ItemID { get; private set; } + public UUID[] Items { get; private set; } + public UUID[] Owners { get; private set; } - public FetchHolder(IClientAPI client, UUID itemID) + public FetchHolder(IClientAPI client, UUID[] items, UUID[] owners) { Client = client; - ItemID = itemID; + Items = items; + Owners = owners; } } @@ -77,16 +80,15 @@ namespace OpenSim.Region.Framework.Scenes /// /// Queues fetch requests /// - Queue m_fetchHolder = new Queue(); + private static ConcurrentQueue m_fetchHolder = new ConcurrentQueue(); + static private object m_threadLock = new object(); + static private bool m_running; /// /// Signal whether a queue is currently being processed or not. /// - protected volatile bool m_processing; - public AsyncInventorySender(Scene scene) { - m_processing = false; m_scene = scene; } @@ -96,20 +98,20 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID) + public void HandleFetchInventory(IClientAPI remoteClient, UUID[] items, UUID[] owners) { - lock (m_fetchHolder) - { -// m_log.DebugFormat( -// "[ASYNC INVENTORY SENDER]: Putting request from {0} for {1} on queue", remoteClient.Name, itemID); + //m_log.DebugFormat( + // "[ASYNC INVENTORY SENDER]: Putting request from {0} for {1} on queue", remoteClient.Name, itemID); - m_fetchHolder.Enqueue(new FetchHolder(remoteClient, itemID)); - } - - if (!m_processing) + m_fetchHolder.Enqueue(new FetchHolder(remoteClient, items, owners)); + if (Monitor.TryEnter(m_threadLock)) { - m_processing = true; - ProcessQueue(); + if (!m_running) + { + m_running = true; + Util.FireAndForget(x => ProcessQueue()); + } + Monitor.Exit(m_threadLock); } } @@ -118,37 +120,42 @@ namespace OpenSim.Region.Framework.Scenes /// protected void ProcessQueue() { - FetchHolder fh = null; - - while (true) + lock(m_threadLock) { - lock (m_fetchHolder) + try { -// m_log.DebugFormat("[ASYNC INVENTORY SENDER]: {0} items left to process", m_fetchHolder.Count); + while (m_fetchHolder.TryDequeue(out FetchHolder fh)) + { + if (!fh.Client.IsActive) + continue; + // m_log.DebugFormat( + // "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID); - if (m_fetchHolder.Count == 0) - { - m_processing = false; - return; - } - else - { - fh = m_fetchHolder.Dequeue(); + var items = new List(); + for(int i = 0; i < fh.Items.Length; ++i ) + { + InventoryItemBase item = m_scene.InventoryService.GetItem(fh.Owners[i], fh.Items[i]); + if (item == null) + continue; + + /* + if (item.AssetType == (int)AssetType.Link) + { + InventoryItemBase itemlk = m_scene.InventoryService.GetItem(fh.Owners[i], item.AssetID); + if(itemlk != null) + items.Add(itemlk); + } + */ + + items.Add(item); + } + + fh.Client.SendInventoryItemDetails(items.ToArray()); + // TODO: Possibly log any failure } } - - if (!fh.Client.IsActive) - continue; - -// m_log.DebugFormat( -// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID); - - InventoryItemBase item = m_scene.InventoryService.GetItem(fh.Client.AgentId, fh.ItemID); - - if (item != null) - fh.Client.SendInventoryItemDetails(item.Owner, item); - - // TODO: Possibly log any failure + catch { } + m_running = false; } } } diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index 68d5122d60..a9a73ad571 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -28,7 +28,7 @@ using System; using System.Collections.Generic; using System.Collections.Concurrent; -using System.Reflection; +//using System.Reflection; using System.Threading; using log4net; using OpenMetaverse; @@ -52,7 +52,7 @@ namespace OpenSim.Region.Framework.Scenes /// public class AsyncSceneObjectGroupDeleter { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// /// Is the deleter currently enabled? /// @@ -145,8 +145,8 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.ErrorFormat( - "[ASYNC OBJECT DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace); + //m_log.ErrorFormat( + // "[ASYNC OBJECT DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace); } } // m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue."); diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 009c72e935..3ab60f93a7 100755 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -714,7 +714,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event AvatarPickerRequest OnAvatarPickerRequest; public event Action OnRequestAvatarsData; public event AddNewPrim OnAddPrim; - public event FetchInventory OnAgentDataUpdateRequest; + public event AgentDataUpdate OnAgentDataUpdateRequest; public event TeleportLocationRequest OnSetStartLocationRequest; public event RequestGodlikePowers OnRequestGodlikePowers; public event GodKickUser OnGodKickUser; @@ -1124,7 +1124,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) + public void SendInventoryItemDetails(InventoryItemBase[] items) { } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 1eb77a7a6a..18f04e8ac3 100755 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -348,7 +348,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event SpinStop OnSpinStop; public event ViewerEffectEventHandler OnViewerEffect; - public event FetchInventory OnAgentDataUpdateRequest; + public event AgentDataUpdate OnAgentDataUpdateRequest; public event TeleportLocationRequest OnSetStartLocationRequest; public event UpdateShape OnUpdatePrimShape; @@ -847,7 +847,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) + public virtual void SendInventoryItemDetails(InventoryItemBase[] items) { } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 929fa4a18a..bc74ccfa74 100755 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -141,7 +141,7 @@ namespace OpenSim.Tests.Common public event SpinStop OnSpinStop; public event ViewerEffectEventHandler OnViewerEffect; - public event FetchInventory OnAgentDataUpdateRequest; + public event AgentDataUpdate OnAgentDataUpdateRequest; public event TeleportLocationRequest OnSetStartLocationRequest; public event UpdateShape OnUpdatePrimShape; @@ -796,7 +796,7 @@ namespace OpenSim.Tests.Common { } - public virtual void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) + public virtual void SendInventoryItemDetails(InventoryItemBase[] items) { }