From a3ac702941bbae92ca5a3ed452eb3d417bf30f0b Mon Sep 17 00:00:00 2001
From: Dr Scofield
Date: Wed, 28 Jan 2009 09:22:12 +0000
Subject: From: Christopher Yeoh <yeohc@au1.ibm.com>

Adding Oarfileloaded and EmptyScriptCompileQueue event support which
allows (with a module) for programmatic notification of when a region
objects and scripts are up and running after a server start or
load-oar.


---
 .../Modules/World/Archiver/ArchiveReadRequest.cs   | 92 +++++++++++++---------
 OpenSim/Region/Environment/Scenes/EventManager.cs  | 31 ++++++++
 OpenSim/Region/ScriptEngine/XEngine/XEngine.cs     | 24 ++++++
 3 files changed, 110 insertions(+), 37 deletions(-)

(limited to 'OpenSim')

diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs
index ce293e4..ee4323c 100644
--- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver
 
         private Scene m_scene;
         private Stream m_loadStream;
+        private string m_errorMessage;
 
         /// <summary>
         /// Used to cache lookups for valid uuids.
@@ -63,6 +64,7 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver
         {
             m_scene = scene;
             m_loadStream = new GZipStream(GetStream(loadPath), CompressionMode.Decompress);
+            m_errorMessage = String.Empty;
         }
         
         public ArchiveReadRequest(Scene scene, Stream loadStream)
@@ -82,62 +84,76 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver
         
         private void DearchiveRegion0DotStar()
         {
-            TarArchiveReader archive = new TarArchiveReader(m_loadStream);
+            int successfulAssetRestores = 0;
+            int failedAssetRestores = 0;
+            List<string> serialisedSceneObjects = new List<string>();
 
-            //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache);
+            try
+            {
+                TarArchiveReader archive = new TarArchiveReader(m_loadStream);
 
-            List<string> serialisedSceneObjects = new List<string>();
-            string filePath = "ERROR";
+                //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache);
 
-            int successfulAssetRestores = 0;
-            int failedAssetRestores = 0;
+                string filePath = "ERROR";
 
-            byte[] data;
-            TarArchiveReader.TarEntryType entryType;
+                byte[] data;
+                TarArchiveReader.TarEntryType entryType;
             
-            while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
-            {
-                //m_log.DebugFormat(
-                //    "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length);
-                if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 
+                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                 {
-                    m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}",
-                                     filePath);
-                }
-                else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
-                {
-                    serialisedSceneObjects.Add(m_asciiEncoding.GetString(data));
-                }
+                    //m_log.DebugFormat(
+                    //    "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length);
+                    if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 
+                    {
+                        m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}",
+                                         filePath);
+                    }
+                    else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
+                    {
+                        serialisedSceneObjects.Add(m_asciiEncoding.GetString(data));
+                    }
 //                else if (filePath.Equals(ArchiveConstants.ASSETS_METADATA_PATH))
 //                {
 //                    string xml = m_asciiEncoding.GetString(data);
 //                    dearchiver.AddAssetMetadata(xml);
 //                }
-                else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
-                {
-                    if (LoadAsset(filePath, data))
-                        successfulAssetRestores++;
-                    else
-                        failedAssetRestores++;
-                }
-                else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
-                {
-                    LoadTerrain(filePath, data);
-                }
-                else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
-                {
-                    LoadRegionSettings(filePath, data);
+                    else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
+                    {
+                        if (LoadAsset(filePath, data))
+                            successfulAssetRestores++;
+                        else
+                            failedAssetRestores++;
+                    }
+                    else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
+                    {
+                        LoadTerrain(filePath, data);
+                    }
+                    else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
+                    {
+                        LoadRegionSettings(filePath, data);
+                    }
                 }
-            }
             
-            //m_log.Debug("[ARCHIVER]: Reached end of archive");
+                //m_log.Debug("[ARCHIVER]: Reached end of archive");
 
-            archive.Close();
+                archive.Close();
+            }
+            catch (Exception e)
+            {
+                m_log.ErrorFormat(
+                    "[ARCHIVER]: Error loading oar file. Exception was: {0}", e);
+                m_errorMessage += e.ToString();
+                m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage);
+                return;
+            }
 
             m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores);
 
             if (failedAssetRestores > 0)
+            {
                 m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores);
+                m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores);
+            }
             
             m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
             m_scene.DeleteAllSceneObjects();
@@ -217,6 +233,8 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver
             {
                 sceneObject.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 0);
             }
+            m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage);
+
         }
 
         /// <summary>
diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs
index b493f84..1543bf0 100644
--- a/OpenSim/Region/Environment/Scenes/EventManager.cs
+++ b/OpenSim/Region/Environment/Scenes/EventManager.cs
@@ -266,6 +266,21 @@ namespace OpenSim.Region.Environment.Scenes
         public delegate float SunLindenHour();
         public event SunLindenHour OnGetSunLindenHour;
 
+        /// <summary>
+        /// Called when oar file has finished loading, although
+        /// the scripts may not have started yet
+        /// Message is non empty string if there were problems loading the oar file
+        /// </summary>
+        public delegate void OarFileLoaded(string message);
+        public event OarFileLoaded OnOarFileLoaded;
+
+        /// <summary>
+        /// Called when the script compile queue becomes empty
+        /// Returns the number of scripts which failed to start
+        /// </summary>
+        public delegate void EmptyScriptCompileQueue(int numScriptsFailed, string message);
+        public event EmptyScriptCompileQueue OnEmptyScriptCompileQueue;
+
         public class MoneyTransferArgs : EventArgs
         {
             public UUID sender;
@@ -399,6 +414,8 @@ namespace OpenSim.Region.Environment.Scenes
         private SunLindenHour handlerSunGetLindenHour = null;
         private OnSetRootAgentSceneDelegate handlerSetRootAgentScene = null;
 
+        private OarFileLoaded handlerOarFileLoaded = null;
+        private EmptyScriptCompileQueue handlerEmptyScriptCompileQueue = null;
 
         public void TriggerGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID)
         {
@@ -902,6 +919,20 @@ namespace OpenSim.Region.Environment.Scenes
             return 6;
         }
 
+        public void TriggerOarFileLoaded(string message)
+        {
+            handlerOarFileLoaded = OnOarFileLoaded;
+            if (handlerOarFileLoaded != null)
+                handlerOarFileLoaded(message);
+        }
+
+        public void TriggerEmptyScriptCompileQueue(int numScriptsFailed, string message)
+        {
+            handlerEmptyScriptCompileQueue = OnEmptyScriptCompileQueue;
+            if (handlerEmptyScriptCompileQueue != null)
+                handlerEmptyScriptCompileQueue(numScriptsFailed, message);
+        }
+
         public void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
         {
             handlerCollidingStart = OnScriptColliderStart;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 30ce79b..fc76d0b 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -71,6 +71,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
         private ThreadPriority m_Prio;
         private bool m_Enabled = false;
         private bool m_InitialStartup = true;
+        private int m_ScriptFailCount; // Number of script fails since compile queue was last empty
+        private string m_ScriptErrorMessage;
 
 // disable warning: need to keep a reference to XEngine.EventManager
 // alive to avoid it being garbage collected
@@ -149,6 +151,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
         public void Initialise(Scene scene, IConfigSource configSource)
         {
             m_ScriptConfig = configSource.Configs["XEngine"];
+            m_ScriptFailCount = 0;
+            m_ScriptErrorMessage = String.Empty;
 
             if (m_ScriptConfig == null)
             {
@@ -417,6 +421,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
             {
                 m_InitialStartup = false;
                 System.Threading.Thread.Sleep(15000);
+                lock (m_CompileQueue) 
+                {
+                    if (m_CompileQueue.Count==0)
+                        // No scripts on region, so won't get triggered later
+                        // by the queue becoming empty so we trigger it here
+                        m_Scene.EventManager.TriggerEmptyScriptCompileQueue(0, String.Empty);
+                }
             }
 
             Object o;
@@ -443,6 +454,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
                 else
                 {
                     m_CurrentCompile = null;
+		    m_Scene.EventManager.TriggerEmptyScriptCompileQueue(m_ScriptFailCount, 
+									m_ScriptErrorMessage);
+		    m_ScriptFailCount = 0;
                 }
             }
             return null;
@@ -468,12 +482,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine
             if (part == null)
             {
                 Log.Error("[Script] SceneObjectPart unavailable. Script NOT started.");
+		m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n";
+		m_ScriptFailCount++;
                 return false;
             }     
 
             TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID);
             if (item == null)
+	    {
+		m_ScriptErrorMessage += "Can't find script inventory item.\n";
+		m_ScriptFailCount++;
                 return false;
+	    }
 
             UUID assetID = item.AssetID;
 
@@ -499,6 +519,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
                 try
                 {
                     // DISPLAY ERROR INWORLD
+		    m_ScriptErrorMessage += "Failed to compile: " + e.Message.ToString();
+		    m_ScriptFailCount++;
                     string text = "Error compiling script:\n" + e.Message.ToString();
                     if (text.Length > 1000)
                         text = text.Substring(0, 1000);
@@ -567,6 +589,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
                         catch (Exception e)
                         {
                             m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
+			    m_ScriptErrorMessage += "Exception creating app domain:\n";
+			    m_ScriptFailCount++;
                             return false;
                         }
                     }
-- 
cgit v1.1