From 3eaaaa0d994c7c994d471d511127ed0ba66ab9bc Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Fri, 24 Dec 2010 08:50:00 -0800
Subject: One more pass at object inventory. This time, fix
 SceneObjectPartInventory so that it makes sure that the file is added to
 Xfer's before it signals the client to come and get it. This allows the
 simplification of the logic of Xfer's.

---
 .../Region/CoreModules/Agent/Xfer/XferModule.cs    |  94 +++-----------
 .../Framework/Scenes/SceneObjectPartInventory.cs   | 136 ++++++++++-----------
 2 files changed, 82 insertions(+), 148 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
index df4ff05..b8e2820 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<string, XferRequest> Requests = new Dictionary<string, XferRequest>();
         private Dictionary<string, FileData> NewFiles = new Dictionary<string, FileData>();
         private Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>();
-        
+
+        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
 
+        /// <summary>
+        /// 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.
+        /// </summary>
+        /// <param name="fileName"></param>
+        /// <param name="data"></param>
+        /// <returns></returns>
         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 1177378..39ebaef 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -766,102 +766,102 @@ 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;
-                return true;
-            }
 
-            return false;
-        }
+                InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
 
-        /// <summary>
-        /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
-        /// </summary>
-        /// <param name="xferManager"></param>
-        public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
-        {
-            bool changed = CreateInventoryFileName();
+                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;
 
-            InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
+                        invString.AddItemStart();
+                        invString.AddNameValueLine("item_id", item.ItemID.ToString());
+                        invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
 
-            lock (m_items)
-            {
-                if (m_inventorySerial == 0) // No inventory
-                {
-                    client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
-                    return;
-                }
+                        invString.AddPermissionsStart();
 
-                client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
-                        Util.StringToBytes256(m_inventoryFileName));
+                        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));
 
-                if (!changed)
-                {
-                    if (m_inventoryFileData.Length > 2)
-                    {
-                        xferManager.AddNewFile(m_inventoryFileName,
-                                m_inventoryFileData);
-                        return;
-                    }
-                }
+                        invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
+                        invString.AddNameValueLine("owner_id", ownerID.ToString());
 
-                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.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
 
-                    invString.AddItemStart();
-                    invString.AddNameValueLine("item_id", item.ItemID.ToString());
-                    invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
+                        invString.AddNameValueLine("group_id", item.GroupID.ToString());
+                        invString.AddSectionEnd();
 
-                    invString.AddPermissionsStart();
+                        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.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.AddSaleStart();
+                        invString.AddNameValueLine("sale_type", "not");
+                        invString.AddNameValueLine("sale_price", "0");
+                        invString.AddSectionEnd();
 
-                    invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
-                    invString.AddNameValueLine("owner_id", ownerID.ToString());
+                        invString.AddNameValueLine("name", item.Name + "|");
+                        invString.AddNameValueLine("desc", item.Description + "|");
 
-                    invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
+                        invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
+                        invString.AddSectionEnd();
+                    }
+                }
 
-                    invString.AddNameValueLine("group_id", item.GroupID.ToString());
-                    invString.AddSectionEnd();
+                m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
 
-                    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));
+                return true;
+            }
 
-                    invString.AddSaleStart();
-                    invString.AddNameValueLine("sale_type", "not");
-                    invString.AddNameValueLine("sale_price", "0");
-                    invString.AddSectionEnd();
+            // No need to recreate, the existing file is fine
+            return false;
+        }
 
-                    invString.AddNameValueLine("name", item.Name + "|");
-                    invString.AddNameValueLine("desc", item.Description + "|");
+        /// <summary>
+        /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
+        /// </summary>
+        /// <param name="xferManager"></param>
+        public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
+        {
+            bool changed = CreateInventoryFile();
 
-                    invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
-                    invString.AddSectionEnd();
-                }
+            if (m_inventorySerial == 0) // No inventory
+            {
+                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));
         }
 
         /// <summary>
-- 
cgit v1.1