From bf1580fba45df7624180b07599c8170074500c99 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Mon, 21 Apr 2008 12:42:56 +0000 Subject: [PATCH] From: Dr Scofield the attached patch set is centered around RemoteAdminPlugin and focuses mainly on making it more robust (i.e. more parameter checking and better error reporting) but also we've re-implemented the LoadTerrain stuff that got disabled during the terrain code reworking: * missing PostInitialize() calls on region modules that were loaded for regions created via RemoteAdmin's CreateRegion XmlRpc call * re-implements RemoteAdmin's LoadTerrain XmlRpc call (probably lost during the TerrainModule rework) * adds lots more parameter checking and error reporting to RemoteAdmin * adds a read-only property to RegionApplicationBase so that we can access the CommsManager * adds Exceptions to TerrainModule so that we get better error case feedback (and can report more meaningful errors in turn) * adds a CheckForTerrainUpdate() call to TerrainModule.LoadFromFile() to make terrain changes effective * adds TryGetCurrentScene(LLUUID) to SceneManager so that we can retrieve Scenes not only by name but also by LLUUID cheers, dr scofield --- .../RemoteController/RemoteAdminPlugin.cs | 160 +++++++++++------- .../Capabilities/CapsHandlers.cs | 4 + .../Filesystem/RegionLoaderFileSystem.cs | 2 +- OpenSim/Region/Application/OpenSimMain.cs | 33 +++- .../ClientStack/RegionApplicationBase.cs | 3 + OpenSim/Region/Environment/ModuleLoader.cs | 11 +- .../Modules/Terrain/TerrainModule.cs | 9 +- .../Region/Environment/Scenes/SceneManager.cs | 16 ++ 8 files changed, 170 insertions(+), 68 deletions(-) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 3e0f4f63d1..b8ee3ee8ff 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -38,6 +38,7 @@ using Nwc.XmlRpc; using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.Modules.Terrain; [assembly : Addin] [assembly : AddinDependency("OpenSim", "0.5")] @@ -88,6 +89,9 @@ namespace OpenSim.ApplicationPlugins.LoadRegions LLUUID regionID = new LLUUID((string) requestData["regionID"]); Hashtable responseData = new Hashtable(); + + m_log.Info("[RADMIN]: Request to restart Region."); + if (requiredPassword != String.Empty && (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) { @@ -119,24 +123,30 @@ namespace OpenSim.ApplicationPlugins.LoadRegions { XmlRpcResponse response = new XmlRpcResponse(); Hashtable requestData = (Hashtable) request.Params[0]; - Hashtable responseData = new Hashtable(); - if (requiredPassword != String.Empty && - (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) - { - responseData["accepted"] = "false"; - response.Value = responseData; - } - else - { + + try { + checkStringParameters(request, new string[] { "password", "message" }); + + if (requiredPassword != String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + throw new Exception("wrong password"); + string message = (string) requestData["message"]; - m_log.Info("[RADMIN]: Broadcasting: " + message); + m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); responseData["accepted"] = "true"; response.Value = responseData; m_app.SceneManager.SendGeneralMessage(message); } + catch(Exception e) + { + m_log.ErrorFormat("[RADMIN]: Broadcasting: failed: {0}", e.Message); + m_log.DebugFormat("[RADMIN]: Broadcasting: failed: {0}", e.ToString()); + responseData["accepted"] = "false"; + response.Value = responseData; + } return response; } @@ -146,35 +156,48 @@ namespace OpenSim.ApplicationPlugins.LoadRegions XmlRpcResponse response = new XmlRpcResponse(); Hashtable requestData = (Hashtable)request.Params[0]; - Hashtable responseData = new Hashtable(); - if (requiredPassword != String.Empty && - (!requestData.Contains("password") || (string)requestData["password"] != requiredPassword)) + m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}", request.ToString()); + foreach (string k in requestData.Keys) { - responseData["accepted"] = "false"; - response.Value = responseData; + m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}: >{1}< {2}", + k, (string)requestData[k], ((string)requestData[k]).Length); } - else - { + + Hashtable responseData = new Hashtable(); + try { + checkStringParameters(request, new string[] { "password", "filename", "regionid"}); + + if (requiredPassword != String.Empty && + (!requestData.Contains("password") || (string)requestData["password"] != requiredPassword)) + throw new Exception("wrong password"); + string file = (string)requestData["filename"]; - LLUUID regionID = LLUUID.Parse((string)requestData["regionid"]); - m_log.Info("[RADMIN]: Terrain Loading: " + file); + LLUUID regionID = (string) requestData["regionid"]; + m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); responseData["accepted"] = "true"; Scene region = null; - if (m_app.SceneManager.TryGetScene(regionID, out region)) - { - //region.LoadWorldMap(file); - responseData["success"] = "true"; - } - else - { - responseData["success"] = "false"; - responseData["error"] = "1: Unable to get a scene with that name."; - } + if (!m_app.SceneManager.TryGetScene(regionID, out region)) + throw new Exception("1: unable to get a scene with that name"); + + ITerrainModule terrainModule = region.RequestModuleInterface(); + if (null == terrainModule) throw new Exception("terrain module not available"); + terrainModule.LoadFromFile(file); + + responseData["success"] = "true"; + response.Value = responseData; } + catch (Exception e) + { + m_log.ErrorFormat("[RADMIN] Terrain Loading: failed: {0}", e.Message); + m_log.DebugFormat("[RADMIN] Terrain Loading: failed: {0}", e.ToString()); + + responseData["success"] = "false"; + responseData["error"] = e.Message; + } return response; } @@ -185,37 +208,32 @@ namespace OpenSim.ApplicationPlugins.LoadRegions XmlRpcResponse response = new XmlRpcResponse(); Hashtable requestData = (Hashtable) request.Params[0]; Hashtable responseData = new Hashtable(); - if (requiredPassword != String.Empty && - (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) - { - responseData["accepted"] = "false"; + + try { + checkStringParameters(request, new string[] { "password", "shutdown" }); + checkIntegerParams(request, new string[] { "milliseconds"}); + + if (requiredPassword != String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + throw new Exception("wrong password"); + + responseData["accepted"] = "true"; response.Value = responseData; - } - else - { + if ((string) requestData["shutdown"] == "delayed") { int timeout = (Int32) requestData["milliseconds"]; - - responseData["accepted"] = "true"; - response.Value = responseData; - m_app.SceneManager.SendGeneralMessage("Region is going down in " + ((int) (timeout/1000)).ToString() + " second(s). Please save what you are doing and log out."); - + // Perform shutdown Timer shutdownTimer = new Timer(timeout); // Wait before firing shutdownTimer.AutoReset = false; shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed); shutdownTimer.Start(); - - return response; - } + } else { - responseData["accepted"] = "true"; - response.Value = responseData; - m_app.SceneManager.SendGeneralMessage("Region is going down now."); // Perform shutdown @@ -223,10 +241,18 @@ namespace OpenSim.ApplicationPlugins.LoadRegions shutdownTimer.AutoReset = false; shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed); shutdownTimer.Start(); - - return response; } } + catch (Exception e) + { + m_log.ErrorFormat("[RADMIN] Shutdown: failed: {0}", e.Message); + m_log.DebugFormat("[RADMIN] Shutdown: failed: {0}", e.ToString()); + + responseData["accepted"] = "false"; + responseData["error"] = e.Message; + + response.Value = responseData; + } return response; } @@ -401,7 +427,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions region.SaveRegionToFile("dynamic region", regionConfigPath); } - m_app.CreateRegion(region, true); + m_app.CreateRegion(region); responseData["success"] = "true"; responseData["region_name"] = region.RegionName; @@ -484,8 +510,10 @@ namespace OpenSim.ApplicationPlugins.LoadRegions uint regX = Convert.ToUInt32((Int32)requestData["start_region_x"]); uint regY = Convert.ToUInt32((Int32)requestData["start_region_y"]); - // FIXME: need to check whether "firstname lastname" - // already exists! + UserProfileData userProfile = m_app.CommunicationsManager.UserService.GetUserProfile(firstname, lastname); + if (null != userProfile) + throw new Exception(String.Format("avatar {0} {1} already exists", firstname, lastname)); + LLUUID userID = m_app.CreateUser(firstname, lastname, passwd, regX, regY); if (userID == LLUUID.Zero) throw new Exception(String.Format("failed to create new user {0} {1}", @@ -523,22 +551,34 @@ namespace OpenSim.ApplicationPlugins.LoadRegions try { // check completeness - foreach (string p in new string[] { "password", "region_name", "filename" }) + foreach (string p in new string[] { "password", "filename" }) { if (!requestData.Contains(p)) throw new Exception(String.Format("missing parameter {0}", p)); + if (String.IsNullOrEmpty((string)requestData[p])) + throw new Exception(String.Format("parameter {0} is empty")); } // check password if (!String.IsNullOrEmpty(requiredPassword) && (string)requestData["password"] != requiredPassword) throw new Exception("wrong password"); - string region_name = (string)requestData["region_name"]; - string filename = (string)requestData["filename"]; - - if (!m_app.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}"); + string filename = (string)requestData["filename"]; + if (requestData.Contains("region_uuid")) + { + LLUUID region_uuid = (string)requestData["region_uuid"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string)requestData["region_name"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); responseData["switched"] = "true"; @@ -550,7 +590,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions catch (Exception e) { m_log.InfoFormat("[RADMIN] LoadXml: {0}", e.Message); - m_log.DebugFormat("[RADMIN] LoadXML {0}: {1}", e.ToString()); + m_log.DebugFormat("[RADMIN] LoadXml: {0}", e.ToString()); responseData["loaded"] = "false"; responseData["switched"] = "false"; diff --git a/OpenSim/Framework/Communications/Capabilities/CapsHandlers.cs b/OpenSim/Framework/Communications/Capabilities/CapsHandlers.cs index 3e3ae167d8..f101131ddb 100644 --- a/OpenSim/Framework/Communications/Capabilities/CapsHandlers.cs +++ b/OpenSim/Framework/Communications/Capabilities/CapsHandlers.cs @@ -44,6 +44,10 @@ namespace OpenSim.Region.Capabilities private uint m_httpListenerPort; /// + /// CapsHandlers is a cap handler container but also takes + /// care of adding and removing cap handlers to and from the + /// supplied BaseHttpServer. + /// /// base HTTP server /// host name of the HTTP /// server diff --git a/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs b/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs index cfaaf02a81..0c01c5afdc 100644 --- a/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs +++ b/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs @@ -63,7 +63,7 @@ namespace OpenSim.Framework.RegionLoader.Filesystem if (configFiles.Length == 0) { - new RegionInfo("DEFAULT REGION CONFIG", Path.Combine(regionConfigPath, "default.xml"),false); + new RegionInfo("DEFAULT REGION CONFIG", Path.Combine(regionConfigPath, "default.xml"), false); configFiles = Directory.GetFiles(regionConfigPath, "*.xml"); } diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index aa08f81db8..26ae52543b 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -462,7 +462,28 @@ namespace OpenSim /// /// /// - public UDPServer CreateRegion(RegionInfo regionInfo, bool portadd_flag) + public UDPServer CreateRegion(RegionInfo regionInfo, bool portadd_flag) { + return CreateRegion(regionInfo, portadd_flag, false); + } + + /// + /// Execute the region creation process. This includes setting up scene infrastructure. + /// + /// + /// + /// + public UDPServer CreateRegion(RegionInfo regionInfo) { + return CreateRegion(regionInfo, false, true); + } + + /// + /// Execute the region creation process. This includes setting up scene infrastructure. + /// + /// + /// + /// + /// + public UDPServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init) { int port = regionInfo.InternalEndPoint.Port; @@ -487,7 +508,7 @@ namespace OpenSim m_log.Info("[MODULES]: Loading Region's modules"); - m_moduleLoader.PickupModules(scene, "."); + List modules = m_moduleLoader.PickupModules(scene, "."); //m_moduleLoader.PickupModules(scene, "ScriptEngines"); //m_moduleLoader.LoadRegionModules(Path.Combine("ScriptEngines", m_scriptEngine), scene); @@ -536,6 +557,14 @@ namespace OpenSim m_regionData.Add(regionInfo); udpServer.ServerListener(); + if (do_post_init) + { + foreach (IRegionModule module in modules) + { + module.PostInitialise(); + } + } + return udpServer; } diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index bc0bea381b..a6124a9071 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -54,6 +54,9 @@ namespace OpenSim.Region.ClientStack protected uint m_httpServerPort; protected CommunicationsManager m_commsManager; + public CommunicationsManager CommunicationsManager { + get { return m_commsManager; } + } protected SceneManager m_sceneManager = new SceneManager(); diff --git a/OpenSim/Region/Environment/ModuleLoader.cs b/OpenSim/Region/Environment/ModuleLoader.cs index 43ca7bdb39..52a6fbd656 100644 --- a/OpenSim/Region/Environment/ModuleLoader.cs +++ b/OpenSim/Region/Environment/ModuleLoader.cs @@ -62,14 +62,16 @@ namespace OpenSim.Region.Environment } } - public void PickupModules(Scene scene, string moduleDir) + public List PickupModules(Scene scene, string moduleDir) { DirectoryInfo dir = new DirectoryInfo(moduleDir); + List modules = new List(); foreach (FileInfo fileInfo in dir.GetFiles("*.dll")) { - LoadRegionModules(fileInfo.FullName, scene); + modules.AddRange(LoadRegionModules(fileInfo.FullName, scene)); } + return modules; } public void LoadDefaultSharedModules() @@ -190,9 +192,10 @@ namespace OpenSim.Region.Environment } } - public void LoadRegionModules(string dllName, Scene scene) + public List LoadRegionModules(string dllName, Scene scene) { IRegionModule[] modules = LoadModules(dllName); + List initializedModules = new List(); if (modules.Length > 0) { @@ -203,6 +206,7 @@ namespace OpenSim.Region.Environment { m_log.InfoFormat("[MODULES]: [{0}]: Initializing.", module.Name); InitializeModule(module, scene); + initializedModules.Add(module); } else { @@ -211,6 +215,7 @@ namespace OpenSim.Region.Environment } } } + return initializedModules; } public void LoadRegionModule(string dllName, string moduleName, Scene scene) diff --git a/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs b/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs index 987c3d0877..f758c91224 100644 --- a/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs +++ b/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs @@ -178,20 +178,24 @@ namespace OpenSim.Region.Environment.Modules.Terrain { m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + " parser does not support file loading. (May be save only)"); - return; + throw new Exception(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); } catch (FileNotFoundException) { m_log.Error( "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); - return; + throw new Exception(String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", + filename)); } } + CheckForTerrainUpdates(); m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); return; } } m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader availible for that format."); + throw new Exception(String.Format("unable to load heightmap from file {0}: no loader available for that format", + filename)); } /// @@ -214,6 +218,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain catch (NotImplementedException) { m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); + throw new Exception(String.Format("unable to save heightmap: {0}: saving of this file format not implemented")); } } diff --git a/OpenSim/Region/Environment/Scenes/SceneManager.cs b/OpenSim/Region/Environment/Scenes/SceneManager.cs index 61a4eaeb1a..40e313ad94 100644 --- a/OpenSim/Region/Environment/Scenes/SceneManager.cs +++ b/OpenSim/Region/Environment/Scenes/SceneManager.cs @@ -250,6 +250,22 @@ namespace OpenSim.Region.Environment.Scenes } } + public bool TrySetCurrentScene(LLUUID regionID) + { + Console.WriteLine("Searching for Region: '{0}'", regionID.ToString()); + + foreach (Scene scene in m_localScenes) + { + if (scene.RegionInfo.RegionID == regionID) + { + m_currentScene = scene; + return true; + } + } + + return false; + } + public bool TryGetScene(string regionName, out Scene scene) { foreach (Scene mscene in m_localScenes)