From 7dbcf0570f0f5d521373df6d381c2d75dc2845d3 Mon Sep 17 00:00:00 2001 From: Dr Scofield Date: Wed, 22 Apr 2009 18:09:55 +0000 Subject: From: Alan Webb Changes to enable script state persistence across non-restart serialization situations (inventory/OAR/attachments) Also fixing test cases for OAR and IAR so they don't barf with the new code. --- OpenSim/Framework/TaskInventoryItem.cs | 11 ++ .../Archiver/Tests/InventoryArchiverTests.cs | 1 + .../World/Archiver/Tests/ArchiverTests.cs | 15 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 210 ++++++++++++++------- .../Framework/Scenes/SceneObjectPartInventory.cs | 19 ++ 5 files changed, 185 insertions(+), 71 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs index 43d28e7..66da564 100644 --- a/OpenSim/Framework/TaskInventoryItem.cs +++ b/OpenSim/Framework/TaskInventoryItem.cs @@ -120,6 +120,7 @@ namespace OpenSim.Framework private UUID _permsGranter; private int _permsMask; private int _type = 0; + private UUID _oldID; public UUID AssetID { get { @@ -220,6 +221,15 @@ namespace OpenSim.Framework } } + public UUID OldItemID { + get { + return _oldID; + } + set { + _oldID = value; + } + } + public UUID LastOwnerID { get { return _lastOwnerID; @@ -327,6 +337,7 @@ namespace OpenSim.Framework /// The new part ID to which this item belongs public void ResetIDs(UUID partID) { + _oldID = _itemID; _itemID = UUID.Random(); _parentPartID = partID; _parentID = partID; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 01e5ae0..8e6b461 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -96,6 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests part1.Name = partName; object1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(object1, false); } UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 3ffabbd..a25b25f 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -201,11 +201,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); Vector3 offsetPosition = new Vector3(20, 25, 30); + SerialiserModule serialiserModule = new SerialiserModule(); + ArchiverModule archiverModule = new ArchiverModule(); + + Scene scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + SceneObjectPart part1 = new SceneObjectPart( UUID.Zero, shape, groupPosition, rotationOffset, offsetPosition); part1.Name = part1Name; SceneObjectGroup object1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(object1, false); string object1FileName = string.Format( "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", @@ -218,11 +225,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - SerialiserModule serialiserModule = new SerialiserModule(); - ArchiverModule archiverModule = new ArchiverModule(); + // SerialiserModule serialiserModule = new SerialiserModule(); + // ArchiverModule archiverModule = new ArchiverModule(); - Scene scene = SceneSetupHelpers.SetupScene(); - SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + // Scene scene = SceneSetupHelpers.SetupScene(); + // SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); archiverModule.DearchiveRegion(archiveReadStream); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 2552a3d..364da72 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -169,6 +169,8 @@ namespace OpenSim.Region.Framework.Scenes private bool m_scriptListens_atTarget = false; private bool m_scriptListens_notAtTarget = false; + internal Dictionary m_savedScriptState = null; + #region Properties /// @@ -423,6 +425,7 @@ namespace OpenSim.Region.Framework.Scenes /// public SceneObjectGroup(UUID fromUserInventoryItemID, string xmlData, bool isOriginalXmlFormat) { + if (!isOriginalXmlFormat) throw new Exception("This constructor must specify the xml is in OpenSim's original format"); @@ -436,50 +439,60 @@ namespace OpenSim.Region.Framework.Scenes // Handle Nested property xmlData = xmlData.Replace("", ""); xmlData = xmlData.Replace("", ""); - StringReader sr = new StringReader(xmlData); - XmlTextReader reader = new XmlTextReader(sr); try { - reader.Read(); - reader.ReadStartElement("SceneObjectGroup"); - reader.ReadStartElement("RootPart"); - SetRootPart(SceneObjectPart.FromXml(fromUserInventoryItemID, reader)); - reader.ReadEndElement(); + StringReader sr; + XmlTextReader reader; + XmlNodeList parts; + XmlDocument doc; + int linkNum; + + doc = new XmlDocument(); + doc.LoadXml(xmlData); + parts = doc.GetElementsByTagName("RootPart"); - while (reader.Read()) + if(parts.Count == 0) { - switch (reader.NodeType) - { - case XmlNodeType.Element: - if (reader.Name == "Part") - { - reader.Read(); - SceneObjectPart part = SceneObjectPart.FromXml(reader); - - // We reset the link number in order to make sure that the persisted linkset order is - int linkNum = part.LinkNum; - AddPart(part); - part.LinkNum = linkNum; - - part.TrimPermissions(); - part.StoreUndoState(); - } - break; - - case XmlNodeType.EndElement: - break; - } + throw new Exception("[SCENE] Invalid Xml format - no root part"); + } + else + { + sr = new StringReader(parts[0].InnerXml); + reader = new XmlTextReader(sr); + SetRootPart(SceneObjectPart.FromXml(fromUserInventoryItemID, reader)); + reader.Close(); + sr.Close(); + } + + parts = doc.GetElementsByTagName("Part"); + + for (int i=0; i", ""); xmlData = xmlData.Replace("", ""); - StringReader sr = new StringReader(xmlData); - XmlTextReader reader = new XmlTextReader(sr); - reader.Read(); + try + { + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlData); + + XmlNodeList parts = doc.GetElementsByTagName("SceneObjectPart"); - reader.ReadStartElement("SceneObjectGroup"); - SetRootPart(CreatePartFromXml(reader)); + // Process the root part first + if(parts.Count > 0) + { + StringReader sr = new StringReader(parts[0].OuterXml); + XmlTextReader reader = new XmlTextReader(sr); + SetRootPart(CreatePartFromXml(reader)); + reader.Close(); + sr.Close(); + } - reader.Read(); - bool more = true; + // Then deal with the rest + for(int i=1; i 0) + { + m_savedScriptState = new Dictionary(); + foreach(XmlNode node in nodes) + { + if(node.Attributes["UUID"] != null) + { + UUID itemid = new UUID(node.Attributes["UUID"].Value); + m_savedScriptState.Add(itemid, node.InnerXml); + } + } + } + } + public void SetFromAssetID(UUID AssetId) { lock (m_parts) @@ -748,8 +783,9 @@ namespace OpenSim.Region.Framework.Scenes } } - writer.WriteEndElement(); - writer.WriteEndElement(); + writer.WriteEndElement(); // OtherParts + SaveScriptedState(writer); + writer.WriteEndElement(); // SceneObjectGroup //m_log.DebugFormat("[SOG]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); } @@ -769,6 +805,7 @@ namespace OpenSim.Region.Framework.Scenes public void ToXml2(XmlTextWriter writer) { + //m_log.DebugFormat("[SOG]: Starting serialization of SOG {0} to XML2", Name); //int time = System.Environment.TickCount; @@ -787,9 +824,48 @@ namespace OpenSim.Region.Framework.Scenes } } - writer.WriteEndElement(); - writer.WriteEndElement(); + writer.WriteEndElement(); // End of OtherParts + SaveScriptedState(writer); + writer.WriteEndElement(); // End of SceneObjectGroup + //m_log.DebugFormat("[SOG]: Finished serialization of SOG {0} to XML2, {1}ms", Name, System.Environment.TickCount - time); + + } + + private void SaveScriptedState(XmlTextWriter writer) + { + + XmlDocument doc = new XmlDocument(); + Dictionary states = new Dictionary(); + + // Capture script state while holding the lock + lock (m_parts) + { + foreach (SceneObjectPart part in m_parts.Values) + { + Dictionary pstates = part.Inventory.GetScriptStates(); + foreach (UUID itemid in pstates.Keys) + { + states.Add(itemid, pstates[itemid]); + } + } + } + + if(states.Count > 0) + { + // Now generate the necessary XML wrappings + writer.WriteStartElement(String.Empty, "GroupScriptStates", String.Empty); + foreach(UUID itemid in states.Keys) + { + doc.LoadXml(states[itemid]); + writer.WriteStartElement(String.Empty, "SavedScriptState", String.Empty); + writer.WriteAttributeString(String.Empty, "UUID", String.Empty, itemid.ToString()); + writer.WriteRaw(doc.DocumentElement.OuterXml); // Writes ScriptState element + writer.WriteEndElement(); // End of SavedScriptState + } + writer.WriteEndElement(); // End of GroupScriptStates + } + } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 9666525..e952799 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -26,6 +26,7 @@ */ using System; +using System.IO; using System.Collections.Generic; using System.Reflection; using OpenMetaverse; @@ -264,6 +265,8 @@ namespace OpenSim.Region.Framework.Scenes } else { + if(m_part.ParentGroup.m_savedScriptState != null) + RestoreSavedScriptState(item.OldItemID, item.ItemID); m_items[item.ItemID].PermsMask = 0; m_items[item.ItemID].PermsGranter = UUID.Zero; string script = Utils.BytesToString(asset.Data); @@ -276,6 +279,22 @@ namespace OpenSim.Region.Framework.Scenes } } + static System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + + private void RestoreSavedScriptState(UUID oldID, UUID newID) + { + if(m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID)) + { + string fpath = Path.Combine("ScriptEngines/"+m_part.ParentGroup.Scene.RegionInfo.RegionID.ToString(), + newID.ToString()+".state"); + FileStream fs = File.Create(fpath); + Byte[] buffer = enc.GetBytes(m_part.ParentGroup.m_savedScriptState[oldID]); + fs.Write(buffer,0,buffer.Length); + fs.Close(); + m_part.ParentGroup.m_savedScriptState.Remove(oldID); + } + } + /// /// Start a script which is in this prim's inventory. /// -- cgit v1.1