From 5af108a029e5382f6a2f6d4d10b3d4de3a8f5245 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Wed, 21 May 2008 21:22:56 +0000 Subject: * This update causes the backup process to run in a separate thread. * Concurrency issues are resolved because each object makes a memory-only copy of itself and backs up the copy. * Because of the way this is done, the latest at the time of the backup gets backed up (no functionality change) * You can move *thousands of objects at a time* and the sim doesn't freeze and wait for the backup to complete. * This can be enhanced more by dedicating the thread as opposed to starting it when the backup process starts. --- OpenSim/Region/Environment/Scenes/EventManager.cs | 10 +++- OpenSim/Region/Environment/Scenes/InnerScene.cs | 2 +- OpenSim/Region/Environment/Scenes/Scene.cs | 16 +++++- .../Region/Environment/Scenes/SceneObjectGroup.cs | 65 +++++++++++++++------- .../Scenes/SceneObjectPart.Inventory.cs | 7 ++- .../Region/Environment/Scenes/SceneObjectPart.cs | 22 +++++--- 6 files changed, 85 insertions(+), 37 deletions(-) (limited to 'OpenSim/Region/Environment/Scenes') diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs index 7ff9213..c6daa28 100644 --- a/OpenSim/Region/Environment/Scenes/EventManager.cs +++ b/OpenSim/Region/Environment/Scenes/EventManager.cs @@ -355,10 +355,16 @@ namespace OpenSim.Region.Environment.Scenes public void TriggerOnBackup(IRegionDataStore dstore) { handlerBackup = OnBackup; - if (handlerBackup != null) + Delegate[] items = OnBackup.GetInvocationList(); + foreach (OnBackupDelegate del in items) { - handlerBackup(dstore); + if (del != null) + del(dstore); } + //if (handlerBackup != null) + //{ + // handlerBackup(dstore); + //} } public void TriggerParcelPrimCountUpdate() diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs index 62055d8..695cb88 100644 --- a/OpenSim/Region/Environment/Scenes/InnerScene.cs +++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs @@ -1399,7 +1399,7 @@ namespace OpenSim.Region.Environment.Scenes { if (m_parentScene.ExternalChecks.ExternalChecksCanDuplicateObject(originPrim.Children.Count, originPrim.UUID, AgentID, originPrim.AbsolutePosition)) { - SceneObjectGroup copy = originPrim.Copy(AgentID, GroupID); + SceneObjectGroup copy = originPrim.Copy(AgentID, GroupID, true); copy.AbsolutePosition = copy.AbsolutePosition + offset; copy.ResetIDs(); diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 56d114c..280e09a 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -58,6 +58,7 @@ namespace OpenSim.Region.Environment.Scenes public SynchronizeSceneHandler SynchronizeScene = null; public int splitID = 0; + #region Fields protected Timer m_heartbeatTimer = new Timer(); @@ -83,6 +84,7 @@ namespace OpenSim.Region.Environment.Scenes private int m_RestartTimerCounter; private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing private int m_incrementsof15seconds = 0; + private bool m_backingup = false; public string m_simulatorVersion = "OpenSimulator 0.5"; @@ -842,7 +844,14 @@ namespace OpenSim.Region.Environment.Scenes private void UpdateStorageBackup() { - Backup(); + if (!m_backingup) + { + m_backingup = true; + Thread backupthread = new Thread(Backup); + backupthread.Name = "BackupWriter"; + backupthread.IsBackground = true; + backupthread.Start(); + } } private void UpdateEvents() @@ -863,10 +872,11 @@ namespace OpenSim.Region.Environment.Scenes /// /// /// - public bool Backup() + public void Backup() { EventManager.TriggerOnBackup(m_storageManager.DataStore); - return true; + m_backingup = false; + //return true; } #endregion diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs index 44e4c81..4b82bf9 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs @@ -1085,13 +1085,24 @@ namespace OpenSim.Region.Environment.Scenes /// public void ProcessBackup(IRegionDataStore datastore) { - if (HasGroupChanged) + // don't backup while it's selected or you're asking for changes mid stream. + if (HasGroupChanged && !IsSelected) { - datastore.StoreObject(this, m_scene.RegionInfo.RegionID); + m_log.Info("STORING"); + SceneObjectGroup backup_group = Copy(OwnerID, GroupID, false); + + datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); HasGroupChanged = false; + + backup_group.ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); }); + + backup_group = null; } + + // Why is storing the inventory outside of HasGroupChanged? - ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); }); + + //ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); }); } #endregion @@ -1165,7 +1176,7 @@ namespace OpenSim.Region.Environment.Scenes /// Duplicates this object, including operations such as physics set up and attaching to the backup event. /// /// - public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID) + public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID, bool userExposed) { SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone(); dupe.m_parts = new Dictionary(); @@ -1176,11 +1187,13 @@ namespace OpenSim.Region.Environment.Scenes dupe.m_scene = m_scene; dupe.m_regionHandle = m_regionHandle; - dupe.CopyRootPart(m_rootPart, OwnerID, GroupID); - dupe.m_rootPart.TrimPermissions(); + dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); + + if (userExposed) + dupe.m_rootPart.TrimPermissions(); /// may need to create a new Physics actor. - if (dupe.RootPart.PhysActor != null) + if (dupe.RootPart.PhysActor != null && userExposed) { PrimitiveBaseShape pbs = dupe.RootPart.Shape; @@ -1202,26 +1215,36 @@ namespace OpenSim.Region.Environment.Scenes // switch the owner to the person who did the copying // Second Life copies an object and duplicates the first one in it's place // So, we have to make a copy of this one, set it in it's place then set the owner on this one + if (userExposed) + { + SetRootPartOwner(m_rootPart, cAgentID, cGroupID); + m_rootPart.ScheduleFullUpdate(); + } - SetRootPartOwner(m_rootPart, cAgentID, cGroupID); - - - m_rootPart.ScheduleFullUpdate(); + List partList = new List(m_parts.Values); foreach (SceneObjectPart part in partList) { if (part.UUID != m_rootPart.UUID) { - dupe.CopyPart(part, OwnerID, GroupID); - SetPartOwner(part, cAgentID, cGroupID); - part.ScheduleFullUpdate(); + dupe.CopyPart(part, OwnerID, GroupID, userExposed); + + if (userExposed) + { + SetPartOwner(part, cAgentID, cGroupID); + part.ScheduleFullUpdate(); + } } } - dupe.UpdateParentIDs(); - dupe.AttachToBackup(); - ScheduleGroupForFullUpdate(); + if (userExposed) + { + dupe.UpdateParentIDs(); + + dupe.AttachToBackup(); + ScheduleGroupForFullUpdate(); + } return dupe; } @@ -1232,9 +1255,9 @@ namespace OpenSim.Region.Environment.Scenes /// /// /// - public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) + public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID, bool userExposed) { - SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); + SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count, userExposed); newPart.SetParent(this); lock (m_parts) @@ -1364,9 +1387,9 @@ namespace OpenSim.Region.Environment.Scenes /// /// /// - public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) + public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID, bool userExposed) { - SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); + SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count, userExposed); newPart.SetParent(this); lock (m_parts) diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs index d63260d..51521ff 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs @@ -99,7 +99,7 @@ namespace OpenSim.Region.Environment.Scenes } HasInventoryChanged = true; - + ParentGroup.HasGroupChanged = true; IList items = new List(TaskInventory.Values); TaskInventory.Clear(); @@ -121,7 +121,7 @@ namespace OpenSim.Region.Environment.Scenes } HasInventoryChanged = true; - + ParentGroup.HasGroupChanged = true; IList items = new List(TaskInventory.Values); foreach (TaskInventoryItem item in items) { @@ -304,6 +304,7 @@ namespace OpenSim.Region.Environment.Scenes m_inventorySerial++; //m_inventorySerial += 2; HasInventoryChanged = true; + ParentGroup.HasGroupChanged = true; } /// @@ -373,6 +374,7 @@ namespace OpenSim.Region.Environment.Scenes TriggerScriptChangedEvent(Changed.INVENTORY); HasInventoryChanged = true; + ParentGroup.HasGroupChanged = true; return true; } @@ -411,6 +413,7 @@ namespace OpenSim.Region.Environment.Scenes TriggerScriptChangedEvent(Changed.INVENTORY); HasInventoryChanged = true; + ParentGroup.HasGroupChanged = true; int scriptcount = 0; lock (m_taskInventory) diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index f5d3618..d95143e 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -1523,12 +1523,14 @@ namespace OpenSim.Region.Environment.Scenes /// Duplicates this part. /// /// - public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum) + public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum, bool userExposed) { SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone(); dupe.m_shape = m_shape.Copy(); dupe.m_regionHandle = m_regionHandle; - dupe.UUID = LLUUID.Random(); + if (userExposed) + dupe.UUID = LLUUID.Random(); + dupe.LocalId = localID; dupe.OwnerID = AgentID; dupe.GroupID = GroupID; @@ -1548,7 +1550,8 @@ namespace OpenSim.Region.Environment.Scenes dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone(); - dupe.ResetIDs(linkNum); + if (userExposed) + dupe.ResetIDs(linkNum); // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. dupe.LastOwnerID = ObjectOwner; @@ -1556,13 +1559,16 @@ namespace OpenSim.Region.Environment.Scenes byte[] extraP = new byte[Shape.ExtraParams.Length]; Array.Copy(Shape.ExtraParams, extraP, extraP.Length); dupe.Shape.ExtraParams = extraP; - if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != LLUUID.Zero) + + if (userExposed) { - m_parentGroup.Scene.AssetCache.GetAsset(dupe.m_shape.SculptTexture, dupe.SculptTextureCallback, true); + if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != LLUUID.Zero) + { + m_parentGroup.Scene.AssetCache.GetAsset(dupe.m_shape.SculptTexture, dupe.SculptTextureCallback, true); + } + bool UsePhysics = ((dupe.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0); + dupe.DoPhysicsPropertyUpdate(UsePhysics, true); } - bool UsePhysics = ((dupe.ObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0); - dupe.DoPhysicsPropertyUpdate(UsePhysics, true); - return dupe; } -- cgit v1.1