mirror of
https://github.com/opensim/opensim.git
synced 2026-08-05 00:46:02 +08:00
From: Alan Webb <alan_webb@us.ibm.com>
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.
This commit is contained in:
@@ -169,6 +169,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
private bool m_scriptListens_atTarget = false;
|
||||
private bool m_scriptListens_notAtTarget = false;
|
||||
|
||||
internal Dictionary<UUID, string> m_savedScriptState = null;
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
@@ -423,6 +425,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </param>
|
||||
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 <UUID><UUID> property
|
||||
xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>");
|
||||
xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>");
|
||||
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;
|
||||
|
||||
while (reader.Read())
|
||||
doc = new XmlDocument();
|
||||
doc.LoadXml(xmlData);
|
||||
parts = doc.GetElementsByTagName("RootPart");
|
||||
|
||||
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<parts.Count ; i++)
|
||||
{
|
||||
sr = new StringReader(parts[i].InnerXml);
|
||||
reader = new XmlTextReader(sr);
|
||||
SceneObjectPart part = SceneObjectPart.FromXml(reader);
|
||||
linkNum = part.LinkNum;
|
||||
AddPart(part);
|
||||
part.LinkNum = linkNum;
|
||||
part.TrimPermissions();
|
||||
part.StoreUndoState();
|
||||
reader.Close();
|
||||
sr.Close();
|
||||
}
|
||||
|
||||
// Script state may, or may not, exist. Not having any, is NOT
|
||||
// ever a problem.
|
||||
|
||||
LoadScriptState(doc);
|
||||
|
||||
}
|
||||
catch (XmlException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[SCENE]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData);
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
sr.Close();
|
||||
//m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
|
||||
}
|
||||
|
||||
@@ -493,6 +506,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
protected void SetFromXml(string xmlData)
|
||||
{
|
||||
|
||||
//m_log.DebugFormat("[SOG]: Starting deserialization of SOG");
|
||||
//int time = System.Environment.TickCount;
|
||||
|
||||
@@ -504,42 +518,46 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>");
|
||||
xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>");
|
||||
|
||||
StringReader sr = new StringReader(xmlData);
|
||||
XmlTextReader reader = new XmlTextReader(sr);
|
||||
reader.Read();
|
||||
|
||||
reader.ReadStartElement("SceneObjectGroup");
|
||||
SetRootPart(CreatePartFromXml(reader));
|
||||
|
||||
reader.Read();
|
||||
bool more = true;
|
||||
|
||||
while (more)
|
||||
try
|
||||
{
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
if (reader.Name == "SceneObjectPart")
|
||||
{
|
||||
SceneObjectPart part = CreatePartFromXml(reader);
|
||||
AddPart(part);
|
||||
part.StoreUndoState();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("found unexpected element: " + reader.Name);
|
||||
reader.Read();
|
||||
}
|
||||
break;
|
||||
case XmlNodeType.EndElement:
|
||||
reader.Read();
|
||||
break;
|
||||
}
|
||||
more = !reader.EOF;
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
sr.Close();
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(xmlData);
|
||||
|
||||
XmlNodeList parts = doc.GetElementsByTagName("SceneObjectPart");
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Then deal with the rest
|
||||
for(int i=1; i<parts.Count; i++)
|
||||
{
|
||||
StringReader sr = new StringReader(parts[i].OuterXml);
|
||||
XmlTextReader reader = new XmlTextReader(sr);
|
||||
SceneObjectPart part = CreatePartFromXml(reader);
|
||||
AddPart(part);
|
||||
part.StoreUndoState();
|
||||
reader.Close();
|
||||
sr.Close();
|
||||
}
|
||||
|
||||
// Script state may, or may not, exist. Not having any, is NOT
|
||||
// ever a problem.
|
||||
|
||||
LoadScriptState(doc);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[SCENE]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData);
|
||||
}
|
||||
|
||||
//m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
|
||||
}
|
||||
@@ -567,6 +585,23 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
}
|
||||
|
||||
private void LoadScriptState(XmlDocument doc)
|
||||
{
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("SavedScriptState");
|
||||
if(nodes.Count > 0)
|
||||
{
|
||||
m_savedScriptState = new Dictionary<UUID, string>();
|
||||
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<UUID,string> states = new Dictionary<UUID,string>();
|
||||
|
||||
// Capture script state while holding the lock
|
||||
lock (m_parts)
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
Dictionary<UUID,string> 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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user