diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs index df4ff053f6..b8e2820db7 100644 --- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs +++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs @@ -27,7 +27,9 @@ using System; using System.Collections.Generic; +using System.Reflection; using Nini.Config; +using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -37,12 +39,11 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer { public class XferModule : IRegionModule, IXfer { - private static uint counter = 0; private Scene m_scene; - private Dictionary Requests = new Dictionary(); private Dictionary NewFiles = new Dictionary(); private Dictionary Transfers = new Dictionary(); - + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public struct XferRequest { @@ -90,6 +91,14 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer #region IXfer Members + /// + /// Let the Xfer module know about a file that the client is about to request. + /// Caller is responsible for making sure that the file is here before + /// the client starts the XferRequest. + /// + /// + /// + /// public bool AddNewFile(string fileName, byte[] data) { lock (NewFiles) @@ -97,7 +106,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer if (NewFiles.ContainsKey(fileName)) { NewFiles[fileName].Count++; - //Console.WriteLine("AddNewFile " + fileName + " counter=" + NewFiles[fileName].Count); + NewFiles[fileName].Data = data; } else { @@ -105,23 +114,9 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer fd.Count = 1; fd.Data = data; NewFiles.Add(fileName, fd); - //Console.WriteLine("AddNewFile " + fileName); } } - // This happens when the Xfer request ends up coming before - // the fileName is added by this method. That may happen when - // the file generation (the event that calle this method) - // takes a long time. In this case, we need to kick the - // Xfer request mannually. - if (Requests.ContainsKey(fileName)) - { - //Console.WriteLine("*** AddNewFile Requests.Contains " + fileName); - - RequestXfer(Requests[fileName].remoteClient, Requests[fileName].xferID, fileName); - Requests.Remove(fileName); - } - return true; } @@ -144,23 +139,17 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer { lock (NewFiles) { - //Console.WriteLine("---- RequestXfer " + fileName + " ----"); - if (NewFiles.ContainsKey(fileName)) { - //Console.WriteLine("NewFiles.ContainsKey " + fileName + " with count=" + NewFiles[fileName].Count); if (!Transfers.ContainsKey(xferID)) { - //Console.WriteLine("!Transfers.ContainsKey("+xferID+")"); byte[] fileData = NewFiles[fileName].Data; XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); Transfers.Add(xferID, transaction); if (transaction.StartSend()) - { RemoveXferData(xferID); - } // The transaction for this file is either complete or on its way RemoveOrDecrement(fileName); @@ -168,42 +157,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer } } else - { - ////Console.WriteLine("*** ! NewFiles.ContainsKey " + fileName); - //if (RequestTime.Count > 0) - //{ - // //Console.WriteLine("RequestTime.Count > 0"); - // TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - RequestTime[0].timeStamp.Ticks); - // if (ts.TotalSeconds > 30) - // { - // Console.WriteLine("ts.TotalSeconds > 30"); - // Requests.Remove(RequestTime[0].fileName); - // RequestTime.RemoveAt(0); - // // Do we want to abort this here? - // //remoteClient.SendAbortXfer(xferID); - // } - //} - - XferRequest nRequest = new XferRequest(); - nRequest.remoteClient = remoteClient; - nRequest.xferID = xferID; - nRequest.fileName = fileName; - nRequest.timeStamp = DateTime.UtcNow; - nRequest.fileName = fileName; - - if (!Requests.ContainsKey(fileName)) - { - //Console.WriteLine("**** !Requests.ContainsKey(" + fileName + ")"); - Requests.Add(fileName, nRequest); - } - else - { - //Console.WriteLine("**** Requests.ContainsKey(" + fileName + ")"); - Requests.Add(fileName + "-" + counter.ToString(), nRequest); - counter++; - } - - } + m_log.WarnFormat("[Xfer]: {0} not found", fileName); } } @@ -220,15 +174,6 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer RemoveXferData(xferID); RemoveOrDecrement(dl.FileName); } - else - { - if (Requests.ContainsKey(dl.FileName)) - { - XferRequest req = Requests[dl.FileName]; - req.timeStamp = DateTime.UtcNow; - Requests[dl.FileName] = req; - } - } } } } @@ -238,19 +183,12 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer // NewFiles must be locked! if (Transfers.ContainsKey(xferID)) { - // Qualifier distinguishes between the OpenMetaverse version and the nested class - XferModule.XferDownLoad xferItem = Transfers[xferID]; //string filename = xferItem.FileName; Transfers.Remove(xferID); xferItem.Data = new byte[0]; // Clear the data xferItem.DataPointer = 0; - // If the abort comes in - - if (Requests.ContainsKey(xferItem.FileName)) - Requests.Remove(xferItem.FileName); - } } @@ -272,13 +210,9 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer if (NewFiles.ContainsKey(fileName)) { if (NewFiles[fileName].Count == 1) - { NewFiles.Remove(fileName); - } else - { NewFiles[fileName].Count--; - } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 1177378076..39ebaefcab 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -766,16 +766,71 @@ namespace OpenSim.Region.Framework.Scenes return -1; } - private bool CreateInventoryFileName() + private bool CreateInventoryFile() { if (m_inventoryFileName == String.Empty || m_inventoryFileNameSerial < m_inventorySerial) { + // Something changed, we need to create a new file m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; m_inventoryFileNameSerial = m_inventorySerial; + + InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); + + lock (m_items) + { + foreach (TaskInventoryItem item in m_items.Values) + { + UUID ownerID = item.OwnerID; + uint everyoneMask = 0; + uint baseMask = item.BasePermissions; + uint ownerMask = item.CurrentPermissions; + uint groupMask = item.GroupPermissions; + + invString.AddItemStart(); + invString.AddNameValueLine("item_id", item.ItemID.ToString()); + invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); + + invString.AddPermissionsStart(); + + invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); + invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); + invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); + invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); + + invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); + invString.AddNameValueLine("owner_id", ownerID.ToString()); + + invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); + + invString.AddNameValueLine("group_id", item.GroupID.ToString()); + invString.AddSectionEnd(); + + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); + invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); + invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); + + invString.AddSaleStart(); + invString.AddNameValueLine("sale_type", "not"); + invString.AddNameValueLine("sale_price", "0"); + invString.AddSectionEnd(); + + invString.AddNameValueLine("name", item.Name + "|"); + invString.AddNameValueLine("desc", item.Description + "|"); + + invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); + invString.AddSectionEnd(); + } + } + + m_inventoryFileData = Utils.StringToBytes(invString.BuildString); + return true; } + // No need to recreate, the existing file is fine return false; } @@ -785,83 +840,28 @@ namespace OpenSim.Region.Framework.Scenes /// public void RequestInventoryFile(IClientAPI client, IXfer xferManager) { - bool changed = CreateInventoryFileName(); + bool changed = CreateInventoryFile(); - InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); - - lock (m_items) + if (m_inventorySerial == 0) // No inventory { - if (m_inventorySerial == 0) // No inventory - { - client.SendTaskInventory(m_part.UUID, 0, new byte[0]); - return; - } - - client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, - Util.StringToBytes256(m_inventoryFileName)); - - if (!changed) - { - if (m_inventoryFileData.Length > 2) - { - xferManager.AddNewFile(m_inventoryFileName, - m_inventoryFileData); - return; - } - } - - foreach (TaskInventoryItem item in m_items.Values) - { - UUID ownerID = item.OwnerID; - uint everyoneMask = 0; - uint baseMask = item.BasePermissions; - uint ownerMask = item.CurrentPermissions; - uint groupMask = item.GroupPermissions; - - invString.AddItemStart(); - invString.AddNameValueLine("item_id", item.ItemID.ToString()); - invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); - - invString.AddPermissionsStart(); - - invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); - invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); - invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); - invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); - - invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); - invString.AddNameValueLine("owner_id", ownerID.ToString()); - - invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); - - invString.AddNameValueLine("group_id", item.GroupID.ToString()); - invString.AddSectionEnd(); - - invString.AddNameValueLine("asset_id", item.AssetID.ToString()); - invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); - invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); - invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); - - invString.AddSaleStart(); - invString.AddNameValueLine("sale_type", "not"); - invString.AddNameValueLine("sale_price", "0"); - invString.AddSectionEnd(); - - invString.AddNameValueLine("name", item.Name + "|"); - invString.AddNameValueLine("desc", item.Description + "|"); - - invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); - invString.AddSectionEnd(); - } + client.SendTaskInventory(m_part.UUID, 0, new byte[0]); + return; } - m_inventoryFileData = Utils.StringToBytes(invString.BuildString); + // In principle, we should only do the rest if the inventory changed; + // by sending m_inventorySerial to the client, it ought to know + // that nothing changed and that it doesn't need to request the file. + // Unfortunately, it doesn't look like the client optimizes this; + // the client seems to always come back and request the Xfer, + // no matter what value m_inventorySerial has. if (m_inventoryFileData.Length > 2) - { + // Add the file for Xfer xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); - } + + // Tell the client we're ready to Xfer the file + client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, + Util.StringToBytes256(m_inventoryFileName)); } ///