* 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.0.6.0-stable
parent
3e997772ea
commit
5af108a029
|
@ -355,10 +355,16 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
public void TriggerOnBackup(IRegionDataStore dstore)
|
public void TriggerOnBackup(IRegionDataStore dstore)
|
||||||
{
|
{
|
||||||
handlerBackup = OnBackup;
|
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()
|
public void TriggerParcelPrimCountUpdate()
|
||||||
|
|
|
@ -1399,7 +1399,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
{
|
{
|
||||||
if (m_parentScene.ExternalChecks.ExternalChecksCanDuplicateObject(originPrim.Children.Count, originPrim.UUID, AgentID, originPrim.AbsolutePosition))
|
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.AbsolutePosition = copy.AbsolutePosition + offset;
|
||||||
copy.ResetIDs();
|
copy.ResetIDs();
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
public SynchronizeSceneHandler SynchronizeScene = null;
|
public SynchronizeSceneHandler SynchronizeScene = null;
|
||||||
public int splitID = 0;
|
public int splitID = 0;
|
||||||
|
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
protected Timer m_heartbeatTimer = new Timer();
|
protected Timer m_heartbeatTimer = new Timer();
|
||||||
|
@ -83,6 +84,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
private int m_RestartTimerCounter;
|
private int m_RestartTimerCounter;
|
||||||
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
|
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
|
||||||
private int m_incrementsof15seconds = 0;
|
private int m_incrementsof15seconds = 0;
|
||||||
|
private bool m_backingup = false;
|
||||||
|
|
||||||
public string m_simulatorVersion = "OpenSimulator 0.5";
|
public string m_simulatorVersion = "OpenSimulator 0.5";
|
||||||
|
|
||||||
|
@ -842,7 +844,14 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
|
|
||||||
private void UpdateStorageBackup()
|
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()
|
private void UpdateEvents()
|
||||||
|
@ -863,10 +872,11 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool Backup()
|
public void Backup()
|
||||||
{
|
{
|
||||||
EventManager.TriggerOnBackup(m_storageManager.DataStore);
|
EventManager.TriggerOnBackup(m_storageManager.DataStore);
|
||||||
return true;
|
m_backingup = false;
|
||||||
|
//return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -1085,13 +1085,24 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
/// <param name="datastore"></param>
|
/// <param name="datastore"></param>
|
||||||
public void ProcessBackup(IRegionDataStore datastore)
|
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;
|
HasGroupChanged = false;
|
||||||
|
|
||||||
|
backup_group.ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); });
|
||||||
|
|
||||||
|
backup_group = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); });
|
// Why is storing the inventory outside of HasGroupChanged?
|
||||||
|
|
||||||
|
|
||||||
|
//ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); });
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#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.
|
/// Duplicates this object, including operations such as physics set up and attaching to the backup event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID)
|
public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID, bool userExposed)
|
||||||
{
|
{
|
||||||
SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone();
|
SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone();
|
||||||
dupe.m_parts = new Dictionary<LLUUID, SceneObjectPart>();
|
dupe.m_parts = new Dictionary<LLUUID, SceneObjectPart>();
|
||||||
|
@ -1176,11 +1187,13 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
dupe.m_scene = m_scene;
|
dupe.m_scene = m_scene;
|
||||||
dupe.m_regionHandle = m_regionHandle;
|
dupe.m_regionHandle = m_regionHandle;
|
||||||
|
|
||||||
dupe.CopyRootPart(m_rootPart, OwnerID, GroupID);
|
dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
|
||||||
dupe.m_rootPart.TrimPermissions();
|
|
||||||
|
if (userExposed)
|
||||||
|
dupe.m_rootPart.TrimPermissions();
|
||||||
|
|
||||||
/// may need to create a new Physics actor.
|
/// may need to create a new Physics actor.
|
||||||
if (dupe.RootPart.PhysActor != null)
|
if (dupe.RootPart.PhysActor != null && userExposed)
|
||||||
{
|
{
|
||||||
PrimitiveBaseShape pbs = dupe.RootPart.Shape;
|
PrimitiveBaseShape pbs = dupe.RootPart.Shape;
|
||||||
|
|
||||||
|
@ -1202,26 +1215,36 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
// switch the owner to the person who did the copying
|
// switch the owner to the person who did the copying
|
||||||
// Second Life copies an object and duplicates the first one in it's place
|
// 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
|
// 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);
|
{
|
||||||
|
SetRootPartOwner(m_rootPart, cAgentID, cGroupID);
|
||||||
|
m_rootPart.ScheduleFullUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
m_rootPart.ScheduleFullUpdate();
|
|
||||||
|
|
||||||
List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.Values);
|
List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.Values);
|
||||||
foreach (SceneObjectPart part in partList)
|
foreach (SceneObjectPart part in partList)
|
||||||
{
|
{
|
||||||
if (part.UUID != m_rootPart.UUID)
|
if (part.UUID != m_rootPart.UUID)
|
||||||
{
|
{
|
||||||
dupe.CopyPart(part, OwnerID, GroupID);
|
dupe.CopyPart(part, OwnerID, GroupID, userExposed);
|
||||||
SetPartOwner(part, cAgentID, cGroupID);
|
|
||||||
part.ScheduleFullUpdate();
|
if (userExposed)
|
||||||
|
{
|
||||||
|
SetPartOwner(part, cAgentID, cGroupID);
|
||||||
|
part.ScheduleFullUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dupe.UpdateParentIDs();
|
|
||||||
|
|
||||||
dupe.AttachToBackup();
|
if (userExposed)
|
||||||
ScheduleGroupForFullUpdate();
|
{
|
||||||
|
dupe.UpdateParentIDs();
|
||||||
|
|
||||||
|
dupe.AttachToBackup();
|
||||||
|
ScheduleGroupForFullUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
return dupe;
|
return dupe;
|
||||||
}
|
}
|
||||||
|
@ -1232,9 +1255,9 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
/// <param name="part"></param>
|
/// <param name="part"></param>
|
||||||
/// <param name="cAgentID"></param>
|
/// <param name="cAgentID"></param>
|
||||||
/// <param name="cGroupID"></param>
|
/// <param name="cGroupID"></param>
|
||||||
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);
|
newPart.SetParent(this);
|
||||||
|
|
||||||
lock (m_parts)
|
lock (m_parts)
|
||||||
|
@ -1364,9 +1387,9 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
/// <param name="part"></param>
|
/// <param name="part"></param>
|
||||||
/// <param name="cAgentID"></param>
|
/// <param name="cAgentID"></param>
|
||||||
/// <param name="cGroupID"></param>
|
/// <param name="cGroupID"></param>
|
||||||
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);
|
newPart.SetParent(this);
|
||||||
|
|
||||||
lock (m_parts)
|
lock (m_parts)
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
|
ParentGroup.HasGroupChanged = true;
|
||||||
IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values);
|
IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values);
|
||||||
TaskInventory.Clear();
|
TaskInventory.Clear();
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
|
ParentGroup.HasGroupChanged = true;
|
||||||
IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values);
|
IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values);
|
||||||
foreach (TaskInventoryItem item in items)
|
foreach (TaskInventoryItem item in items)
|
||||||
{
|
{
|
||||||
|
@ -304,6 +304,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
m_inventorySerial++;
|
m_inventorySerial++;
|
||||||
//m_inventorySerial += 2;
|
//m_inventorySerial += 2;
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
|
ParentGroup.HasGroupChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -373,6 +374,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
TriggerScriptChangedEvent(Changed.INVENTORY);
|
TriggerScriptChangedEvent(Changed.INVENTORY);
|
||||||
|
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
|
ParentGroup.HasGroupChanged = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -411,6 +413,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
TriggerScriptChangedEvent(Changed.INVENTORY);
|
TriggerScriptChangedEvent(Changed.INVENTORY);
|
||||||
|
|
||||||
HasInventoryChanged = true;
|
HasInventoryChanged = true;
|
||||||
|
ParentGroup.HasGroupChanged = true;
|
||||||
|
|
||||||
int scriptcount = 0;
|
int scriptcount = 0;
|
||||||
lock (m_taskInventory)
|
lock (m_taskInventory)
|
||||||
|
|
|
@ -1523,12 +1523,14 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
/// Duplicates this part.
|
/// Duplicates this part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
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();
|
SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone();
|
||||||
dupe.m_shape = m_shape.Copy();
|
dupe.m_shape = m_shape.Copy();
|
||||||
dupe.m_regionHandle = m_regionHandle;
|
dupe.m_regionHandle = m_regionHandle;
|
||||||
dupe.UUID = LLUUID.Random();
|
if (userExposed)
|
||||||
|
dupe.UUID = LLUUID.Random();
|
||||||
|
|
||||||
dupe.LocalId = localID;
|
dupe.LocalId = localID;
|
||||||
dupe.OwnerID = AgentID;
|
dupe.OwnerID = AgentID;
|
||||||
dupe.GroupID = GroupID;
|
dupe.GroupID = GroupID;
|
||||||
|
@ -1548,7 +1550,8 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
|
|
||||||
dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone();
|
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.
|
// This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
|
||||||
dupe.LastOwnerID = ObjectOwner;
|
dupe.LastOwnerID = ObjectOwner;
|
||||||
|
@ -1556,13 +1559,16 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
byte[] extraP = new byte[Shape.ExtraParams.Length];
|
byte[] extraP = new byte[Shape.ExtraParams.Length];
|
||||||
Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
|
Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
|
||||||
dupe.Shape.ExtraParams = extraP;
|
dupe.Shape.ExtraParams = extraP;
|
||||||
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);
|
|
||||||
|
|
||||||
|
if (userExposed)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
return dupe;
|
return dupe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue