From d263a044b1ebb13477b2b391637ccc2da4368838 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Sun, 25 Nov 2007 04:52:14 +0000 Subject: [PATCH] * Added the ability to restart your individual sims from within them using the estate tools. * The sims properly restart, however they don't yet notify the existing avatars that they are up. To see the sim again, you'll need to log-out and back in until I can figure out how to get the proper data to the sims and to the avatar so they reconnect again. --- .../LoadRegions/LoadRegionsPlugin.cs | 29 ++++- OpenSim/Framework/IScene.cs | 19 ++++ OpenSim/Region/Application/OpenSimMain.cs | 46 +++++++- OpenSim/Region/ClientStack/UDPServer.cs | 14 +++ OpenSim/Region/Environment/EstateManager.cs | 19 ++++ .../Region/Environment/PermissionManager.cs | 8 ++ OpenSim/Region/Environment/Scenes/Scene.cs | 101 +++++++++++++++++- .../Region/Environment/Scenes/SceneBase.cs | 34 ++++++ .../Scenes/SceneCommunicationService.cs | 14 +++ .../Region/Environment/Scenes/SceneManager.cs | 60 ++++++++++- 10 files changed, 336 insertions(+), 8 deletions(-) diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs index e8509fcf85..3c12d58cac 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -37,7 +37,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions regionLoader.SetIniConfigSource(openSim.ConfigSource); RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); - + openSim.ModuleLoader.LoadDefaultSharedModules(); for (int i = 0; i < regionsToLoad.Length; i++) @@ -49,7 +49,34 @@ namespace OpenSim.ApplicationPlugins.LoadRegions openSim.ModuleLoader.PostInitialise(); openSim.ModuleLoader.ClearCache(); } + public void LoadRegionFromConfig(OpenSimMain openSim, ulong regionhandle) + { + System.Console.WriteLine("Load Regions addin being initialised"); + IRegionLoader regionLoader; + if (openSim.ConfigSource.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem") + { + MainLog.Instance.Notice("Loading Region Info from filesystem"); + regionLoader = new RegionLoaderFileSystem(); + } + else + { + MainLog.Instance.Notice("Loading Region Info from web"); + regionLoader = new RegionLoaderWebServer(); + } + + regionLoader.SetIniConfigSource(openSim.ConfigSource); + RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); + for (int i = 0; i < regionsToLoad.Length; i++) + { + if (regionhandle == regionsToLoad[i].RegionHandle) + { + MainLog.Instance.Debug("Creating Region: " + regionsToLoad[i].RegionName); + openSim.CreateRegion(regionsToLoad[i]); + } + } + + } public void Close() { diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index 2311afff33..0e4d260f81 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -29,14 +29,33 @@ using libsecondlife; namespace OpenSim.Framework { + public delegate void restart( RegionInfo thisRegion ); + public delegate void regionup ( RegionInfo thisRegion ); + + public enum RegionStatus : int + { + Down = 0, + Up = 1, + Crashed = 2, + Starting = 3 + }; + public interface IScene { + event restart OnRestart; + event regionup OnRegionUp; + void AddNewClient(IClientAPI client, bool child); void RemoveClient(LLUUID agentID); + void Restart(int seconds); + void OtherRegionUp(RegionInfo thisRegion); + RegionInfo RegionInfo { get; } uint NextLocalId { get; } + RegionStatus Region_Status { get; set; } + ClientManager ClientManager { get; } } } \ No newline at end of file diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index ed16cd4ca8..8edfc6fc64 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -320,7 +320,7 @@ namespace OpenSim plugin.Initialise(this); m_plugins.Add(plugin); } - + // Start UDP servers for (int i = 0; i < m_udpServers.Count; i++) { @@ -412,6 +412,50 @@ namespace OpenSim m_assetCache = new AssetCache(assetServer, m_log); // m_assetCache = new assetCache("OpenSim.Region.GridInterfaces.Local.dll", m_networkServersInfo.AssetURL, m_networkServersInfo.AssetSendKey); + m_sceneManager.OnReStartSim += handleReStartRegion; + + } + public void handleReStartRegion(RegionInfo whichRegion) + { + MainLog.Instance.Error("MAIN", "Got Restart Singlal from SceneManager"); + // Shutting down the UDP server + bool foundUDPServer = false; + int UDPServerElement = 0; + + for (int i = 0; i < m_udpServers.Count; i++) + { + + if (m_udpServers[i].RegionHandle == whichRegion.RegionHandle) + { + UDPServerElement = i; + foundUDPServer = true; + break; + } + } + if (foundUDPServer) + { + // m_udpServers[UDPServerElement].Server.End + m_udpServers[UDPServerElement].Server.Close(); + m_udpServers.RemoveAt(UDPServerElement); + } + + //Removing the region from the sim's database of regions.. + int RegionHandleElement = -1; + for (int i = 0; i < m_regionData.Count; i++) + { + if (whichRegion.RegionHandle == m_regionData[i].RegionHandle) + { + RegionHandleElement = i; + } + } + if (RegionHandleElement >= 0) + { + m_regionData.RemoveAt(RegionHandleElement); + } + UDPServer restartingRegion = CreateRegion(whichRegion); + restartingRegion.ServerListener(); + m_sceneManager.SendSimOnlineNotification(restartingRegion.RegionHandle); + } protected override LogBase CreateLog() diff --git a/OpenSim/Region/ClientStack/UDPServer.cs b/OpenSim/Region/ClientStack/UDPServer.cs index 8314fc3823..8f377c1a83 100644 --- a/OpenSim/Region/ClientStack/UDPServer.cs +++ b/OpenSim/Region/ClientStack/UDPServer.cs @@ -47,6 +47,7 @@ namespace OpenSim.Region.ClientStack protected EndPoint epSender; protected AsyncCallback ReceivedData; protected PacketServer m_packetServer; + protected ulong m_regionHandle; protected int listenPort; protected IScene m_localScene; @@ -66,6 +67,15 @@ namespace OpenSim.Region.ClientStack { m_localScene = value; m_packetServer.LocalScene = m_localScene; + m_regionHandle = m_localScene.RegionInfo.RegionHandle; + } + + } + public ulong RegionHandle + { + get + { + return m_regionHandle; } } @@ -115,6 +125,10 @@ namespace OpenSim.Region.ClientStack return; } + catch (System.ObjectDisposedException od) + { + return; + } int packetEnd = numBytes - 1; diff --git a/OpenSim/Region/Environment/EstateManager.cs b/OpenSim/Region/Environment/EstateManager.cs index c569fc597c..b847e4f16f 100644 --- a/OpenSim/Region/Environment/EstateManager.cs +++ b/OpenSim/Region/Environment/EstateManager.cs @@ -171,6 +171,12 @@ namespace OpenSim.Region.Environment if (m_scene.PermissionsMngr.CanEditEstateTerrain(remote_client.AgentId)) estateSetRegionTerrainHandler(packet); break; + case "restart": + if (m_scene.PermissionsMngr.CanRestartSim(remote_client.AgentId)) + { + estateRestartSim(packet); + } + break; default: MainLog.Instance.Error("EstateOwnerMessage: Unknown method requested\n" + packet.ToString()); break; @@ -322,6 +328,19 @@ namespace OpenSim.Region.Environment } } } + private void estateRestartSim(EstateOwnerMessagePacket packet) + { + // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. + foreach (EstateOwnerMessagePacket.ParamListBlock block in packet.ParamList) + { + float timeSeconds = 0; + timeSeconds = BitConverter.ToInt16(block.Parameter, 1); + timeSeconds = (int)((timeSeconds / 100) - 3); + m_scene.Restart(timeSeconds); + + } + } + #endregion diff --git a/OpenSim/Region/Environment/PermissionManager.cs b/OpenSim/Region/Environment/PermissionManager.cs index 412c6e71a1..6efa116f58 100644 --- a/OpenSim/Region/Environment/PermissionManager.cs +++ b/OpenSim/Region/Environment/PermissionManager.cs @@ -306,6 +306,14 @@ namespace OpenSim.Region.Environment return GenericEstatePermission(user); } + public virtual bool CanRestartSim(LLUUID user) + { + // Since this is potentially going on a grid... + + //return GenericEstatePermission(AgentId); + return m_scene.RegionInfo.MasterAvatarAssignedUUID == user; + } + #endregion #region Parcel Permissions diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 735dddb0b7..9cdb49bad2 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -70,6 +70,10 @@ namespace OpenSim.Region.Environment.Scenes private readonly Mutex updateLock; public bool m_physicalPrim; public bool m_sendTasksToChild; + private int m_RestartTimerCounter; + private Timer t_restartTimer = new Timer(15000); // Wait before firing + private int m_incrementsof15seconds = 0; + protected ModuleLoader m_moduleLoader; protected StorageManager m_storageManager; protected AgentCircuitManager m_authenticateHandler; @@ -253,15 +257,80 @@ namespace OpenSim.Region.Environment.Scenes m_eventManager.OnPermissionError += SendPermissionAlert; } + public override void OtherRegionUp(RegionInfo otherRegion) + { + // Another region is up. We have to tell all our ScenePresences about it + // This fails to get the desired effect and needs further work. + + ForEachScenePresence(delegate(ScenePresence agent) + { + if (!(agent.IsChildAgent)) + { + InformClientOfNeighbor(agent, otherRegion); + this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); + + } + } + ); + } + public virtual void Restart(float seconds) + { + if (seconds < 100) + { + t_restartTimer.Stop(); + SendGeneralAlert("Restart Aborted"); + } + else + { + t_restartTimer.Interval = 15000; + m_incrementsof15seconds = (int) seconds/15; + m_RestartTimerCounter = 0; + t_restartTimer.AutoReset = true; + t_restartTimer.Elapsed += new ElapsedEventHandler(restartTimer_Elapsed); + MainLog.Instance.Error("REGION", "Restarting Region in " + (seconds / 60) + " minutes"); + t_restartTimer.Start(); + SendGeneralAlert("Restarting in 2 Minutes"); + } + + + } + public void restartTimer_Elapsed(object sender, ElapsedEventArgs e) + { + m_RestartTimerCounter++; + if (m_RestartTimerCounter <= m_incrementsof15seconds) + { + if (m_RestartTimerCounter == 4 || m_RestartTimerCounter == 6 || m_RestartTimerCounter == 7) + SendGeneralAlert("Restarting in " + ((8-m_RestartTimerCounter) * 15) + " seconds"); + } + else + { + t_restartTimer.Stop(); + MainLog.Instance.Error("REGION", "Closing"); + Close(); + MainLog.Instance.Error("REGION", "Firing Region Restart Message"); + base.Restart(0); + } + + } public override void Close() { ForEachScenePresence(delegate(ScenePresence avatar) { - avatar.ControllingClient.Kick("The region is going down."); + if (avatar.KnownChildRegions.Contains(RegionInfo.RegionHandle)) + avatar.KnownChildRegions.Remove(RegionInfo.RegionHandle); + + if (!avatar.IsChildAgent) + avatar.ControllingClient.Kick("The simulator is going down."); + + avatar.ControllingClient.OutPacket(new libsecondlife.Packets.DisableSimulatorPacket(), ThrottleOutPacketType.Task); }); + + Thread.Sleep(500); + ForEachScenePresence(delegate(ScenePresence avatar) { + avatar.ControllingClient.Stop(); }); @@ -269,7 +338,7 @@ namespace OpenSim.Region.Environment.Scenes m_heartbeatTimer.Close(); m_innerScene.Close(); - m_sceneGridService.Close(); + UnRegisterReginWithComms(); foreach (IRegionModule module in this.Modules.Values) { @@ -992,6 +1061,14 @@ namespace OpenSim.Region.Environment.Scenes m_sceneGridService.OnAvatarCrossingIntoRegion += AgentCrossing; m_sceneGridService.OnCloseAgentConnection += CloseConnection; } + public void UnRegisterReginWithComms() + { + m_sceneGridService.OnExpectUser -= NewUserConnection; + m_sceneGridService.OnAvatarCrossingIntoRegion -= AgentCrossing; + m_sceneGridService.OnCloseAgentConnection -= CloseConnection; + + m_sceneGridService.Close(); + } /// /// @@ -1060,6 +1137,10 @@ namespace OpenSim.Region.Environment.Scenes { m_sceneGridService.EnableNeighbourChildAgents(presence); } + public void InformClientOfNeighbor(ScenePresence presence, RegionInfo region) + { + m_sceneGridService.InformNeighborChildAgent(presence, region); + } /// /// @@ -1258,9 +1339,15 @@ namespace OpenSim.Region.Environment.Scenes ClientManager.ForEachClient(delegate (IClientAPI controller) { - if (controller.AgentId != godid) // Do we really want to kick the initiator of this madness? + ScenePresence p = GetScenePresence(controller.AgentId); + bool childagent = false; + if (!p.Equals(null)) + if (p.IsChildAgent) + childagent=true; + if (controller.AgentId != godid && !childagent) // Do we really want to kick the initiator of this madness? { controller.Kick(Helpers.FieldToUTF8String(reason)); + } } ); @@ -1269,7 +1356,13 @@ namespace OpenSim.Region.Environment.Scenes // Is there another way to make sure *all* clients get this 'inter region' message? ClientManager.ForEachClient(delegate (IClientAPI controller) { - if (controller.AgentId != godid) // Do we really want to kick the initiator of this madness? + ScenePresence p = GetScenePresence(controller.AgentId); + bool childagent = false; + if (!p.Equals(null)) + if (p.IsChildAgent) + childagent = true; + + if (controller.AgentId != godid && !childagent) // Do we really want to kick the initiator of this madness? { controller.Close(); } diff --git a/OpenSim/Region/Environment/Scenes/SceneBase.cs b/OpenSim/Region/Environment/Scenes/SceneBase.cs index 1bb7d10825..43593747fc 100644 --- a/OpenSim/Region/Environment/Scenes/SceneBase.cs +++ b/OpenSim/Region/Environment/Scenes/SceneBase.cs @@ -27,6 +27,7 @@ */ using System; using System.Collections.Generic; +using System.Timers; using libsecondlife; using OpenSim.Framework; using OpenSim.Framework.Communications.Cache; @@ -37,6 +38,13 @@ namespace OpenSim.Region.Environment.Scenes { public abstract class SceneBase : IScene { + #region Events + + public event restart OnRestart; + public event regionup OnRegionUp; + + #endregion + #region Fields private readonly ClientManager m_clientManager = new ClientManager(); @@ -48,6 +56,7 @@ namespace OpenSim.Region.Environment.Scenes protected ulong m_regionHandle; protected string m_regionName; protected RegionInfo m_regInfo; + protected RegionStatus m_regStatus; public TerrainEngine Terrain; @@ -69,6 +78,12 @@ namespace OpenSim.Region.Environment.Scenes set { m_assetCache = value; } } + public RegionStatus Region_Status + { + get { return m_regStatus; } + set { m_regStatus = value; } + } + #endregion #region Update Methods @@ -78,6 +93,8 @@ namespace OpenSim.Region.Environment.Scenes /// public abstract void Update(); + + #endregion #region Terrain Methods @@ -130,6 +147,23 @@ namespace OpenSim.Region.Environment.Scenes get { return m_nextLocalId++; } } + #region admin stuff + + /// + /// Region Restart - Seconds till restart. + /// + /// + public virtual void Restart(int seconds) + { + MainLog.Instance.Error("REGION", "passing Restart Message up the namespace"); + OnRestart(RegionInfo); + } + + + public abstract void OtherRegionUp(RegionInfo thisRegion); + + + #endregion #region Shutdown /// diff --git a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs index ad7ff589dc..9a10c514e7 100644 --- a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs @@ -149,6 +149,20 @@ namespace OpenSim.Region.Environment.Scenes } } } + public void InformNeighborChildAgent(ScenePresence avatar, RegionInfo region) + { + AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo(); + agent.BaseFolder = LLUUID.Zero; + agent.InventoryFolder = LLUUID.Zero; + agent.startpos = new LLVector3(128, 128, 70); + agent.child = true; + + InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; + d.BeginInvoke(avatar, agent, region.RegionHandle, region.ExternalEndPoint, + InformClientOfNeighbourCompleted, + d); + } + #endregion /// diff --git a/OpenSim/Region/Environment/Scenes/SceneManager.cs b/OpenSim/Region/Environment/Scenes/SceneManager.cs index e71d94679d..4360d97f46 100644 --- a/OpenSim/Region/Environment/Scenes/SceneManager.cs +++ b/OpenSim/Region/Environment/Scenes/SceneManager.cs @@ -34,8 +34,12 @@ using OpenSim.Framework.Console; namespace OpenSim.Region.Environment.Scenes { + public delegate void ReStartSim(RegionInfo thisregion); + public class SceneManager { + public event ReStartSim OnReStartSim; + private readonly List m_localScenes; private Scene m_currentScene = null; @@ -72,11 +76,63 @@ namespace OpenSim.Region.Environment.Scenes } } - public void Add(Scene scene) + public void Close(Scene cscene) { - m_localScenes.Add(scene); + if (m_localScenes.Contains(cscene)) + { + for (int i = 0; i < m_localScenes.Count; i++) + { + if (m_localScenes[i].Equals(cscene)) + { + + m_localScenes[i].Close(); + } + } + } } + public void Add(Scene scene) + { + scene.OnRestart += handleRestart; + m_localScenes.Add(scene); + + } + + public void handleRestart(RegionInfo rdata) + { + MainLog.Instance.Error("SCENEMANAGER", "Got Restart message for region:" + rdata.RegionName +" Sending up to main"); + int RegionSceneElement = -1; + for (int i = 0; i < m_localScenes.Count; i++) + { + + if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName) + RegionSceneElement = i; + } + + // Now we make sure the region is no longer known about by the SceneManager + // Prevents Duplicates. + + if (RegionSceneElement >= 0) + m_localScenes.RemoveAt(RegionSceneElement); + + // Send signal to main that we're restarting this sim. + OnReStartSim(rdata); + } + + public void SendSimOnlineNotification(ulong regionHandle) + { + + for (int i = 0; i < m_localScenes.Count; i++) + { + if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle) + { + // Inform other regions to tell their avatar about me + m_localScenes[i].OtherRegionUp(m_localScenes[i].RegionInfo); + } + } + + + } public void SaveCurrentSceneToXml(string filename) { CurrentOrFirstScene.SavePrimsToXml(filename);