diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs new file mode 100644 index 0000000..e90d83b --- /dev/null +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.IO; | ||
30 | using System.Xml; | ||
31 | using OpenSim.Region.ScriptEngine.Shared; | ||
32 | using OpenSim.Region.ScriptEngine.Shared.Api; | ||
33 | using log4net; | ||
34 | |||
35 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | ||
36 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | ||
37 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
38 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; | ||
39 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | ||
40 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
41 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | ||
42 | |||
43 | namespace OpenSim.Region.ScriptEngine.Yengine | ||
44 | { | ||
45 | public partial class XMRInstance | ||
46 | { | ||
47 | /********************************************************************************\ | ||
48 | * The only method of interest to outside this module is GetExecutionState() * | ||
49 | * which captures the current state of the script into an XML document. * | ||
50 | * * | ||
51 | * The rest of this module contains support routines for GetExecutionState(). * | ||
52 | \********************************************************************************/ | ||
53 | |||
54 | /** | ||
55 | * @brief Create an XML element that gives the current state of the script. | ||
56 | * <ScriptState Engine="YEngine" SourceHash=m_ObjCode.sourceHash Asset=m_Item.AssetID> | ||
57 | * <Snapshot>globalsandstackdump</Snapshot> | ||
58 | * <Running>m_Running</Running> | ||
59 | * <DetectArray ... | ||
60 | * <EventQueue ... | ||
61 | * <Permissions ... | ||
62 | * <Plugins /> | ||
63 | * </ScriptState> | ||
64 | * Updates the .state file while we're at it. | ||
65 | */ | ||
66 | public XmlElement GetExecutionState(XmlDocument doc) | ||
67 | { | ||
68 | // When we're detaching an attachment, we need to wait here. | ||
69 | |||
70 | // Change this to a 5 second timeout. If things do mess up, | ||
71 | // we don't want to be stuck forever. | ||
72 | // | ||
73 | m_DetachReady.WaitOne(5000, false); | ||
74 | |||
75 | XmlElement scriptStateN = doc.CreateElement("", "ScriptState", ""); | ||
76 | scriptStateN.SetAttribute("Engine", m_Engine.ScriptEngineName); | ||
77 | scriptStateN.SetAttribute("Asset", m_Item.AssetID.ToString()); | ||
78 | scriptStateN.SetAttribute("SourceHash", m_ObjCode.sourceHash); | ||
79 | |||
80 | // Make sure we aren't executing part of the script so it stays | ||
81 | // stable. Setting suspendOnCheckRun tells CheckRun() to suspend | ||
82 | // and return out so RunOne() will release the lock asap. | ||
83 | suspendOnCheckRunHold = true; | ||
84 | lock(m_RunLock) | ||
85 | { | ||
86 | m_RunOnePhase = "GetExecutionState enter"; | ||
87 | CheckRunLockInvariants(true); | ||
88 | |||
89 | // Get copy of script globals and stack in relocateable form. | ||
90 | MemoryStream snapshotStream = new MemoryStream(); | ||
91 | MigrateOutEventHandler(snapshotStream); | ||
92 | Byte[] snapshotBytes = snapshotStream.ToArray(); | ||
93 | snapshotStream.Close(); | ||
94 | string snapshotString = Convert.ToBase64String(snapshotBytes); | ||
95 | XmlElement snapshotN = doc.CreateElement("", "Snapshot", ""); | ||
96 | snapshotN.AppendChild(doc.CreateTextNode(snapshotString)); | ||
97 | scriptStateN.AppendChild(snapshotN); | ||
98 | m_RunOnePhase = "GetExecutionState B"; | ||
99 | CheckRunLockInvariants(true); | ||
100 | |||
101 | // "Running" says whether or not we are accepting new events. | ||
102 | XmlElement runningN = doc.CreateElement("", "Running", ""); | ||
103 | runningN.AppendChild(doc.CreateTextNode(m_Running.ToString())); | ||
104 | scriptStateN.AppendChild(runningN); | ||
105 | m_RunOnePhase = "GetExecutionState C"; | ||
106 | CheckRunLockInvariants(true); | ||
107 | |||
108 | // "DoGblInit" says whether or not default:state_entry() will init global vars. | ||
109 | XmlElement doGblInitN = doc.CreateElement("", "DoGblInit", ""); | ||
110 | doGblInitN.AppendChild(doc.CreateTextNode(doGblInit.ToString())); | ||
111 | scriptStateN.AppendChild(doGblInitN); | ||
112 | m_RunOnePhase = "GetExecutionState D"; | ||
113 | CheckRunLockInvariants(true); | ||
114 | |||
115 | // More misc data. | ||
116 | XmlNode permissionsN = doc.CreateElement("", "Permissions", ""); | ||
117 | scriptStateN.AppendChild(permissionsN); | ||
118 | |||
119 | XmlAttribute granterA = doc.CreateAttribute("", "granter", ""); | ||
120 | granterA.Value = m_Item.PermsGranter.ToString(); | ||
121 | permissionsN.Attributes.Append(granterA); | ||
122 | |||
123 | XmlAttribute maskA = doc.CreateAttribute("", "mask", ""); | ||
124 | maskA.Value = m_Item.PermsMask.ToString(); | ||
125 | permissionsN.Attributes.Append(maskA); | ||
126 | m_RunOnePhase = "GetExecutionState E"; | ||
127 | CheckRunLockInvariants(true); | ||
128 | |||
129 | // "DetectParams" are returned by llDetected...() script functions | ||
130 | // for the currently active event, if any. | ||
131 | if(m_DetectParams != null) | ||
132 | { | ||
133 | XmlElement detParArrayN = doc.CreateElement("", "DetectArray", ""); | ||
134 | AppendXMLDetectArray(doc, detParArrayN, m_DetectParams); | ||
135 | scriptStateN.AppendChild(detParArrayN); | ||
136 | } | ||
137 | m_RunOnePhase = "GetExecutionState F"; | ||
138 | CheckRunLockInvariants(true); | ||
139 | |||
140 | // Save any events we have in the queue. | ||
141 | // <EventQueue> | ||
142 | // <Event Name="..."> | ||
143 | // <param>...</param> ... | ||
144 | // <DetectParams>...</DetectParams> ... | ||
145 | // </Event> | ||
146 | // ... | ||
147 | // </EventQueue> | ||
148 | XmlElement queuedEventsN = doc.CreateElement("", "EventQueue", ""); | ||
149 | lock(m_QueueLock) | ||
150 | { | ||
151 | foreach(EventParams evt in m_EventQueue) | ||
152 | { | ||
153 | XmlElement singleEventN = doc.CreateElement("", "Event", ""); | ||
154 | singleEventN.SetAttribute("Name", evt.EventName); | ||
155 | AppendXMLObjectArray(doc, singleEventN, evt.Params, "param"); | ||
156 | AppendXMLDetectArray(doc, singleEventN, evt.DetectParams); | ||
157 | queuedEventsN.AppendChild(singleEventN); | ||
158 | } | ||
159 | } | ||
160 | scriptStateN.AppendChild(queuedEventsN); | ||
161 | m_RunOnePhase = "GetExecutionState G"; | ||
162 | CheckRunLockInvariants(true); | ||
163 | |||
164 | // "Plugins" indicate enabled timers and listens, etc. | ||
165 | Object[] pluginData = | ||
166 | AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID); | ||
167 | |||
168 | XmlNode plugins = doc.CreateElement("", "Plugins", ""); | ||
169 | AppendXMLObjectArray(doc, plugins, pluginData, "plugin"); | ||
170 | scriptStateN.AppendChild(plugins); | ||
171 | m_RunOnePhase = "GetExecutionState H"; | ||
172 | CheckRunLockInvariants(true); | ||
173 | |||
174 | // Let script run again. | ||
175 | suspendOnCheckRunHold = false; | ||
176 | |||
177 | m_RunOnePhase = "GetExecutionState leave"; | ||
178 | CheckRunLockInvariants(true); | ||
179 | } | ||
180 | |||
181 | // scriptStateN represents the contents of the .state file so | ||
182 | // write the .state file while we are here. | ||
183 | FileStream fs = File.Create(m_StateFileName); | ||
184 | StreamWriter sw = new StreamWriter(fs); | ||
185 | sw.Write(scriptStateN.OuterXml); | ||
186 | sw.Close(); | ||
187 | fs.Close(); | ||
188 | |||
189 | return scriptStateN; | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * @brief Write script state to output stream. | ||
194 | * Input: | ||
195 | * stream = stream to write event handler state information to | ||
196 | */ | ||
197 | private void MigrateOutEventHandler(Stream stream) | ||
198 | { | ||
199 | // Write script state out, frames and all, to the stream. | ||
200 | // Does not change script state. | ||
201 | stream.WriteByte(migrationVersion); | ||
202 | stream.WriteByte((byte)16); | ||
203 | this.MigrateOut(new BinaryWriter(stream)); | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * @brief Convert an DetectParams[] to corresponding XML. | ||
208 | * DetectParams[] holds the values retrievable by llDetected...() for | ||
209 | * a given event. | ||
210 | */ | ||
211 | private static void AppendXMLDetectArray(XmlDocument doc, XmlElement parent, DetectParams[] detect) | ||
212 | { | ||
213 | foreach(DetectParams d in detect) | ||
214 | { | ||
215 | XmlElement detectParamsN = GetXMLDetect(doc, d); | ||
216 | parent.AppendChild(detectParamsN); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | private static XmlElement GetXMLDetect(XmlDocument doc, DetectParams d) | ||
221 | { | ||
222 | XmlElement detectParamsN = doc.CreateElement("", "DetectParams", ""); | ||
223 | |||
224 | XmlAttribute d_key = doc.CreateAttribute("", "key", ""); | ||
225 | d_key.Value = d.Key.ToString(); | ||
226 | detectParamsN.Attributes.Append(d_key); | ||
227 | |||
228 | XmlAttribute pos = doc.CreateAttribute("", "pos", ""); | ||
229 | pos.Value = d.OffsetPos.ToString(); | ||
230 | detectParamsN.Attributes.Append(pos); | ||
231 | |||
232 | XmlAttribute d_linkNum = doc.CreateAttribute("", "linkNum", ""); | ||
233 | d_linkNum.Value = d.LinkNum.ToString(); | ||
234 | detectParamsN.Attributes.Append(d_linkNum); | ||
235 | |||
236 | XmlAttribute d_group = doc.CreateAttribute("", "group", ""); | ||
237 | d_group.Value = d.Group.ToString(); | ||
238 | detectParamsN.Attributes.Append(d_group); | ||
239 | |||
240 | XmlAttribute d_name = doc.CreateAttribute("", "name", ""); | ||
241 | d_name.Value = d.Name.ToString(); | ||
242 | detectParamsN.Attributes.Append(d_name); | ||
243 | |||
244 | XmlAttribute d_owner = doc.CreateAttribute("", "owner", ""); | ||
245 | d_owner.Value = d.Owner.ToString(); | ||
246 | detectParamsN.Attributes.Append(d_owner); | ||
247 | |||
248 | XmlAttribute d_position = doc.CreateAttribute("", "position", ""); | ||
249 | d_position.Value = d.Position.ToString(); | ||
250 | detectParamsN.Attributes.Append(d_position); | ||
251 | |||
252 | XmlAttribute d_rotation = doc.CreateAttribute("", "rotation", ""); | ||
253 | d_rotation.Value = d.Rotation.ToString(); | ||
254 | detectParamsN.Attributes.Append(d_rotation); | ||
255 | |||
256 | XmlAttribute d_type = doc.CreateAttribute("", "type", ""); | ||
257 | d_type.Value = d.Type.ToString(); | ||
258 | detectParamsN.Attributes.Append(d_type); | ||
259 | |||
260 | XmlAttribute d_velocity = doc.CreateAttribute("", "velocity", ""); | ||
261 | d_velocity.Value = d.Velocity.ToString(); | ||
262 | detectParamsN.Attributes.Append(d_velocity); | ||
263 | |||
264 | return detectParamsN; | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * @brief Append elements of an array of objects to an XML parent. | ||
269 | * @param doc = document the parent is part of | ||
270 | * @param parent = parent to append the items to | ||
271 | * @param array = array of objects | ||
272 | * @param tag = <tag ..>...</tag> for each element | ||
273 | */ | ||
274 | private static void AppendXMLObjectArray(XmlDocument doc, XmlNode parent, object[] array, string tag) | ||
275 | { | ||
276 | foreach(object o in array) | ||
277 | { | ||
278 | XmlElement element = GetXMLObject(doc, o, tag); | ||
279 | parent.AppendChild(element); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * @brief Get and XML representation of an object. | ||
285 | * @param doc = document the tag will be put in | ||
286 | * @param o = object to be represented | ||
287 | * @param tag = <tag ...>...</tag> | ||
288 | */ | ||
289 | private static XmlElement GetXMLObject(XmlDocument doc, object o, string tag) | ||
290 | { | ||
291 | XmlAttribute typ = doc.CreateAttribute("", "type", ""); | ||
292 | XmlElement n = doc.CreateElement("", tag, ""); | ||
293 | |||
294 | if(o is LSL_List) | ||
295 | { | ||
296 | typ.Value = "list"; | ||
297 | n.Attributes.Append(typ); | ||
298 | AppendXMLObjectArray(doc, n, ((LSL_List)o).Data, "item"); | ||
299 | } | ||
300 | else | ||
301 | { | ||
302 | typ.Value = o.GetType().ToString(); | ||
303 | n.Attributes.Append(typ); | ||
304 | n.AppendChild(doc.CreateTextNode(o.ToString())); | ||
305 | } | ||
306 | return n; | ||
307 | } | ||
308 | } | ||
309 | } | ||