diff options
author | Dr Scofield | 2009-04-22 18:09:55 +0000 |
---|---|---|
committer | Dr Scofield | 2009-04-22 18:09:55 +0000 |
commit | 7dbcf0570f0f5d521373df6d381c2d75dc2845d3 (patch) | |
tree | 63d7b2429f78b4b66e9194c5ee35476ac9b1e5e0 /OpenSim/Region/Framework/Scenes | |
parent | more cleanup (diff) | |
download | opensim-SC-7dbcf0570f0f5d521373df6d381c2d75dc2845d3.zip opensim-SC-7dbcf0570f0f5d521373df6d381c2d75dc2845d3.tar.gz opensim-SC-7dbcf0570f0f5d521373df6d381c2d75dc2845d3.tar.bz2 opensim-SC-7dbcf0570f0f5d521373df6d381c2d75dc2845d3.tar.xz |
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.
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 210 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 19 |
2 files changed, 162 insertions, 67 deletions
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 | |||
169 | private bool m_scriptListens_atTarget = false; | 169 | private bool m_scriptListens_atTarget = false; |
170 | private bool m_scriptListens_notAtTarget = false; | 170 | private bool m_scriptListens_notAtTarget = false; |
171 | 171 | ||
172 | internal Dictionary<UUID, string> m_savedScriptState = null; | ||
173 | |||
172 | #region Properties | 174 | #region Properties |
173 | 175 | ||
174 | /// <summary> | 176 | /// <summary> |
@@ -423,6 +425,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
423 | /// </param> | 425 | /// </param> |
424 | public SceneObjectGroup(UUID fromUserInventoryItemID, string xmlData, bool isOriginalXmlFormat) | 426 | public SceneObjectGroup(UUID fromUserInventoryItemID, string xmlData, bool isOriginalXmlFormat) |
425 | { | 427 | { |
428 | |||
426 | if (!isOriginalXmlFormat) | 429 | if (!isOriginalXmlFormat) |
427 | throw new Exception("This constructor must specify the xml is in OpenSim's original format"); | 430 | throw new Exception("This constructor must specify the xml is in OpenSim's original format"); |
428 | 431 | ||
@@ -436,50 +439,60 @@ namespace OpenSim.Region.Framework.Scenes | |||
436 | // Handle Nested <UUID><UUID> property | 439 | // Handle Nested <UUID><UUID> property |
437 | xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>"); | 440 | xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>"); |
438 | xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>"); | 441 | xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>"); |
439 | StringReader sr = new StringReader(xmlData); | ||
440 | XmlTextReader reader = new XmlTextReader(sr); | ||
441 | 442 | ||
442 | try | 443 | try |
443 | { | 444 | { |
444 | reader.Read(); | ||
445 | reader.ReadStartElement("SceneObjectGroup"); | ||
446 | reader.ReadStartElement("RootPart"); | ||
447 | SetRootPart(SceneObjectPart.FromXml(fromUserInventoryItemID, reader)); | ||
448 | 445 | ||
449 | reader.ReadEndElement(); | 446 | StringReader sr; |
447 | XmlTextReader reader; | ||
448 | XmlNodeList parts; | ||
449 | XmlDocument doc; | ||
450 | int linkNum; | ||
451 | |||
452 | doc = new XmlDocument(); | ||
453 | doc.LoadXml(xmlData); | ||
454 | parts = doc.GetElementsByTagName("RootPart"); | ||
450 | 455 | ||
451 | while (reader.Read()) | 456 | if(parts.Count == 0) |
452 | { | 457 | { |
453 | switch (reader.NodeType) | 458 | throw new Exception("[SCENE] Invalid Xml format - no root part"); |
454 | { | 459 | } |
455 | case XmlNodeType.Element: | 460 | else |
456 | if (reader.Name == "Part") | 461 | { |
457 | { | 462 | sr = new StringReader(parts[0].InnerXml); |
458 | reader.Read(); | 463 | reader = new XmlTextReader(sr); |
459 | SceneObjectPart part = SceneObjectPart.FromXml(reader); | 464 | SetRootPart(SceneObjectPart.FromXml(fromUserInventoryItemID, reader)); |
460 | 465 | reader.Close(); | |
461 | // We reset the link number in order to make sure that the persisted linkset order is | 466 | sr.Close(); |
462 | int linkNum = part.LinkNum; | 467 | } |
463 | AddPart(part); | 468 | |
464 | part.LinkNum = linkNum; | 469 | parts = doc.GetElementsByTagName("Part"); |
465 | 470 | ||
466 | part.TrimPermissions(); | 471 | for (int i=0; i<parts.Count ; i++) |
467 | part.StoreUndoState(); | 472 | { |
468 | } | 473 | sr = new StringReader(parts[i].InnerXml); |
469 | break; | 474 | reader = new XmlTextReader(sr); |
470 | 475 | SceneObjectPart part = SceneObjectPart.FromXml(reader); | |
471 | case XmlNodeType.EndElement: | 476 | linkNum = part.LinkNum; |
472 | break; | 477 | AddPart(part); |
473 | } | 478 | part.LinkNum = linkNum; |
479 | part.TrimPermissions(); | ||
480 | part.StoreUndoState(); | ||
481 | reader.Close(); | ||
482 | sr.Close(); | ||
474 | } | 483 | } |
484 | |||
485 | // Script state may, or may not, exist. Not having any, is NOT | ||
486 | // ever a problem. | ||
487 | |||
488 | LoadScriptState(doc); | ||
489 | |||
475 | } | 490 | } |
476 | catch (XmlException e) | 491 | catch (Exception e) |
477 | { | 492 | { |
478 | m_log.ErrorFormat("[SCENE]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData); | 493 | m_log.ErrorFormat("[SCENE]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData); |
479 | } | 494 | } |
480 | 495 | ||
481 | reader.Close(); | ||
482 | sr.Close(); | ||
483 | //m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); | 496 | //m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); |
484 | } | 497 | } |
485 | 498 | ||
@@ -493,6 +506,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
493 | 506 | ||
494 | protected void SetFromXml(string xmlData) | 507 | protected void SetFromXml(string xmlData) |
495 | { | 508 | { |
509 | |||
496 | //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); | 510 | //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); |
497 | //int time = System.Environment.TickCount; | 511 | //int time = System.Environment.TickCount; |
498 | 512 | ||
@@ -504,43 +518,47 @@ namespace OpenSim.Region.Framework.Scenes | |||
504 | xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>"); | 518 | xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>"); |
505 | xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>"); | 519 | xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>"); |
506 | 520 | ||
507 | StringReader sr = new StringReader(xmlData); | 521 | try |
508 | XmlTextReader reader = new XmlTextReader(sr); | 522 | { |
509 | reader.Read(); | 523 | |
524 | XmlDocument doc = new XmlDocument(); | ||
525 | doc.LoadXml(xmlData); | ||
526 | |||
527 | XmlNodeList parts = doc.GetElementsByTagName("SceneObjectPart"); | ||
510 | 528 | ||
511 | reader.ReadStartElement("SceneObjectGroup"); | 529 | // Process the root part first |
512 | SetRootPart(CreatePartFromXml(reader)); | 530 | if(parts.Count > 0) |
531 | { | ||
532 | StringReader sr = new StringReader(parts[0].OuterXml); | ||
533 | XmlTextReader reader = new XmlTextReader(sr); | ||
534 | SetRootPart(CreatePartFromXml(reader)); | ||
535 | reader.Close(); | ||
536 | sr.Close(); | ||
537 | } | ||
513 | 538 | ||
514 | reader.Read(); | 539 | // Then deal with the rest |
515 | bool more = true; | 540 | for(int i=1; i<parts.Count; i++) |
541 | { | ||
542 | StringReader sr = new StringReader(parts[i].OuterXml); | ||
543 | XmlTextReader reader = new XmlTextReader(sr); | ||
544 | SceneObjectPart part = CreatePartFromXml(reader); | ||
545 | AddPart(part); | ||
546 | part.StoreUndoState(); | ||
547 | reader.Close(); | ||
548 | sr.Close(); | ||
549 | } | ||
516 | 550 | ||
517 | while (more) | 551 | // Script state may, or may not, exist. Not having any, is NOT |
552 | // ever a problem. | ||
553 | |||
554 | LoadScriptState(doc); | ||
555 | |||
556 | } | ||
557 | catch (Exception e) | ||
518 | { | 558 | { |
519 | switch (reader.NodeType) | 559 | m_log.ErrorFormat("[SCENE]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData); |
520 | { | ||
521 | case XmlNodeType.Element: | ||
522 | if (reader.Name == "SceneObjectPart") | ||
523 | { | ||
524 | SceneObjectPart part = CreatePartFromXml(reader); | ||
525 | AddPart(part); | ||
526 | part.StoreUndoState(); | ||
527 | } | ||
528 | else | ||
529 | { | ||
530 | m_log.Warn("found unexpected element: " + reader.Name); | ||
531 | reader.Read(); | ||
532 | } | ||
533 | break; | ||
534 | case XmlNodeType.EndElement: | ||
535 | reader.Read(); | ||
536 | break; | ||
537 | } | ||
538 | more = !reader.EOF; | ||
539 | } | 560 | } |
540 | 561 | ||
541 | reader.Close(); | ||
542 | sr.Close(); | ||
543 | |||
544 | //m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); | 562 | //m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); |
545 | } | 563 | } |
546 | 564 | ||
@@ -567,6 +585,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
567 | { | 585 | { |
568 | } | 586 | } |
569 | 587 | ||
588 | private void LoadScriptState(XmlDocument doc) | ||
589 | { | ||
590 | XmlNodeList nodes = doc.GetElementsByTagName("SavedScriptState"); | ||
591 | if(nodes.Count > 0) | ||
592 | { | ||
593 | m_savedScriptState = new Dictionary<UUID, string>(); | ||
594 | foreach(XmlNode node in nodes) | ||
595 | { | ||
596 | if(node.Attributes["UUID"] != null) | ||
597 | { | ||
598 | UUID itemid = new UUID(node.Attributes["UUID"].Value); | ||
599 | m_savedScriptState.Add(itemid, node.InnerXml); | ||
600 | } | ||
601 | } | ||
602 | } | ||
603 | } | ||
604 | |||
570 | public void SetFromAssetID(UUID AssetId) | 605 | public void SetFromAssetID(UUID AssetId) |
571 | { | 606 | { |
572 | lock (m_parts) | 607 | lock (m_parts) |
@@ -748,8 +783,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
748 | } | 783 | } |
749 | } | 784 | } |
750 | 785 | ||
751 | writer.WriteEndElement(); | 786 | writer.WriteEndElement(); // OtherParts |
752 | writer.WriteEndElement(); | 787 | SaveScriptedState(writer); |
788 | writer.WriteEndElement(); // SceneObjectGroup | ||
753 | 789 | ||
754 | //m_log.DebugFormat("[SOG]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); | 790 | //m_log.DebugFormat("[SOG]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); |
755 | } | 791 | } |
@@ -769,6 +805,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
769 | 805 | ||
770 | public void ToXml2(XmlTextWriter writer) | 806 | public void ToXml2(XmlTextWriter writer) |
771 | { | 807 | { |
808 | |||
772 | //m_log.DebugFormat("[SOG]: Starting serialization of SOG {0} to XML2", Name); | 809 | //m_log.DebugFormat("[SOG]: Starting serialization of SOG {0} to XML2", Name); |
773 | //int time = System.Environment.TickCount; | 810 | //int time = System.Environment.TickCount; |
774 | 811 | ||
@@ -787,9 +824,48 @@ namespace OpenSim.Region.Framework.Scenes | |||
787 | } | 824 | } |
788 | } | 825 | } |
789 | 826 | ||
790 | writer.WriteEndElement(); | 827 | writer.WriteEndElement(); // End of OtherParts |
791 | writer.WriteEndElement(); | 828 | SaveScriptedState(writer); |
829 | writer.WriteEndElement(); // End of SceneObjectGroup | ||
830 | |||
792 | //m_log.DebugFormat("[SOG]: Finished serialization of SOG {0} to XML2, {1}ms", Name, System.Environment.TickCount - time); | 831 | //m_log.DebugFormat("[SOG]: Finished serialization of SOG {0} to XML2, {1}ms", Name, System.Environment.TickCount - time); |
832 | |||
833 | } | ||
834 | |||
835 | private void SaveScriptedState(XmlTextWriter writer) | ||
836 | { | ||
837 | |||
838 | XmlDocument doc = new XmlDocument(); | ||
839 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | ||
840 | |||
841 | // Capture script state while holding the lock | ||
842 | lock (m_parts) | ||
843 | { | ||
844 | foreach (SceneObjectPart part in m_parts.Values) | ||
845 | { | ||
846 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); | ||
847 | foreach (UUID itemid in pstates.Keys) | ||
848 | { | ||
849 | states.Add(itemid, pstates[itemid]); | ||
850 | } | ||
851 | } | ||
852 | } | ||
853 | |||
854 | if(states.Count > 0) | ||
855 | { | ||
856 | // Now generate the necessary XML wrappings | ||
857 | writer.WriteStartElement(String.Empty, "GroupScriptStates", String.Empty); | ||
858 | foreach(UUID itemid in states.Keys) | ||
859 | { | ||
860 | doc.LoadXml(states[itemid]); | ||
861 | writer.WriteStartElement(String.Empty, "SavedScriptState", String.Empty); | ||
862 | writer.WriteAttributeString(String.Empty, "UUID", String.Empty, itemid.ToString()); | ||
863 | writer.WriteRaw(doc.DocumentElement.OuterXml); // Writes ScriptState element | ||
864 | writer.WriteEndElement(); // End of SavedScriptState | ||
865 | } | ||
866 | writer.WriteEndElement(); // End of GroupScriptStates | ||
867 | } | ||
868 | |||
793 | } | 869 | } |
794 | 870 | ||
795 | /// <summary> | 871 | /// <summary> |
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 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.IO; | ||
29 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
30 | using System.Reflection; | 31 | using System.Reflection; |
31 | using OpenMetaverse; | 32 | using OpenMetaverse; |
@@ -264,6 +265,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
264 | } | 265 | } |
265 | else | 266 | else |
266 | { | 267 | { |
268 | if(m_part.ParentGroup.m_savedScriptState != null) | ||
269 | RestoreSavedScriptState(item.OldItemID, item.ItemID); | ||
267 | m_items[item.ItemID].PermsMask = 0; | 270 | m_items[item.ItemID].PermsMask = 0; |
268 | m_items[item.ItemID].PermsGranter = UUID.Zero; | 271 | m_items[item.ItemID].PermsGranter = UUID.Zero; |
269 | string script = Utils.BytesToString(asset.Data); | 272 | string script = Utils.BytesToString(asset.Data); |
@@ -276,6 +279,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
276 | } | 279 | } |
277 | } | 280 | } |
278 | 281 | ||
282 | static System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); | ||
283 | |||
284 | private void RestoreSavedScriptState(UUID oldID, UUID newID) | ||
285 | { | ||
286 | if(m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID)) | ||
287 | { | ||
288 | string fpath = Path.Combine("ScriptEngines/"+m_part.ParentGroup.Scene.RegionInfo.RegionID.ToString(), | ||
289 | newID.ToString()+".state"); | ||
290 | FileStream fs = File.Create(fpath); | ||
291 | Byte[] buffer = enc.GetBytes(m_part.ParentGroup.m_savedScriptState[oldID]); | ||
292 | fs.Write(buffer,0,buffer.Length); | ||
293 | fs.Close(); | ||
294 | m_part.ParentGroup.m_savedScriptState.Remove(oldID); | ||
295 | } | ||
296 | } | ||
297 | |||
279 | /// <summary> | 298 | /// <summary> |
280 | /// Start a script which is in this prim's inventory. | 299 | /// Start a script which is in this prim's inventory. |
281 | /// </summary> | 300 | /// </summary> |