From 7c542be83392b71af4bc9f9fdf029fa1952cef25 Mon Sep 17 00:00:00 2001
From: "Huaiyu (Kitty) Liu" <huaiyu.liu@intel.com>
Date: Mon, 6 Jun 2011 15:22:23 -0700
Subject: [PATCH] When TaskInventory value is synced across, each receiver will
 also call Inventory.ForceInventoryPersistence, so that PSA will see
 HasInventoryChanged set to true and do proper persistence backup.

Also, added ScheduleSyncUpdate in UpdateInventoryItem, so that the new
TaskInventory item will be propagated to all actors.
---
 .../SymmetricSync/RegionSyncModule.cs         |  8 +++
 .../Framework/Interfaces/IEntityInventory.cs  |  3 +
 .../Framework/Scenes/Scene.Inventory.cs       | 13 ++--
 .../Scenes/SceneObjectGroup.Inventory.cs      | 28 ++++++++
 .../Scenes/SceneObjectPartInventory.cs        | 65 +++++++++++++++++++
 5 files changed, 113 insertions(+), 4 deletions(-)

diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
index b72add27d3..a7b0e73ac6 100644
--- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
+++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
@@ -4603,6 +4603,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
                                 //UpdateSOPProperty(part, m_propertiesSyncInfo[property]);
                                 SetSOPPropertyValue(part, property);
                                 propertiesUpdated.Add(property);
+
+                                if (property == SceneObjectPartSyncProperties.TaskInventory)
+                                {
+                                    //Mark the inventory as has changed, for proper backup
+                                    part.Inventory.ForceInventoryPersistence();
+                                }
+
+                                part.ParentGroup.HasGroupChanged = true;
                             }
                         }
                         catch (Exception e)
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index d34a8a8f5a..17350df79f 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -233,5 +233,8 @@ namespace OpenSim.Region.Framework.Interfaces
         /// A <see cref="Dictionary`2"/>
         /// </returns>
         Dictionary<UUID, string> GetScriptStates();
+
+        //DSG
+        bool UpdateInventoryItemBySync(TaskInventoryItem item);
     }
 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 6c7a359934..f22c893110 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -327,7 +327,7 @@ namespace OpenSim.Region.Framework.Scenes
         //Scene does permission checking, asset creation and storing, then informs Script Engine to 
         //update the script.
         ////////////////////////////////////////////////////////////////////////////////////////////////
-        //Only should be called when this is the cached Scene of script engine 
+        //Only should be called when this is the local Scene of script engine 
         public ArrayList OnUpdateScript(UUID avatarID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
         {
             ArrayList errors = new ArrayList();
@@ -353,7 +353,7 @@ namespace OpenSim.Region.Framework.Scenes
 
             // Update item with new asset
             item.AssetID = newAssetID;
-            group.UpdateInventoryItem(item);
+            group.UpdateInventoryItemBySync(item);
             m_log.Debug("UpdateInventoryItem on object "+group.UUID);
 
             if (isScriptRunning)
@@ -419,9 +419,14 @@ namespace OpenSim.Region.Framework.Scenes
                 return new ArrayList();
             }
 
-            // Update item with new asset
+            // Update item with new asset.
+            // The actor that initiate the UpdateScript event should also send out
+            // a sync message for the updated task inventory. In case that sync message is 
+            // not here year, we retrieve and update the task item -- w/o marking that
+            // the taskinventory is modified here, so that when the sync message is here,
+            // the actor and timestamp info will be copied.
             item.AssetID = newAssetID;
-            group.UpdateInventoryItem(item);
+            group.UpdateInventoryItemBySync(item);
             m_log.Debug("UpdateInventoryItem on object "+group.UUID);
 
             if (isScriptRunning)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 61fde6f0e9..be480f0172 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -398,5 +398,33 @@ namespace OpenSim.Region.Framework.Scenes
                 parts[i].Inventory.SuspendScripts();
         }
         #endregion REGION SYNC
+
+        #region DSG SYNC
+        /// <summary>
+        /// Update an existing inventory item.
+        /// </summary>
+        /// <param name="item">The updated item.  An item with the same id must already exist
+        /// in this prim's inventory</param>
+        /// <returns>false if the item did not exist, true if the update occurred succesfully</returns>
+        public bool UpdateInventoryItemBySync(TaskInventoryItem item)
+        {
+            SceneObjectPart part = GetChildPart(item.ParentPartID);
+            if (part != null)
+            {
+                part.Inventory.UpdateInventoryItemBySync(item);
+
+                return true;
+            }
+            else
+            {
+                m_log.ErrorFormat(
+                    "[PRIM INVENTORY]: " +
+                    "Couldn't find prim ID {0} to update item {1}, {2}",
+                    item.ParentPartID, item.Name, item.ItemID);
+            }
+
+            return false;
+        }
+        #endregion 
     }
 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 1ce7076e07..21a670fe7d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -727,6 +727,9 @@ namespace OpenSim.Region.Framework.Scenes
                 {
                     HasInventoryChanged = true;
                     m_part.ParentGroup.HasGroupChanged = true;
+
+                    //DSG
+                    m_part.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.TaskInventory});
                 }
                 
                 return true;
@@ -1182,6 +1185,68 @@ namespace OpenSim.Region.Framework.Scenes
             }
         }
         #endregion REGION SYNC
+
+        #region DSG SYNC
+        /// <summary>
+        /// Update an existing inventory item.
+        /// </summary>
+        /// <param name="item">The updated item.  An item with the same id must already exist
+        /// in this prim's inventory.</param>
+        /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
+        public bool UpdateInventoryItemBySync(TaskInventoryItem item)
+        {
+            return UpdateInventoryItemBySync(item, true, true);
+        }
+
+        //Similar to UpdateInventoryItem except that ScheduleSyncUpdate is not triggered
+        private bool UpdateInventoryItemBySync(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
+        {
+            TaskInventoryItem it = GetInventoryItem(item.ItemID);
+            if (it != null)
+            {
+//                m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
+                
+                item.ParentID = m_part.UUID;
+                item.ParentPartID = m_part.UUID;
+
+                // If group permissions have been set on, check that the groupID is up to date in case it has
+                // changed since permissions were last set.
+                if (item.GroupPermissions != (uint)PermissionMask.None)
+                    item.GroupID = m_part.GroupID;
+
+                if (item.AssetID == UUID.Zero)
+                    item.AssetID = it.AssetID;
+
+                lock (m_items)
+                {
+                    m_items[item.ItemID] = item;
+                    m_inventorySerial++;
+                }
+                
+                if (fireScriptEvents)
+                    m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
+                
+                if (considerChanged)
+                {
+                    HasInventoryChanged = true;
+                    m_part.ParentGroup.HasGroupChanged = true;
+                }
+                
+                return true;
+            }
+            else
+            {
+                m_log.ErrorFormat(
+                    "[PRIM INVENTORY]: " +
+                    "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
+                    item.ItemID, m_part.Name, m_part.UUID, 
+                    m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
+            }
+            return false;
+
+        }
+
+        #endregion DSG SYNC
     }
 
     /*