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. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 210 ++++++++++++++------- .../Framework/Scenes/SceneObjectPartInventory.cs | 19 ++ 2 files changed, 162 insertions(+), 67 deletions(-) (limited to 'OpenSim/Region/Framework') 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