Beispiel #1
0
        public void SaveState(string assembly)
        {
            // If we're currently in an event, just tell it to save upon return
            //
            if (m_InEvent)
            {
                m_SaveState = true;
                return;
            }

            PluginData = AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID);

            string xml = ScriptSerializer.Serialize(this);

            if (m_CurrentState != xml)
            {
                try
                {
                    FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state"));
                    System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
                    Byte[] buf = enc.GetBytes(xml);
                    fs.Write(buf, 0, buf.Length);
                    fs.Close();
                }
                catch (Exception e)
                {
                    m_log.Error("Unable to save xml\n" + e.ToString());
                }
                //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state")))
                //{
                //    throw new Exception("Completed persistence save, but no file was created");
                //}
                m_CurrentState = xml;
            }
        }
        public string GetXMLState()
        {
            bool run = Running;

            Stop(100);
            Running = run;

            // We should not be doing this, but since we are about to
            // dispose this, it really doesn't make a difference
            // This is meant to work around a Windows only race
            //
            m_InEvent = false;

            // Force an update of the in-memory plugin data
            //
            PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID);

            return(ScriptSerializer.Serialize(this));
        }
        public void SaveState(string assembly)
        {
            // If we're currently in an event, just tell it to save upon return
            //
            if (m_InEvent)
            {
                m_SaveState = true;
                return;
            }

            PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID);

            string xml = ScriptSerializer.Serialize(this);

            // Compare hash of the state we just just created with the state last written to disk
            // If the state is different, update the disk file.
            UUID hash = UUID.Parse(Utils.MD5String(xml));

            if (hash != m_CurrentStateHash)
            {
                try
                {
                    FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"));
                    System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
                    Byte[] buf = enc.GetBytes(xml);
                    fs.Write(buf, 0, buf.Length);
                    fs.Close();
                }
                catch (Exception)
                {
                    // m_log.Error("Unable to save xml\n"+e.ToString());
                }
                //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")))
                //{
                //    throw new Exception("Completed persistence save, but no file was created");
                //}
                m_CurrentStateHash = hash;
            }
        }
Beispiel #4
0
        /********************************************************************************\
        *  The only method of interest to outside this module is GetExecutionState()   *
        *  which captures the current state of the script into an XML document.        *
        *                                                                              *
        *  The rest of this module contains support routines for GetExecutionState().  *
        \********************************************************************************/

        /**
         * @brief Create an XML element that gives the current state of the script.
         *   <ScriptState Engine="YEngine" SourceHash=m_ObjCode.sourceHash Asset=m_Item.AssetID>
         *     <Snapshot>globalsandstackdump</Snapshot>
         *     <Running>m_Running</Running>
         *     <DetectArray ...
         *     <EventQueue ...
         *     <Permissions ...
         *     <Plugins />
         *   </ScriptState>
         * Updates the .state file while we're at it.
         */
        public XmlElement GetExecutionState(XmlDocument doc)
        {
            // When we're detaching an attachment, we need to wait here.

            // Change this to a 5 second timeout. If things do mess up,
            // we don't want to be stuck forever.
            //
            m_DetachReady.WaitOne(5000, false);

            XmlElement scriptStateN = doc.CreateElement("", "ScriptState", "");

            scriptStateN.SetAttribute("Engine", m_Engine.ScriptEngineName);
            scriptStateN.SetAttribute("Asset", m_Item.AssetID.ToString());
            scriptStateN.SetAttribute("SourceHash", m_ObjCode.sourceHash);

            // Make sure we aren't executing part of the script so it stays
            // stable.  Setting suspendOnCheckRun tells CheckRun() to suspend
            // and return out so RunOne() will release the lock asap.
            suspendOnCheckRunHold = true;
            lock (m_RunLock)
            {
                m_RunOnePhase = "GetExecutionState enter";
                CheckRunLockInvariants(true);

                // Get copy of script globals and stack in relocateable form.
                Byte[] snapshotBytes;
                using (MemoryStream snapshotStream = new MemoryStream())
                {
                    MigrateOutEventHandler(snapshotStream);
                    snapshotBytes = snapshotStream.ToArray();
                }

                string     snapshotString = Convert.ToBase64String(snapshotBytes);
                XmlElement snapshotN      = doc.CreateElement("", "Snapshot", "");
                snapshotN.AppendChild(doc.CreateTextNode(snapshotString));
                scriptStateN.AppendChild(snapshotN);
                m_RunOnePhase = "GetExecutionState B";
                CheckRunLockInvariants(true);

                // "Running" says whether or not we are accepting new events.
                XmlElement runningN = doc.CreateElement("", "Running", "");
                runningN.AppendChild(doc.CreateTextNode(m_Running.ToString()));
                scriptStateN.AppendChild(runningN);
                m_RunOnePhase = "GetExecutionState C";
                CheckRunLockInvariants(true);

                // "DoGblInit" says whether or not default:state_entry() will init global vars.
                XmlElement doGblInitN = doc.CreateElement("", "DoGblInit", "");
                doGblInitN.AppendChild(doc.CreateTextNode(doGblInit.ToString()));
                scriptStateN.AppendChild(doGblInitN);
                m_RunOnePhase = "GetExecutionState D";
                CheckRunLockInvariants(true);

                if (m_XMRLSLApi != null)
                {
                    double     scriptTime  = Util.GetTimeStampMS() - m_XMRLSLApi.getLSLTimer();
                    XmlElement scriptTimeN = doc.CreateElement("", "scrpTime", "");
                    scriptTimeN.AppendChild(doc.CreateTextNode(scriptTime.ToString()));
                    scriptStateN.AppendChild(scriptTimeN);
                }

                if (m_minEventDelay != 0.0)
                {
                    XmlElement minEventDelayN = doc.CreateElement("", "mEvtDly", "");
                    minEventDelayN.AppendChild(doc.CreateTextNode(m_minEventDelay.ToString()));
                    scriptStateN.AppendChild(minEventDelayN);
                    m_RunOnePhase = "GetExecutionState D";
                    CheckRunLockInvariants(true);
                }

                // More misc data.
                XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
                scriptStateN.AppendChild(permissionsN);

                XmlAttribute granterA = doc.CreateAttribute("", "granter", "");
                granterA.Value = m_Item.PermsGranter.ToString();
                permissionsN.Attributes.Append(granterA);

                XmlAttribute maskA = doc.CreateAttribute("", "mask", "");
                maskA.Value = m_Item.PermsMask.ToString();
                permissionsN.Attributes.Append(maskA);
                m_RunOnePhase = "GetExecutionState E";
                CheckRunLockInvariants(true);

                // "DetectParams" are returned by llDetected...() script functions
                // for the currently active event, if any.
                if (m_DetectParams != null)
                {
                    XmlElement detParArrayN = doc.CreateElement("", "DetectArray", "");
                    AppendXMLDetectArray(doc, detParArrayN, m_DetectParams);
                    scriptStateN.AppendChild(detParArrayN);
                }
                m_RunOnePhase = "GetExecutionState F";
                CheckRunLockInvariants(true);

                // Save any events we have in the queue.
                // <EventQueue>
                //   <Event Name="...">
                //     <param>...</param> ...
                //     <DetectParams>...</DetectParams> ...
                //   </Event>
                //   ...
                // </EventQueue>
                XmlElement queuedEventsN = doc.CreateElement("", "EventQueue", "");
                lock (m_QueueLock)
                {
                    foreach (EventParams evt in m_EventQueue)
                    {
                        XmlElement singleEventN = doc.CreateElement("", "Event", "");
                        singleEventN.SetAttribute("Name", evt.EventName);
                        AppendXMLObjectArray(doc, singleEventN, evt.Params, "param");
                        AppendXMLDetectArray(doc, singleEventN, evt.DetectParams);
                        queuedEventsN.AppendChild(singleEventN);
                    }
                }
                scriptStateN.AppendChild(queuedEventsN);
                m_RunOnePhase = "GetExecutionState G";
                CheckRunLockInvariants(true);

                // "Plugins" indicate enabled timers and listens, etc.
                Object[] pluginData =
                    AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID);

                XmlNode plugins = doc.CreateElement("", "Plugins", "");
                AppendXMLObjectArray(doc, plugins, pluginData, "plugin");
                scriptStateN.AppendChild(plugins);
                m_RunOnePhase = "GetExecutionState H";
                CheckRunLockInvariants(true);

                // Let script run again.
                suspendOnCheckRunHold = false;

                m_RunOnePhase = "GetExecutionState leave";
                CheckRunLockInvariants(true);
            }

            // scriptStateN represents the contents of the .state file so
            // write the .state file while we are here.
            using (FileStream fs = File.Create(m_StateFileName))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                    sw.Write(scriptStateN.OuterXml);
            }

            return(scriptStateN);
        }
Beispiel #5
0
        public void SaveState()
        {
            if (!Running)
            {
                return;
            }

            // We cannot call this inside the EventQueue lock since it will currently take AsyncCommandManager.staticLock.
            // This may already be held by AsyncCommandManager.DoOneCmdHandlerPass() which in turn can take EventQueue
            // lock via ScriptInstance.PostEvent().
            PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID);

            // We need to lock here to avoid any race with a thread that is removing this script.
            lock (EventQueue)
            {
                // Check again to avoid a race with a thread in Stop()
                if (!Running)
                {
                    return;
                }

                // If we're currently in an event, just tell it to save upon return
                //
                if (m_InEvent)
                {
                    m_SaveState = true;
                    return;
                }

                //            m_log.DebugFormat(
                //                "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}",
                //                ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name);

                string xml = ScriptSerializer.Serialize(this);

                // Compare hash of the state we just just created with the state last written to disk
                // If the state is different, update the disk file.
                UUID hash = UUID.Parse(Utils.MD5String(xml));

                if (hash != m_CurrentStateHash)
                {
                    try
                    {
                        using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state")))
                        {
                            Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml);
                            fs.Write(buf, 0, buf.Length);
                        }
                    }
                    catch (Exception)
                    {
                        // m_log.Error("Unable to save xml\n"+e.ToString());
                    }
                    //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")))
                    //{
                    //    throw new Exception("Completed persistence save, but no file was created");
                    //}
                    m_CurrentStateHash = hash;
                }
            }
        }