diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs index ce293e4312..ee4323ccb1 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; /// /// 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); - - //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache); - - List serialisedSceneObjects = new List(); - string filePath = "ERROR"; - int successfulAssetRestores = 0; int failedAssetRestores = 0; + List serialisedSceneObjects = new List(); - byte[] data; - TarArchiveReader.TarEntryType entryType; - - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + try { - //m_log.DebugFormat( - // "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length); - if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) + TarArchiveReader archive = new TarArchiveReader(m_loadStream); + + //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache); + + string filePath = "ERROR"; + + byte[] data; + TarArchiveReader.TarEntryType 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.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.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); + } /// diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs index b493f843f6..1543bf04b2 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; + /// + /// 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 + /// + public delegate void OarFileLoaded(string message); + public event OarFileLoaded OnOarFileLoaded; + + /// + /// Called when the script compile queue becomes empty + /// Returns the number of scripts which failed to start + /// + 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 30ce79b28c..fc76d0b297 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; } }