From 082f2baebe300e1313a34444c42dcc0a20c44baf Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Tue, 27 Nov 2007 13:46:52 +0000 Subject: Fixed an event in the events chain in inter-region communications. As a consequence, restarting sims in the same process instance now shows them when they come back up in grid mode and standalone mode. --- OpenSim/Region/Application/OpenSimMain.cs | 3 + .../Communications/Local/LocalBackEndServices.cs | 58 ++++++- .../Region/Communications/OGS1/OGS1GridServices.cs | 183 +++++++++++++++------ OpenSim/Region/Environment/Scenes/Scene.cs | 73 ++++++-- .../Scenes/SceneCommunicationService.cs | 31 +++- OpenSim/Region/Environment/Scenes/SceneManager.cs | 6 + 6 files changed, 284 insertions(+), 70 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index 1afa74a..eab4827 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -722,6 +722,9 @@ namespace OpenSim case "shutdown": Shutdown(); break; + case "restart": + m_sceneManager.RestartCurrentScene(); + break; case "change-region": if (cmdparams.Length > 0) diff --git a/OpenSim/Region/Communications/Local/LocalBackEndServices.cs b/OpenSim/Region/Communications/Local/LocalBackEndServices.cs index 746a19a..6e807ec 100644 --- a/OpenSim/Region/Communications/Local/LocalBackEndServices.cs +++ b/OpenSim/Region/Communications/Local/LocalBackEndServices.cs @@ -42,6 +42,28 @@ namespace OpenSim.Region.Communications.Local private Dictionary m_remoteRegionInfoCache = new Dictionary(); + public string _gdebugRegionName = ""; + + public string gdebugRegionName + { + get { return _gdebugRegionName; } + set + { + _gdebugRegionName = value; + + } + } + public string _rdebugRegionName = ""; + + public string rdebugRegionName + { + get { return _rdebugRegionName; } + set + { + _rdebugRegionName = value; + + } + } public LocalBackEndServices() { } @@ -54,18 +76,36 @@ namespace OpenSim.Region.Communications.Local public RegionCommsListener RegisterRegion(RegionInfo regionInfo) { //Console.WriteLine("CommsManager - Region " + regionInfo.RegionHandle + " , " + regionInfo.RegionLocX + " , "+ regionInfo.RegionLocY +" is registering"); - if (!m_regions.ContainsKey( regionInfo.RegionHandle)) + if (!m_regions.ContainsKey(regionInfo.RegionHandle)) { //Console.WriteLine("CommsManager - Adding Region " + regionInfo.RegionHandle ); m_regions.Add(regionInfo.RegionHandle, regionInfo); RegionCommsListener regionHost = new RegionCommsListener(); + if (m_regionListeners.ContainsKey(regionInfo.RegionHandle)) + { + OpenSim.Framework.Console.MainLog.Instance.Error("INTERREGION", "Error:Region registered twice as an Events listener for Interregion Communications but not as a listed region. In Standalone mode this will cause BIG issues. In grid mode, it means a region went down and came back up."); + m_regionListeners.Remove(regionInfo.RegionHandle); + } m_regionListeners.Add(regionInfo.RegionHandle, regionHost); return regionHost; } + else + { + // Already in our list, so the region went dead and restarted. + m_regions.Remove(regionInfo.RegionHandle); + OpenSim.Framework.Console.MainLog.Instance.Warn("INTERREGION", "Region registered twice. Region went down and came back up."); - //already in our list of regions so for now lets return null + RegionCommsListener regionHost = new RegionCommsListener(); + if (m_regionListeners.ContainsKey(regionInfo.RegionHandle)) + { + m_regionListeners.Remove(regionInfo.RegionHandle); + } + m_regionListeners.Add(regionInfo.RegionHandle, regionHost); + + return regionHost; + } return null; } @@ -168,7 +208,7 @@ namespace OpenSim.Region.Communications.Local listener.TriggerRegionUp(region); } - return true; + return false; } public bool TriggerRegionUp(RegionInfo region) @@ -181,10 +221,14 @@ namespace OpenSim.Region.Communications.Local //should change from agentCircuitData { //Console.WriteLine("CommsManager- Trying to Inform a region to expect child agent"); + //OpenSim.Framework.Console.MainLog.Instance.Verbose("INTER", rdebugRegionName + ":Local BackEnd: Trying to inform region of child agent: " + agentData.firstname + " " + agentData.lastname); + if (m_regionListeners.ContainsKey(regionHandle)) { // Console.WriteLine("CommsManager- Informing a region to expect child agent"); m_regionListeners[regionHandle].TriggerExpectUser(regionHandle, agentData); + //OpenSim.Framework.Console.MainLog.Instance.Verbose("INTER", rdebugRegionName + ":Local BackEnd: Got Listener trigginering local event: " + agentData.firstname + " " + agentData.lastname); + return true; } return false; @@ -277,8 +321,12 @@ namespace OpenSim.Region.Communications.Local public void TriggerExpectUser(ulong regionHandle, AgentCircuitData agent) { + //OpenSim.Framework.Console.MainLog.Instance.Verbose("INTER", rdebugRegionName + ":Local BackEnd: Other region is sending child agent our way: " + agent.firstname + " " + agent.lastname); + if (m_regionListeners.ContainsKey(regionHandle)) { + //OpenSim.Framework.Console.MainLog.Instance.Verbose("INTER", rdebugRegionName + ":Local BackEnd: FoundLocalRegion To send it to: " + agent.firstname + " " + agent.lastname); + m_regionListeners[regionHandle].TriggerExpectUser(regionHandle, agent); } } @@ -327,8 +375,12 @@ namespace OpenSim.Region.Communications.Local public bool IncomingChildAgent(ulong regionHandle, AgentCircuitData agentData) { + // OpenSim.Framework.Console.MainLog.Instance.Verbose("INTER", rdebugRegionName + ":Local BackEnd: Other local region is sending child agent our way: " + agentData.firstname + " " + agentData.lastname); + if (m_regionListeners.ContainsKey(regionHandle)) { + //OpenSim.Framework.Console.MainLog.Instance.Verbose("INTER", rdebugRegionName + ":Local BackEnd: found local region to trigger event on: " + agentData.firstname + " " + agentData.lastname); + TriggerExpectUser(regionHandle, agentData); return true; } diff --git a/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs b/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs index a0d6bd3..282b720 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs @@ -49,11 +49,33 @@ namespace OpenSim.Region.Communications.OGS1 { private LocalBackEndServices m_localBackend = new LocalBackEndServices(); private Dictionary m_remoteRegionInfoCache = new Dictionary(); + private List m_knownRegions = new List(); public BaseHttpServer httpListener; public NetworkServersInfo serversInfo; public BaseHttpServer httpServer; + public string _gdebugRegionName = ""; + public string gdebugRegionName + { + get { return _gdebugRegionName; } + set + { + _gdebugRegionName = value; + + } + } + public string _rdebugRegionName = ""; + + public string rdebugRegionName + { + get { return _rdebugRegionName; } + set + { + _rdebugRegionName = value; + + } + } /// /// /// @@ -105,10 +127,19 @@ namespace OpenSim.Region.Communications.OGS1 // Process Response if (GridRespData.ContainsKey("error")) { - string errorstring = (string) GridRespData["error"]; + string errorstring = (string)GridRespData["error"]; MainLog.Instance.Error("Unable to connect to grid: " + errorstring); return null; } + else + { + //m_knownRegions = RequestNeighbours(regionInfo.RegionLocX, regionInfo.RegionLocY); + + + } + //SimpleRegionInfo regiondata = new SimpleRegionInfo(); + //regiondata.RegionID = griddatahash["UUID"]; + //regiondata.RemotingAddress = return m_localBackend.RegisterRegion(regionInfo); } @@ -155,7 +186,53 @@ namespace OpenSim.Region.Communications.OGS1 return neighbours; } + /// + /// + /// + /// + /// + public RegionInfo RequestNeighbourInfo(LLUUID Region_UUID) + { + RegionInfo regionInfo; + Hashtable requestData = new Hashtable(); + requestData["region_UUID"] = Region_UUID.ToStringHyphenated(); + requestData["authkey"] = serversInfo.GridSendKey; + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); + XmlRpcResponse GridResp = GridReq.Send(serversInfo.GridURL, 3000); + + Hashtable responseData = (Hashtable)GridResp.Value; + if (responseData.ContainsKey("error")) + { + Console.WriteLine("error received from grid server" + responseData["error"]); + return null; + } + + uint regX = Convert.ToUInt32((string)responseData["region_locx"]); + uint regY = Convert.ToUInt32((string)responseData["region_locy"]); + string internalIpStr = (string)responseData["sim_ip"]; + uint port = Convert.ToUInt32(responseData["sim_port"]); + string externalUri = (string)responseData["sim_uri"]; + + IPEndPoint neighbourInternalEndPoint = new IPEndPoint(IPAddress.Parse(internalIpStr), (int)port); + string neighbourExternalUri = externalUri; + regionInfo = new RegionInfo(regX, regY, neighbourInternalEndPoint, internalIpStr); + + regionInfo.RemotingPort = Convert.ToUInt32((string)responseData["remoting_port"]); + regionInfo.RemotingAddress = internalIpStr; + + regionInfo.RegionID = new LLUUID((string)responseData["region_UUID"]); + regionInfo.RegionName = (string)responseData["region_name"]; + + if (requestData.ContainsKey("regionHandle")) + { + m_remoteRegionInfoCache.Add(Convert.ToUInt64((string)requestData["regionHandle"]), regionInfo); + } + + return regionInfo; + } /// /// /// @@ -381,7 +458,7 @@ namespace OpenSim.Region.Communications.OGS1 InterRegionSingleton.Instance.OnPrimGroupArrival += IncomingPrim; InterRegionSingleton.Instance.OnPrimGroupNear += TriggerExpectPrimCrossing; InterRegionSingleton.Instance.OnRegionUp += TriggerRegionUp; - + InterRegionSingleton.Instance.OnRegionUp += RegionUp; } #region Methods called by regions in this instance @@ -427,7 +504,7 @@ namespace OpenSim.Region.Communications.OGS1 Console.WriteLine("remoting object not found"); } remObject = null; - + MainLog.Instance.Verbose("INTER", gdebugRegionName + ": OGS1 tried to InformRegionOfChildAgent for " + agentData.firstname + " " + agentData.lastname + " and got " + retValue.ToString()); return retValue; } @@ -470,17 +547,27 @@ namespace OpenSim.Region.Communications.OGS1 // UGLY! public bool RegionUp(RegionInfo region) { - RegionInfo regInfo = null; - try + + // This is stupid. For this to work, when the region registers it must request nearby map blocks. + // In addition to filling the map blocks, it fills a 'known regions' list. + + // This known regions list then gets queried on here to get the remoting data from the neighbors. + // *Pull yourself up by your bootstraps?* + + if (m_localBackend.RegionUp(region)) { - if (m_localBackend.RegionUp(region)) - { - return true; - } - foreach (RegionInfo remoteInfo in m_remoteRegionInfoCache.Values) - { - regInfo = RequestNeighbourInfo(remoteInfo.RegionHandle); - if (regInfo != null) + return true; + } + return true; + foreach (SimpleRegionInfo knownregion in m_knownRegions) + { + // Wha? + RegionInfo regInfo = RequestNeighbourInfo(knownregion.RegionID); + + try + { + + if ((!(regInfo.Equals(null)) && regInfo.RemotingAddress.Length > 0)) { //don't want to be creating a new link to the remote instance every time like we are here bool retValue = false; @@ -501,43 +588,41 @@ namespace OpenSim.Region.Communications.OGS1 Console.WriteLine("remoting object not found"); } remObject = null; + //MainLog.Instance.Verbose("INTER", gdebugRegionName + ": OGS1 tried to NotifyRegionUp for " + region.RegionName + " and got " + retValue.ToString()); } } - - - return true; - } - catch (RemotingException e) - { - MainLog.Instance.Warn("Remoting Error: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); - MainLog.Instance.Debug(e.ToString()); - return false; - } - catch (SocketException e) - { - MainLog.Instance.Warn("Socket Error: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); - MainLog.Instance.Debug(e.ToString()); - return false; - } - catch (InvalidCredentialException e) - { - MainLog.Instance.Warn("Invalid Credentials: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); - MainLog.Instance.Debug(e.ToString()); - return false; - } - catch (AuthenticationException e) - { - MainLog.Instance.Warn("Authentication exception: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); - MainLog.Instance.Debug(e.ToString()); - return false; - } - catch (Exception e) - { - MainLog.Instance.Warn("Unknown exception: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); - MainLog.Instance.Debug(e.ToString()); - return false; + catch (RemotingException e) + { + MainLog.Instance.Warn("Remoting Error: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + MainLog.Instance.Debug(e.ToString()); + //return false; + } + catch (SocketException e) + { + MainLog.Instance.Warn("Socket Error: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + MainLog.Instance.Debug(e.ToString()); + //return false; + } + catch (InvalidCredentialException e) + { + MainLog.Instance.Warn("Invalid Credentials: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + MainLog.Instance.Debug(e.ToString()); + //return false; + } + catch (AuthenticationException e) + { + MainLog.Instance.Warn("Authentication exception: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + MainLog.Instance.Debug(e.ToString()); + //return false; + } + catch (Exception e) + { + MainLog.Instance.Warn("Unknown exception: Unable to connect to adjacent region: " + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + MainLog.Instance.Debug(e.ToString()); + //return false; + } } return true; } @@ -745,19 +830,23 @@ namespace OpenSim.Region.Communications.OGS1 /// public bool IncomingChildAgent(ulong regionHandle, AgentCircuitData agentData) { + //MainLog.Instance.Verbose("INTER", gdebugRegionName + ": Incoming OGS1 Agent " + agentData.firstname + " " + agentData.lastname); + try { return m_localBackend.IncomingChildAgent(regionHandle, agentData); } catch (RemotingException e) { - MainLog.Instance.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); + //MainLog.Instance.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); return false; } } public bool TriggerRegionUp(RegionInfo regionData) { + //MainLog.Instance.Verbose("INTER", gdebugRegionName + ": Incoming OGS1 RegionUpReport " + regionData.RegionName); + try { return m_localBackend.TriggerRegionUp(regionData); diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index a9791ee..d8723f6 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -57,6 +57,9 @@ namespace OpenSim.Region.Environment.Scenes { #region Fields protected Timer m_heartbeatTimer = new Timer(); + protected Timer m_restartWaitTimer = new Timer(); + + protected List m_regionRestartNotifyList = new List(); public InnerScene m_innerScene; @@ -210,6 +213,7 @@ namespace OpenSim.Region.Environment.Scenes m_authenticateHandler = authen; CommsManager = commsMan; m_sceneGridService = sceneGridService; + m_sceneGridService.debugRegionName = regInfo.RegionName; m_storageManager = storeManager; AssetCache = assetCach; m_regInfo = regInfo; @@ -244,6 +248,8 @@ namespace OpenSim.Region.Environment.Scenes httpListener = httpServer; m_dumpAssetsToFile = dumpAssetsToFile; + + // This function was moved to terrain for some kind of map hack by babble RegisterRegionWithComms(); } @@ -262,29 +268,23 @@ namespace OpenSim.Region.Environment.Scenes { // Another region is up. We have to tell all our ScenePresences about it // This fails to get the desired effect and needs further work. - try + if (RegionInfo.RegionHandle != otherRegion.RegionHandle) { - - ForEachScenePresence(delegate(ScenePresence agent) + if (!(m_regionRestartNotifyList.Contains(otherRegion))) { - if (!(agent.IsChildAgent)) - { - this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); - InformClientOfNeighbor(agent, otherRegion); - } + m_regionRestartNotifyList.Add(otherRegion); + + m_restartWaitTimer = new Timer(20000); + m_restartWaitTimer.AutoReset = false; + m_restartWaitTimer.Elapsed += new ElapsedEventHandler(restart_Notify_Wait_Elapsed); + m_restartWaitTimer.Start(); } - - ); - } - catch (System.NullReferenceException) - { - // This means that we're not booted up completely yet. } return true; } public virtual void Restart(float seconds) { - if (seconds < 100) + if (seconds < 15) { t_restartTimer.Stop(); SendGeneralAlert("Restart Aborted"); @@ -314,6 +314,7 @@ namespace OpenSim.Region.Environment.Scenes else { t_restartTimer.Stop(); + t_restartTimer.AutoReset = false; MainLog.Instance.Error("REGION", "Closing"); Close(); MainLog.Instance.Error("REGION", "Firing Region Restart Message"); @@ -321,6 +322,34 @@ namespace OpenSim.Region.Environment.Scenes } } + public void restart_Notify_Wait_Elapsed(object sender, ElapsedEventArgs e) + { + m_restartWaitTimer.Stop(); + foreach (RegionInfo region in m_regionRestartNotifyList) + { + try + { + + ForEachScenePresence(delegate(ScenePresence agent) + { + if (!(agent.IsChildAgent)) + { + //agent.ControllingClient.new + //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); + InformClientOfNeighbor(agent, region); + } + } + + ); + } + catch (System.NullReferenceException) + { + // This means that we're not booted up completely yet. + } + } + // Reset list to nothing. + m_regionRestartNotifyList = new List(); + } public override void Close() { ForEachScenePresence(delegate(ScenePresence avatar) @@ -642,7 +671,11 @@ namespace OpenSim.Region.Environment.Scenes } CreateTerrainTextureInitial(); - CommsManager.GridService.RegisterRegion(RegionInfo); //hack to update the terrain texture in grid mode so it shows on world map + //CommsManager.GridService.RegisterRegion(RegionInfo); //hack to update the terrain texture in grid mode so it shows on world map + + // These two 'commands' *must be* next to each other or sim rebooting fails. + m_sceneGridService.RegisterRegion(RegionInfo); + m_sceneGridService.InformNeighborsThatRegionisUp(RegionInfo); } catch (Exception e) { @@ -1073,13 +1106,17 @@ namespace OpenSim.Region.Environment.Scenes /// public void RegisterRegionWithComms() { - m_sceneGridService.RegisterRegion(m_regInfo); + // Don't register here. babblefro moved registration to *after *the map + // functions on line 675 so that a proper map will generate and get sent to grid services + // Double registrations will cause inter region communication issues + + //m_sceneGridService.RegisterRegion(m_regInfo); m_sceneGridService.OnExpectUser += NewUserConnection; m_sceneGridService.OnAvatarCrossingIntoRegion += AgentCrossing; m_sceneGridService.OnCloseAgentConnection += CloseConnection; m_sceneGridService.OnRegionUp += OtherRegionUp; // Tell Other regions that I'm here. - m_sceneGridService.InformNeighborsThatRegionisUp(RegionInfo); + } public void UnRegisterReginWithComms() { diff --git a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs index 18ce34d..0355a1b 100644 --- a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs @@ -22,25 +22,48 @@ namespace OpenSim.Region.Environment.Scenes public event CloseAgentConnection OnCloseAgentConnection; public event PrimCrossing OnPrimCrossingIntoRegion; public event RegionUp OnRegionUp; - + public string _debugRegionName = ""; + + public string debugRegionName + { + get { return _debugRegionName; } + set + { + _debugRegionName = value; + + + + } + } public SceneCommunicationService(CommunicationsManager commsMan) { m_commsProvider = commsMan; + m_commsProvider.GridService.gdebugRegionName = _debugRegionName; + m_commsProvider.InterRegion.rdebugRegionName = _debugRegionName; } public void RegisterRegion(RegionInfo regionInfos) { m_regionInfo = regionInfos; regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo); + if (regionCommsHost != null) { + //MainLog.Instance.Verbose("INTER", debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString()); + + regionCommsHost.debugRegionName = _debugRegionName; regionCommsHost.OnExpectUser += NewUserConnection; regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing; regionCommsHost.OnPrimCrossingIntoRegion += PrimCrossing; regionCommsHost.OnCloseAgentConnection += CloseConnection; regionCommsHost.OnRegionUp += newRegionUp; - + + + } + else + { + //MainLog.Instance.Verbose("INTER", debugRegionName + ": SceneCommunicationService: registered with gridservice and got null"); } } @@ -70,6 +93,7 @@ namespace OpenSim.Region.Environment.Scenes { if (OnExpectUser != null) { + //MainLog.Instance.Verbose("INTER", debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname); OnExpectUser(regionHandle, agent); } } @@ -78,6 +102,7 @@ namespace OpenSim.Region.Environment.Scenes { if (OnRegionUp != null) { + //MainLog.Instance.Verbose("INTER", debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName); OnRegionUp(region); } return true; @@ -188,6 +213,7 @@ namespace OpenSim.Region.Environment.Scenes /// public virtual RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle) { + //MainLog.Instance.Verbose("INTER", debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString()); return m_commsProvider.GridService.RequestNeighbourInfo(regionHandle); } @@ -275,6 +301,7 @@ namespace OpenSim.Region.Environment.Scenes public void InformNeighborsThatRegionisUp(RegionInfo region) { + //MainLog.Instance.Verbose("INTER", debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); bool val = m_commsProvider.InterRegion.RegionUp(region); } diff --git a/OpenSim/Region/Environment/Scenes/SceneManager.cs b/OpenSim/Region/Environment/Scenes/SceneManager.cs index c28269e..eba45fc 100644 --- a/OpenSim/Region/Environment/Scenes/SceneManager.cs +++ b/OpenSim/Region/Environment/Scenes/SceneManager.cs @@ -214,6 +214,12 @@ namespace OpenSim.Region.Environment.Scenes } } + public void RestartCurrentScene() + { + ForEachCurrentScene(delegate(Scene scene) { scene.Restart(15); }); + + } + public void BackupCurrentScene() { ForEachCurrentScene(delegate(Scene scene) { scene.Backup(); }); -- cgit v1.1