Merge branch 'master' into careminster-presence-refactor
commit
3284356bba
|
@ -247,6 +247,8 @@ namespace OpenSim.Data.MySQL
|
||||||
|
|
||||||
public void RemoveObject(UUID obj, UUID regionUUID)
|
public void RemoveObject(UUID obj, UUID regionUUID)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[REGION DB]: Deleting scene object {0} from {1} in database", obj, regionUUID);
|
||||||
|
|
||||||
List<UUID> uuids = new List<UUID>();
|
List<UUID> uuids = new List<UUID>();
|
||||||
|
|
||||||
// Formerly, this used to check the region UUID.
|
// Formerly, this used to check the region UUID.
|
||||||
|
|
|
@ -111,11 +111,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)
|
private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
m_log.Debug("[SCENE]: Starting send to inventory loop");
|
m_log.Debug("[ASYNC DELETER]: Starting send to inventory loop");
|
||||||
|
|
||||||
while (InventoryDeQueueAndDelete())
|
while (InventoryDeQueueAndDelete())
|
||||||
{
|
{
|
||||||
//m_log.Debug("[SCENE]: Sent item successfully to inventory, continuing...");
|
//m_log.Debug("[ASYNC DELETER]: Sent item successfully to inventory, continuing...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
x = m_inventoryDeletes.Dequeue();
|
x = m_inventoryDeletes.Dequeue();
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left);
|
"[ASYNC DELETER]: Sending object to user's inventory, {0} item(s) remaining.", left);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -152,7 +152,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("Exception background sending object: " + e);
|
m_log.ErrorFormat(
|
||||||
|
"[ASYNC DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -164,12 +165,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// We can't put the object group details in here since the root part may have disappeared (which is where these sit).
|
// We can't put the object group details in here since the root part may have disappeared (which is where these sit).
|
||||||
// FIXME: This needs to be fixed.
|
// FIXME: This needs to be fixed.
|
||||||
m_log.ErrorFormat(
|
m_log.ErrorFormat(
|
||||||
"[SCENE]: Queued sending of scene object to agent {0} {1} failed: {2}",
|
"[ASYNC DELETER]: Queued sending of scene object to agent {0} {1} failed: {2} {3}",
|
||||||
(x != null ? x.remoteClient.Name : "unavailable"), (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"), e.ToString());
|
(x != null ? x.remoteClient.Name : "unavailable"),
|
||||||
|
(x != null ? x.remoteClient.AgentId.ToString() : "unavailable"),
|
||||||
|
e.Message,
|
||||||
|
e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.Debug("[SCENE]: No objects left in inventory send queue.");
|
m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue.");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -69,6 +69,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public bool IsDeleted
|
public bool IsDeleted
|
||||||
{
|
{
|
||||||
get { return m_isDeleted; }
|
get { return m_isDeleted; }
|
||||||
|
set { m_isDeleted = value; }
|
||||||
}
|
}
|
||||||
protected bool m_isDeleted;
|
protected bool m_isDeleted;
|
||||||
|
|
||||||
|
|
|
@ -688,7 +688,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerOnBackup(IRegionDataStore dstore)
|
public void TriggerOnBackup(IRegionDataStore dstore, bool forced)
|
||||||
{
|
{
|
||||||
OnBackupDelegate handlerOnAttach = OnBackup;
|
OnBackupDelegate handlerOnAttach = OnBackup;
|
||||||
if (handlerOnAttach != null)
|
if (handlerOnAttach != null)
|
||||||
|
@ -697,7 +697,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d(dstore, false);
|
d(dstore, forced);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1719,7 +1719,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public virtual void DeRezObject(IClientAPI remoteClient, uint localID,
|
public virtual void DeRezObject(IClientAPI remoteClient, uint localID,
|
||||||
UUID groupID, DeRezAction action, UUID destinationID)
|
UUID groupID, DeRezAction action, UUID destinationID)
|
||||||
{
|
{
|
||||||
DeRezObjects(remoteClient, new List<uint>() { localID} , groupID, action, destinationID);
|
DeRezObjects(remoteClient, new List<uint>() { localID }, groupID, action, destinationID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void DeRezObjects(IClientAPI remoteClient, List<uint> localIDs,
|
public virtual void DeRezObjects(IClientAPI remoteClient, List<uint> localIDs,
|
||||||
|
@ -1764,11 +1764,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
deleteIDs.Add(localID);
|
deleteIDs.Add(localID);
|
||||||
deleteGroups.Add(grp);
|
deleteGroups.Add(grp);
|
||||||
|
|
||||||
// Force a database backup/update on this SceneObjectGroup
|
|
||||||
// So that we know the database is upto date,
|
|
||||||
// for when deleting the object from it
|
|
||||||
ForceSceneObjectBackup(grp);
|
|
||||||
|
|
||||||
if (remoteClient == null)
|
if (remoteClient == null)
|
||||||
{
|
{
|
||||||
// Autoreturn has a null client. Nothing else does. So
|
// Autoreturn has a null client. Nothing else does. So
|
||||||
|
|
|
@ -1562,18 +1562,22 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void BackupWaitCallback(object o)
|
private void BackupWaitCallback(object o)
|
||||||
{
|
{
|
||||||
Backup();
|
Backup(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Backup the scene. This acts as the main method of the backup thread.
|
/// Backup the scene. This acts as the main method of the backup thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="forced">
|
||||||
|
/// If true, then any changes that have not yet been persisted are persisted. If false,
|
||||||
|
/// then the persistence decision is left to the backup code (in some situations, such as object persistence,
|
||||||
|
/// it's much more efficient to backup multiple changes at once rather than every single one).
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void Backup()
|
public void Backup(bool forced)
|
||||||
{
|
{
|
||||||
lock (m_returns)
|
lock (m_returns)
|
||||||
{
|
{
|
||||||
EventManager.TriggerOnBackup(m_storageManager.DataStore);
|
EventManager.TriggerOnBackup(m_storageManager.DataStore, forced);
|
||||||
m_backingup = false;
|
m_backingup = false;
|
||||||
|
|
||||||
foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
|
foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
|
||||||
|
@ -2155,7 +2159,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// rootPart.PhysActor = null;
|
// rootPart.PhysActor = null;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (UnlinkSceneObject(group.UUID, false))
|
if (UnlinkSceneObject(group, false))
|
||||||
{
|
{
|
||||||
EventManager.TriggerObjectBeingRemovedFromScene(group);
|
EventManager.TriggerObjectBeingRemovedFromScene(group);
|
||||||
EventManager.TriggerParcelPrimCountTainted();
|
EventManager.TriggerParcelPrimCountTainted();
|
||||||
|
@ -2170,18 +2174,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the
|
/// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the
|
||||||
/// object itself is not destroyed.
|
/// object itself is not destroyed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uuid">Id of object.</param>
|
/// <param name="so">The scene object.</param>
|
||||||
|
/// <param name="softDelete">If true, only deletes from scene, but keeps the object in the database.</param>
|
||||||
/// <returns>true if the object was in the scene, false if it was not</returns>
|
/// <returns>true if the object was in the scene, false if it was not</returns>
|
||||||
/// <param name="softDelete">If true, only deletes from scene, but keeps object in database.</param>
|
public bool UnlinkSceneObject(SceneObjectGroup so, bool softDelete)
|
||||||
public bool UnlinkSceneObject(UUID uuid, bool softDelete)
|
|
||||||
{
|
{
|
||||||
if (m_sceneGraph.DeleteSceneObject(uuid, softDelete))
|
if (m_sceneGraph.DeleteSceneObject(so.UUID, softDelete))
|
||||||
{
|
{
|
||||||
if (!softDelete)
|
if (!softDelete)
|
||||||
{
|
{
|
||||||
m_storageManager.DataStore.RemoveObject(uuid,
|
// Force a database update so that the scene object group ID is accurate. It's possible that the
|
||||||
m_regInfo.RegionID);
|
// group has recently been delinked from another group but that this change has not been persisted
|
||||||
|
// to the DB.
|
||||||
|
ForceSceneObjectBackup(so);
|
||||||
|
so.DetachFromBackup();
|
||||||
|
m_storageManager.DataStore.RemoveObject(so.UUID, m_regInfo.RegionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to keep track of this state in case this group is still queued for further backup.
|
||||||
|
so.IsDeleted = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2212,7 +2223,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
|
m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2229,7 +2240,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
m_log.Warn("[DATABASE]: exception when trying to return the prim that crossed the border.");
|
m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void BackupCurrentScene()
|
public void BackupCurrentScene()
|
||||||
{
|
{
|
||||||
ForEachCurrentScene(delegate(Scene scene) { scene.Backup(); });
|
ForEachCurrentScene(delegate(Scene scene) { scene.Backup(true); });
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TrySetCurrentScene(string regionName)
|
public bool TrySetCurrentScene(string regionName)
|
||||||
|
|
|
@ -1556,9 +1556,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete this group from its scene and tell all the scene presences about that deletion.
|
/// Delete this group from its scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="silent">Broadcast deletions to all clients.</param>
|
///
|
||||||
|
/// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood
|
||||||
|
/// up and all avatars receive notification of its removal. Removal of the scene object from database backup
|
||||||
|
/// must be handled by the caller.
|
||||||
|
///
|
||||||
|
/// <param name="silent">If true then deletion is not broadcast to clients</param>
|
||||||
public void DeleteGroup(bool silent)
|
public void DeleteGroup(bool silent)
|
||||||
{
|
{
|
||||||
// We need to keep track of this state in case this group is still queued for backup.
|
// We need to keep track of this state in case this group is still queued for backup.
|
||||||
|
@ -1729,14 +1734,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public virtual void ProcessBackup(IRegionDataStore datastore, bool forcedBackup)
|
public virtual void ProcessBackup(IRegionDataStore datastore, bool forcedBackup)
|
||||||
{
|
{
|
||||||
if (!m_isBackedUp)
|
if (!m_isBackedUp)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WATER WARS]: Ignoring backup of {0} {1} since object is not marked to be backed up", Name, UUID);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
// Since this is the top of the section of call stack for backing up a particular scene object, don't let
|
|
||||||
// any exception propogate upwards.
|
|
||||||
|
|
||||||
if (IsDeleted || UUID == UUID.Zero)
|
if (IsDeleted || UUID == UUID.Zero)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since this is the top of the section of call stack for backing up a particular scene object, don't let
|
||||||
|
// any exception propogate upwards.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
|
if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
|
||||||
|
@ -1772,7 +1784,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (HasGroupChanged)
|
if (HasGroupChanged)
|
||||||
{
|
{
|
||||||
// don't backup while it's selected or you're asking for changes mid stream.
|
// don't backup while it's selected or you're asking for changes mid stream.
|
||||||
if ((isTimeToPersist()) || (forcedBackup))
|
if (isTimeToPersist() || forcedBackup)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENE]: Storing {0}, {1} in {2}",
|
// "[SCENE]: Storing {0}, {1} in {2}",
|
||||||
|
@ -1795,19 +1807,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
backup_group = null;
|
backup_group = null;
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENE]: Did not update persistence of object {0} {1}, selected = {2}",
|
// "[SCENE]: Did not update persistence of object {0} {1}, selected = {2}",
|
||||||
// Name, UUID, IsSelected);
|
// Name, UUID, IsSelected);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
m_log.ErrorFormat(
|
||||||
"[SCENE]: Storing of {0}, {1} in {2} failed with exception {3}\n\t{4}",
|
"[SCENE]: Storing of {0}, {1} in {2} failed with exception {3}{4}",
|
||||||
Name, UUID, m_scene.RegionInfo.RegionName, e, e.StackTrace);
|
Name, UUID, m_scene.RegionInfo.RegionName, e.Message, e.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2672,7 +2684,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
part.ClearUndoState();
|
part.ClearUndoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_scene.UnlinkSceneObject(objectGroup.UUID, true);
|
m_scene.UnlinkSceneObject(objectGroup, true);
|
||||||
objectGroup.m_isDeleted = true;
|
objectGroup.m_isDeleted = true;
|
||||||
|
|
||||||
objectGroup.lockPartsForWrite(true);
|
objectGroup.lockPartsForWrite(true);
|
||||||
|
|
|
@ -28,20 +28,21 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Scenes.Tests
|
namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class BorderTests
|
public class BorderTests
|
||||||
{
|
{
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCross()
|
public void TestCross()
|
||||||
{
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
|
||||||
List<Border> testborders = new List<Border>();
|
List<Border> testborders = new List<Border>();
|
||||||
|
|
||||||
Border NorthBorder = new Border();
|
Border NorthBorder = new Border();
|
||||||
|
@ -75,8 +76,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
position = new Vector3(200,280,21);
|
position = new Vector3(200,280,21);
|
||||||
Assert.That(NorthBorder.TestCross(position));
|
Assert.That(NorthBorder.TestCross(position));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Test automatic border crossing
|
// Test automatic border crossing
|
||||||
// by setting the border crossing aabb to be the whole region
|
// by setting the border crossing aabb to be the whole region
|
||||||
position = new Vector3(25,25,21); // safely within one 256m region
|
position = new Vector3(25,25,21); // safely within one 256m region
|
||||||
|
@ -95,12 +94,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
|
||||||
WestBorder.BorderLine = new Vector3(0, 256, 255); // automatic border cross in the region
|
WestBorder.BorderLine = new Vector3(0, 256, 255); // automatic border cross in the region
|
||||||
Assert.That(WestBorder.TestCross(position));
|
Assert.That(WestBorder.TestCross(position));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCrossSquare512()
|
public void TestCrossSquare512()
|
||||||
{
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
|
||||||
List<Border> testborders = new List<Border>();
|
List<Border> testborders = new List<Border>();
|
||||||
|
|
||||||
Border NorthBorder = new Border();
|
Border NorthBorder = new Border();
|
||||||
|
@ -174,12 +174,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(!b.TestCross(position));
|
Assert.That(!b.TestCross(position));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCrossRectangle512x256()
|
public void TestCrossRectangle512x256()
|
||||||
{
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
|
||||||
List<Border> testborders = new List<Border>();
|
List<Border> testborders = new List<Border>();
|
||||||
|
|
||||||
Border NorthBorder = new Border();
|
Border NorthBorder = new Border();
|
||||||
|
@ -258,6 +259,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCrossOdd512x512w256hole()
|
public void TestCrossOdd512x512w256hole()
|
||||||
{
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
|
||||||
List<Border> testborders = new List<Border>();
|
List<Border> testborders = new List<Border>();
|
||||||
// 512____
|
// 512____
|
||||||
// | |
|
// | |
|
||||||
|
|
|
@ -53,7 +53,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
public void T010_AddObjects()
|
public void T010_AddObjects()
|
||||||
{
|
{
|
||||||
TestHelper.InMethod();
|
TestHelper.InMethod();
|
||||||
// Console.WriteLine("Beginning test {0}", MethodBase.GetCurrentMethod());
|
|
||||||
|
|
||||||
random = new Random();
|
random = new Random();
|
||||||
SceneObjectGroup found;
|
SceneObjectGroup found;
|
||||||
|
@ -89,7 +88,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
public void T011_ThreadAddRemoveTest()
|
public void T011_ThreadAddRemoveTest()
|
||||||
{
|
{
|
||||||
TestHelper.InMethod();
|
TestHelper.InMethod();
|
||||||
// Console.WriteLine("Beginning test {0}", MethodBase.GetCurrentMethod());
|
|
||||||
|
|
||||||
// This test adds and removes with mutiple threads, attempting to break the
|
// This test adds and removes with mutiple threads, attempting to break the
|
||||||
// uuid and localid dictionary coherence.
|
// uuid and localid dictionary coherence.
|
||||||
|
|
|
@ -26,13 +26,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NUnit.Framework.SyntaxHelpers;
|
using NUnit.Framework.SyntaxHelpers;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Communications;
|
using OpenSim.Framework.Communications;
|
||||||
|
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Tests.Common;
|
using OpenSim.Tests.Common;
|
||||||
using OpenSim.Tests.Common.Mock;
|
using OpenSim.Tests.Common.Mock;
|
||||||
|
@ -260,5 +260,86 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
&& (part4.RotationOffset.W - compareQuaternion.W < 0.00003),
|
&& (part4.RotationOffset.W - compareQuaternion.W < 0.00003),
|
||||||
"Badness 3");
|
"Badness 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test that a new scene object which is already linked is correctly persisted to the persistence layer.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestNewSceneObjectLinkPersistence()
|
||||||
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
//log4net.Config.XmlConfigurator.Configure();
|
||||||
|
|
||||||
|
TestScene scene = SceneSetupHelpers.SetupScene();
|
||||||
|
|
||||||
|
string rootPartName = "rootpart";
|
||||||
|
UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001");
|
||||||
|
string linkPartName = "linkpart";
|
||||||
|
UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000");
|
||||||
|
|
||||||
|
SceneObjectPart rootPart
|
||||||
|
= new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
|
||||||
|
{ Name = rootPartName, UUID = rootPartUuid };
|
||||||
|
SceneObjectPart linkPart
|
||||||
|
= new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
|
||||||
|
{ Name = linkPartName, UUID = linkPartUuid };
|
||||||
|
|
||||||
|
SceneObjectGroup sog = new SceneObjectGroup(rootPart);
|
||||||
|
sog.AddPart(linkPart);
|
||||||
|
scene.AddNewSceneObject(sog, true);
|
||||||
|
|
||||||
|
// In a test, we have to crank the backup handle manually. Normally this would be done by the timer invoked
|
||||||
|
// scene backup thread.
|
||||||
|
scene.Backup(true);
|
||||||
|
|
||||||
|
List<SceneObjectGroup> storedObjects = scene.StorageManager.DataStore.LoadObjects(scene.RegionInfo.RegionID);
|
||||||
|
|
||||||
|
Assert.That(storedObjects.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(storedObjects[0].Children.Count, Is.EqualTo(2));
|
||||||
|
Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid));
|
||||||
|
Assert.That(storedObjects[0].Children.ContainsKey(linkPartUuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test that a delink of a previously linked object is correctly persisted to the database
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestDelinkPersistence()
|
||||||
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
//log4net.Config.XmlConfigurator.Configure();
|
||||||
|
|
||||||
|
TestScene scene = SceneSetupHelpers.SetupScene();
|
||||||
|
|
||||||
|
string rootPartName = "rootpart";
|
||||||
|
UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001");
|
||||||
|
string linkPartName = "linkpart";
|
||||||
|
UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000");
|
||||||
|
|
||||||
|
SceneObjectPart rootPart
|
||||||
|
= new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
|
||||||
|
{ Name = rootPartName, UUID = rootPartUuid };
|
||||||
|
SceneObjectPart linkPart
|
||||||
|
= new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
|
||||||
|
{ Name = linkPartName, UUID = linkPartUuid };
|
||||||
|
|
||||||
|
SceneObjectGroup sog = new SceneObjectGroup(rootPart);
|
||||||
|
sog.AddPart(linkPart);
|
||||||
|
scene.AddNewSceneObject(sog, true);
|
||||||
|
|
||||||
|
// In a test, we have to crank the backup handle manually. Normally this would be done by the timer invoked
|
||||||
|
// scene backup thread.
|
||||||
|
scene.Backup(true);
|
||||||
|
|
||||||
|
// These changes should occur immediately without waiting for a backup pass
|
||||||
|
SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false);
|
||||||
|
scene.DeleteSceneObject(groupToDelete, false);
|
||||||
|
|
||||||
|
List<SceneObjectGroup> storedObjects = scene.StorageManager.DataStore.LoadObjects(scene.RegionInfo.RegionID);
|
||||||
|
|
||||||
|
Assert.That(storedObjects.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(storedObjects[0].Children.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
|
||||||
Assert.That(neighbours.Count, Is.EqualTo(2));
|
Assert.That(neighbours.Count, Is.EqualTo(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fixNullPresence()
|
public void fixNullPresence()
|
||||||
{
|
{
|
||||||
string firstName = "testfirstname";
|
string firstName = "testfirstname";
|
||||||
|
@ -389,8 +390,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
|
||||||
public static string GetRandomCapsObjectPath()
|
public static string GetRandomCapsObjectPath()
|
||||||
{
|
{
|
||||||
TestHelper.InMethod();
|
|
||||||
|
|
||||||
UUID caps = UUID.Random();
|
UUID caps = UUID.Random();
|
||||||
string capsPath = caps.ToString();
|
string capsPath = caps.ToString();
|
||||||
capsPath = capsPath.Remove(capsPath.Length - 4, 4);
|
capsPath = capsPath.Remove(capsPath.Length - 4, 4);
|
||||||
|
@ -429,4 +428,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
return name.ToString();
|
return name.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -300,7 +300,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup.");
|
m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup.");
|
||||||
scene.Backup();
|
scene.Backup(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -133,7 +133,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
|
||||||
m_firstEmptyCompileQueue = false;
|
m_firstEmptyCompileQueue = false;
|
||||||
m_oarFileLoading = false;
|
m_oarFileLoading = false;
|
||||||
|
|
||||||
m_scene.Backup();
|
m_scene.Backup(false);
|
||||||
|
|
||||||
c.From = "RegionReady";
|
c.From = "RegionReady";
|
||||||
if (m_lastOarLoadedOk)
|
if (m_lastOarLoadedOk)
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Data.Null
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Mock region data plugin. This obeys the api contract for persistence but stores everything in memory, so that
|
||||||
|
/// tests can check correct persistence.
|
||||||
|
/// </summary>
|
||||||
|
public class NullDataStore : IRegionDataStore
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
protected Dictionary<UUID, RegionSettings> m_regionSettings = new Dictionary<UUID, RegionSettings>();
|
||||||
|
protected Dictionary<UUID, SceneObjectPart> m_sceneObjectParts = new Dictionary<UUID, SceneObjectPart>();
|
||||||
|
protected Dictionary<UUID, ICollection<TaskInventoryItem>> m_primItems
|
||||||
|
= new Dictionary<UUID, ICollection<TaskInventoryItem>>();
|
||||||
|
protected Dictionary<UUID, double[,]> m_terrains = new Dictionary<UUID, double[,]>();
|
||||||
|
protected Dictionary<UUID, LandData> m_landData = new Dictionary<UUID, LandData>();
|
||||||
|
|
||||||
|
public void Initialise(string dbfile)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StoreRegionSettings(RegionSettings rs)
|
||||||
|
{
|
||||||
|
m_regionSettings[rs.RegionUUID] = rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
|
||||||
|
{
|
||||||
|
//This connector doesn't support the windlight module yet
|
||||||
|
//Return default LL windlight settings
|
||||||
|
return new RegionLightShareData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StoreRegionWindlightSettings(RegionLightShareData wl)
|
||||||
|
{
|
||||||
|
//This connector doesn't support the windlight module yet
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionSettings LoadRegionSettings(UUID regionUUID)
|
||||||
|
{
|
||||||
|
RegionSettings rs = null;
|
||||||
|
m_regionSettings.TryGetValue(regionUUID, out rs);
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
|
||||||
|
{
|
||||||
|
// We can't simply store groups here because on delinking, OpenSim will not update the original group
|
||||||
|
// directly. Rather, the newly delinked parts will be updated to be in their own scene object group
|
||||||
|
// Therefore, we need to store parts rather than groups.
|
||||||
|
foreach (SceneObjectPart prim in obj.Children.Values)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[MOCK REGION DATA PLUGIN]: Storing part {0} {1} in object {2} {3} in region {4}",
|
||||||
|
prim.Name, prim.UUID, obj.Name, obj.UUID, regionUUID);
|
||||||
|
|
||||||
|
m_sceneObjectParts[prim.UUID] = prim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveObject(UUID obj, UUID regionUUID)
|
||||||
|
{
|
||||||
|
// All parts belonging to the object with the uuid are removed.
|
||||||
|
List<SceneObjectPart> parts = new List<SceneObjectPart>(m_sceneObjectParts.Values);
|
||||||
|
foreach (SceneObjectPart part in parts)
|
||||||
|
{
|
||||||
|
if (part.ParentGroup.UUID == obj)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[MOCK REGION DATA PLUGIN]: Removing part {0} {1} as part of object {2} from {3}",
|
||||||
|
part.Name, part.UUID, obj, regionUUID);
|
||||||
|
m_sceneObjectParts.Remove(part.UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see IRegionDatastore
|
||||||
|
public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
|
||||||
|
{
|
||||||
|
m_primItems[primID] = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
|
||||||
|
{
|
||||||
|
Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
|
||||||
|
|
||||||
|
// Create all of the SOGs from the root prims first
|
||||||
|
foreach (SceneObjectPart prim in m_sceneObjectParts.Values)
|
||||||
|
{
|
||||||
|
if (prim.IsRoot)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[MOCK REGION DATA PLUGIN]: Loading root part {0} {1} in {2}", prim.Name, prim.UUID, regionUUID);
|
||||||
|
objects[prim.UUID] = new SceneObjectGroup(prim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all of the children objects to the SOGs
|
||||||
|
foreach (SceneObjectPart prim in m_sceneObjectParts.Values)
|
||||||
|
{
|
||||||
|
SceneObjectGroup sog;
|
||||||
|
if (prim.UUID != prim.ParentUUID)
|
||||||
|
{
|
||||||
|
if (objects.TryGetValue(prim.ParentUUID, out sog))
|
||||||
|
{
|
||||||
|
int originalLinkNum = prim.LinkNum;
|
||||||
|
|
||||||
|
sog.AddPart(prim);
|
||||||
|
|
||||||
|
// SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum.
|
||||||
|
// We override that here
|
||||||
|
if (originalLinkNum != 0)
|
||||||
|
prim.LinkNum = originalLinkNum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[MOCK REGION DATA PLUGIN]: Database contains an orphan child prim {0} {1} in region {2} pointing to missing parent {3}. This prim will not be loaded.",
|
||||||
|
prim.Name, prim.UUID, regionUUID, prim.ParentUUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Load items. This is assymetric - we store items as a separate method but don't retrieve them that
|
||||||
|
// way!
|
||||||
|
|
||||||
|
return new List<SceneObjectGroup>(objects.Values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StoreTerrain(double[,] ter, UUID regionID)
|
||||||
|
{
|
||||||
|
m_terrains[regionID] = ter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[,] LoadTerrain(UUID regionID)
|
||||||
|
{
|
||||||
|
if (m_terrains.ContainsKey(regionID))
|
||||||
|
return m_terrains[regionID];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveLandObject(UUID globalID)
|
||||||
|
{
|
||||||
|
if (m_landData.ContainsKey(globalID))
|
||||||
|
m_landData.Remove(globalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StoreLandObject(ILandObject land)
|
||||||
|
{
|
||||||
|
m_landData[land.LandData.GlobalID] = land.LandData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LandData> LoadLandObjects(UUID regionUUID)
|
||||||
|
{
|
||||||
|
return new List<LandData>(m_landData.Values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ namespace OpenSim.Tests.Common.Mock
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TestInventoryDataPlugin : IInventoryDataPlugin
|
public class TestInventoryDataPlugin : IInventoryDataPlugin
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
/// <value>
|
/// <value>
|
||||||
/// Inventory folders
|
/// Inventory folders
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
|
@ -29,7 +29,6 @@ using System;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Communications;
|
using OpenSim.Framework.Communications;
|
||||||
|
|
||||||
using OpenSim.Framework.Servers;
|
using OpenSim.Framework.Servers;
|
||||||
using OpenSim.Region.Framework;
|
using OpenSim.Region.Framework;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
@ -48,6 +47,11 @@ namespace OpenSim.Tests.Common.Mock
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allow retrieval for test check purposes
|
||||||
|
/// </summary>
|
||||||
|
public StorageManager StorageManager { get { return m_storageManager; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Temporarily override session authentication for tests (namely teleport).
|
/// Temporarily override session authentication for tests (namely teleport).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -157,7 +157,7 @@ namespace OpenSim.Tests.Common.Setup
|
||||||
AgentCircuitManager acm = new AgentCircuitManager();
|
AgentCircuitManager acm = new AgentCircuitManager();
|
||||||
SceneCommunicationService scs = new SceneCommunicationService();
|
SceneCommunicationService scs = new SceneCommunicationService();
|
||||||
|
|
||||||
StorageManager sm = new StorageManager("OpenSim.Data.Null.dll", "", "");
|
StorageManager sm = new StorageManager("OpenSim.Tests.Common.dll", "", "");
|
||||||
IConfigSource configSource = new IniConfigSource();
|
IConfigSource configSource = new IniConfigSource();
|
||||||
|
|
||||||
TestScene testScene = new TestScene(
|
TestScene testScene = new TestScene(
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace OpenSim.Tests.Common
|
||||||
InventoryFolderBase objsFolder = scene.InventoryService.GetFolderForType(userId, AssetType.Object);
|
InventoryFolderBase objsFolder = scene.InventoryService.GetFolderForType(userId, AssetType.Object);
|
||||||
|
|
||||||
item.Folder = objsFolder.ID;
|
item.Folder = objsFolder.ID;
|
||||||
scene.AddInventoryItem(userId, item);
|
scene.AddInventoryItem(item);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue