Convert multiple lock()s which directly hinder script performance in linksets to ReaderWriterLockSlim.
parent
8bbb88ea4e
commit
9888f95068
|
@ -98,6 +98,66 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
private bool m_hasGroupChanged = false;
|
||||
private long timeFirstChanged;
|
||||
private long timeLastChanged;
|
||||
private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
|
||||
|
||||
public void lockPartsForRead(bool locked)
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
if (m_partsLock.RecursiveReadCount > 0)
|
||||
{
|
||||
m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
|
||||
m_partsLock.ExitReadLock();
|
||||
}
|
||||
if (m_partsLock.RecursiveWriteCount > 0)
|
||||
{
|
||||
m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
|
||||
m_partsLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
while (!m_partsLock.TryEnterReadLock(60000))
|
||||
{
|
||||
m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
|
||||
if (m_partsLock.IsWriteLockHeld)
|
||||
{
|
||||
m_partsLock = new System.Threading.ReaderWriterLockSlim();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_partsLock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
public void lockPartsForWrite(bool locked)
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
if (m_partsLock.RecursiveReadCount > 0)
|
||||
{
|
||||
m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
|
||||
m_partsLock.ExitReadLock();
|
||||
}
|
||||
if (m_partsLock.RecursiveWriteCount > 0)
|
||||
{
|
||||
m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
|
||||
m_partsLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
while (!m_partsLock.TryEnterWriteLock(60000))
|
||||
{
|
||||
m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
|
||||
if (m_partsLock.IsWriteLockHeld)
|
||||
{
|
||||
m_partsLock = new System.Threading.ReaderWriterLockSlim();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_partsLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasGroupChanged
|
||||
{
|
||||
|
@ -243,13 +303,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
set
|
||||
{
|
||||
m_regionHandle = value;
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.RegionHandle = m_regionHandle;
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,13 +338,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
||||
}
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.GroupPosition = val;
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
//if (m_rootPart.PhysActor != null)
|
||||
//{
|
||||
|
@ -432,13 +498,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
public void SetFromItemID(UUID AssetId)
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.FromItemID = AssetId;
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
public UUID GetFromItemID()
|
||||
|
@ -505,10 +574,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
Vector3 maxScale = Vector3.Zero;
|
||||
Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
Vector3 partscale = part.Scale;
|
||||
Vector3 partoffset = part.OffsetPosition;
|
||||
|
||||
|
@ -519,8 +589,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
|
||||
maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
|
||||
maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
|
||||
finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
|
||||
finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
|
||||
|
@ -536,10 +609,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
EntityIntersection result = new EntityIntersection();
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
// Temporary commented to stop compiler warning
|
||||
//Vector3 partPosition =
|
||||
// new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
|
||||
|
@ -567,8 +641,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
result.distance = inter.distance;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -581,10 +657,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
|
||||
{
|
||||
float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
Vector3 worldPos = part.GetWorldPosition();
|
||||
Vector3 offset = worldPos - AbsolutePosition;
|
||||
Quaternion worldRot;
|
||||
|
@ -643,6 +720,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
|
||||
backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
|
||||
|
||||
|
||||
|
||||
//m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
|
||||
//m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
|
||||
//m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
|
||||
|
@ -814,6 +893,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
minZ = backBottomLeft.Z;
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
|
||||
|
||||
|
@ -842,17 +922,20 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
Dictionary<UUID,string> states = new Dictionary<UUID,string>();
|
||||
|
||||
// Capture script state while holding the lock
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
|
||||
foreach (UUID itemid in pstates.Keys)
|
||||
{
|
||||
states.Add(itemid, pstates[itemid]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
if (states.Count > 0)
|
||||
{
|
||||
|
@ -1014,13 +1097,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
public override void UpdateMovement()
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.UpdateMovement();
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
public ushort GetTimeDilation()
|
||||
|
@ -1064,7 +1150,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <param name="part"></param>
|
||||
public void AddPart(SceneObjectPart part)
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForWrite(true);
|
||||
{
|
||||
part.SetParent(this);
|
||||
m_parts.Add(part.UUID, part);
|
||||
|
@ -1074,6 +1160,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (part.LinkNum == 2 && RootPart != null)
|
||||
RootPart.LinkNum = 1;
|
||||
}
|
||||
lockPartsForWrite(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1081,28 +1168,33 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
private void UpdateParentIDs()
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
if (part.UUID != m_rootPart.UUID)
|
||||
{
|
||||
part.ParentID = m_rootPart.LocalId;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
public void RegenerateFullIDs()
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.UUID = UUID.Random();
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
// helper provided for parts.
|
||||
|
@ -1183,9 +1275,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
DetachFromBackup();
|
||||
|
||||
lock (m_parts)
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
lockPartsForRead(true);
|
||||
List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
|
||||
lockPartsForRead(false);
|
||||
|
||||
foreach (SceneObjectPart part in values)
|
||||
{
|
||||
// part.Inventory.RemoveScriptInstances();
|
||||
|
||||
|
@ -1204,8 +1298,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void AddScriptLPS(int count)
|
||||
|
@ -1230,17 +1326,20 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
scriptEvents aggregateScriptEvents=0;
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
if (part == null)
|
||||
continue;
|
||||
if (part != RootPart)
|
||||
part.ObjectFlags = objectflagupdate;
|
||||
aggregateScriptEvents |= part.AggregateScriptEvents;
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
|
||||
m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
|
||||
|
@ -1273,42 +1372,52 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <param name="m_physicalPrim"></param>
|
||||
public void ApplyPhysics(bool m_physicalPrim)
|
||||
{
|
||||
lock (m_parts)
|
||||
{
|
||||
lockPartsForRead(true);
|
||||
|
||||
if (m_parts.Count > 1)
|
||||
{
|
||||
List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
|
||||
lockPartsForRead(false);
|
||||
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
foreach (SceneObjectPart part in values)
|
||||
{
|
||||
|
||||
if (part.LocalId != m_rootPart.LocalId)
|
||||
{
|
||||
part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Hack to get the physics scene geometries in the right spot
|
||||
ResetChildPrimPhysicsPositions();
|
||||
}
|
||||
else
|
||||
{
|
||||
lockPartsForRead(false);
|
||||
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetOwnerId(UUID userId)
|
||||
{
|
||||
ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; });
|
||||
ForEachPart(delegate(SceneObjectPart part)
|
||||
{
|
||||
|
||||
part.OwnerID = userId;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void ForEachPart(Action<SceneObjectPart> whatToDo)
|
||||
{
|
||||
lock (m_parts)
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
lockPartsForRead(true);
|
||||
List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
|
||||
lockPartsForRead(false);
|
||||
foreach (SceneObjectPart part in values)
|
||||
{
|
||||
|
||||
whatToDo(part);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1407,14 +1516,17 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
if (part != RootPart)
|
||||
SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1509,10 +1621,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
List<SceneObjectPart> partList;
|
||||
|
||||
lock (m_parts)
|
||||
{
|
||||
lockPartsForRead(true);
|
||||
|
||||
partList = new List<SceneObjectPart>(m_parts.Values);
|
||||
}
|
||||
|
||||
lockPartsForRead(false);
|
||||
|
||||
partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
|
||||
{
|
||||
|
@ -1835,10 +1948,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
|
||||
newPart.SetParent(this);
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForWrite(true);
|
||||
{
|
||||
m_parts.Add(newPart.UUID, newPart);
|
||||
}
|
||||
lockPartsForWrite(false);
|
||||
|
||||
SetPartAsNonRoot(newPart);
|
||||
|
||||
|
@ -1901,7 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
//if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
|
||||
// return;
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
|
||||
|
||||
|
@ -1919,34 +2033,43 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.SendScheduledUpdates();
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
public void ScheduleFullUpdateToAvatar(ScenePresence presence)
|
||||
{
|
||||
RootPart.AddFullUpdateToAvatar(presence);
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
if (part != RootPart)
|
||||
part.AddFullUpdateToAvatar(presence);
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.AddTerseUpdateToAvatar(presence);
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1957,14 +2080,17 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
checkAtTargets();
|
||||
RootPart.ScheduleFullUpdate();
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
if (part != RootPart)
|
||||
part.ScheduleFullUpdate();
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1972,13 +2098,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public void ScheduleGroupForTerseUpdate()
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
part.ScheduleTerseUpdate();
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1991,14 +2120,17 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
RootPart.SendFullUpdateToAllClients();
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
||||
if (part != RootPart)
|
||||
part.SendFullUpdateToAllClients();
|
||||
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2030,13 +2162,14 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (IsDeleted)
|
||||
return;
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
part.SendTerseUpdateToAllClients();
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -2050,16 +2183,18 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <returns>null if no child part with that linknum or child part</returns>
|
||||
public SceneObjectPart GetLinkNumPart(int linknum)
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
if (part.LinkNum == linknum)
|
||||
{
|
||||
lockPartsForRead(false);
|
||||
return part;
|
||||
}
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -2087,17 +2222,19 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public SceneObjectPart GetChildPart(uint localID)
|
||||
{
|
||||
//m_log.DebugFormat("Entered looking for {0}", localID);
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
//m_log.DebugFormat("Found {0}", part.LocalId);
|
||||
if (part.LocalId == localID)
|
||||
{
|
||||
lockPartsForRead(false);
|
||||
return part;
|
||||
}
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -2127,17 +2264,19 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public bool HasChildPrim(uint localID)
|
||||
{
|
||||
//m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
//m_log.DebugFormat("Found {0}", part.LocalId);
|
||||
if (part.LocalId == localID)
|
||||
{
|
||||
lockPartsForRead(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2187,13 +2326,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (m_rootPart.LinkNum == 0)
|
||||
m_rootPart.LinkNum = 1;
|
||||
|
||||
lock (m_parts)
|
||||
{
|
||||
lockPartsForWrite(true);
|
||||
|
||||
m_parts.Add(linkPart.UUID, linkPart);
|
||||
|
||||
lockPartsForWrite(false);
|
||||
|
||||
// Insert in terms of link numbers, the new links
|
||||
// before the current ones (with the exception of
|
||||
// the root prim. Shuffle the old ones up
|
||||
lockPartsForRead(true);
|
||||
foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
|
||||
{
|
||||
if (kvp.Value.LinkNum != 1)
|
||||
|
@ -2202,6 +2344,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
kvp.Value.LinkNum += objectGroup.PrimCount;
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
linkPart.LinkNum = 2;
|
||||
|
||||
|
@ -2225,15 +2368,15 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
part.ClearUndoState();
|
||||
}
|
||||
}
|
||||
|
||||
m_scene.UnlinkSceneObject(objectGroup.UUID, true);
|
||||
objectGroup.m_isDeleted = true;
|
||||
|
||||
lock (objectGroup.m_parts)
|
||||
{
|
||||
objectGroup.lockPartsForWrite(true);
|
||||
|
||||
objectGroup.m_parts.Clear();
|
||||
}
|
||||
|
||||
objectGroup.lockPartsForWrite(false);
|
||||
|
||||
// Can't do this yet since backup still makes use of the root part without any synchronization
|
||||
// objectGroup.m_rootPart = null;
|
||||
|
@ -2292,11 +2435,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
Quaternion worldRot = linkPart.GetWorldRotation();
|
||||
|
||||
// Remove the part from this object
|
||||
lock (m_parts)
|
||||
lockPartsForWrite(true);
|
||||
{
|
||||
m_parts.Remove(linkPart.UUID);
|
||||
}
|
||||
|
||||
lockPartsForWrite(false);
|
||||
lockPartsForRead(true);
|
||||
if (m_parts.Count == 1 && RootPart != null) //Single prim is left
|
||||
RootPart.LinkNum = 0;
|
||||
else
|
||||
|
@ -2307,6 +2451,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
p.LinkNum--;
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
linkPart.ParentID = 0;
|
||||
linkPart.LinkNum = 0;
|
||||
|
@ -2624,9 +2769,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
if (selectionPart != null)
|
||||
{
|
||||
lock (m_parts)
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
lockPartsForRead(true);
|
||||
List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
|
||||
lockPartsForRead(false);
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
|
||||
{
|
||||
|
@ -2635,11 +2781,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2863,7 +3009,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
prevScale.Z *= z;
|
||||
part.Resize(prevScale);
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart obPart in m_parts.Values)
|
||||
{
|
||||
|
@ -2882,6 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
if (part.PhysActor != null)
|
||||
{
|
||||
|
@ -2962,7 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
axDiff *= Quaternion.Inverse(partRotation);
|
||||
diff = axDiff;
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart obPart in m_parts.Values)
|
||||
{
|
||||
|
@ -2972,6 +3119,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
AbsolutePosition = newPos;
|
||||
|
||||
|
@ -3089,7 +3237,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
|
||||
}
|
||||
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart prim in m_parts.Values)
|
||||
{
|
||||
|
@ -3107,6 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
m_rootPart.ScheduleTerseUpdate();
|
||||
}
|
||||
|
@ -3205,7 +3354,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (atTargets.Count > 0)
|
||||
{
|
||||
uint[] localids = new uint[0];
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
localids = new uint[m_parts.Count];
|
||||
int cntr = 0;
|
||||
|
@ -3215,6 +3364,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
cntr++;
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
for (int ctr = 0; ctr < localids.Length; ctr++)
|
||||
{
|
||||
|
@ -3233,7 +3383,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
//trigger not_at_target
|
||||
uint[] localids = new uint[0];
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
localids = new uint[m_parts.Count];
|
||||
int cntr = 0;
|
||||
|
@ -3243,6 +3393,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
cntr++;
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
|
||||
for (int ctr = 0; ctr < localids.Length; ctr++)
|
||||
{
|
||||
|
@ -3256,19 +3407,20 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public float GetMass()
|
||||
{
|
||||
float retmass = 0f;
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
retmass += part.GetMass();
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
return retmass;
|
||||
}
|
||||
|
||||
public void CheckSculptAndLoad()
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
if (!IsDeleted)
|
||||
{
|
||||
|
@ -3293,6 +3445,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
protected void AssetReceived(string id, Object sender, AssetBase asset)
|
||||
|
@ -3313,7 +3466,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <param name="client"></param>
|
||||
public void SetGroup(UUID GroupID, IClientAPI client)
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
{
|
||||
|
@ -3323,7 +3476,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
HasGroupChanged = true;
|
||||
}
|
||||
|
||||
lockPartsForRead(false);
|
||||
ScheduleGroupForFullUpdate();
|
||||
}
|
||||
|
||||
|
@ -3342,11 +3495,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
public void SetAttachmentPoint(byte point)
|
||||
{
|
||||
lock (m_parts)
|
||||
lockPartsForRead(true);
|
||||
{
|
||||
foreach (SceneObjectPart part in m_parts.Values)
|
||||
part.SetAttachmentPoint(point);
|
||||
}
|
||||
lockPartsForRead(false);
|
||||
}
|
||||
|
||||
#region ISceneObject
|
||||
|
|
|
@ -2950,8 +2950,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
return m_host.OwnerID.ToString();
|
||||
}
|
||||
|
||||
[DebuggerNonUserCode]
|
||||
public void llInstantMessage(string user, string message)
|
||||
{
|
||||
UUID result;
|
||||
if (!UUID.TryParse(user, out result))
|
||||
{
|
||||
throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
// We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
|
||||
|
|
|
@ -101,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
private Dictionary<UUID, IScriptInstance> m_Scripts =
|
||||
new Dictionary<UUID, IScriptInstance>();
|
||||
|
||||
private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
|
||||
|
||||
// Maps the asset ID to the assembly
|
||||
|
||||
private Dictionary<UUID, string> m_Assemblies =
|
||||
|
@ -122,6 +124,65 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
|
||||
IWorkItemResult m_CurrentCompile = null;
|
||||
|
||||
private void lockScriptsForRead(bool locked)
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
if (m_scriptsLock.RecursiveReadCount > 0)
|
||||
{
|
||||
m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
|
||||
m_scriptsLock.ExitReadLock();
|
||||
}
|
||||
if (m_scriptsLock.RecursiveWriteCount > 0)
|
||||
{
|
||||
m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
|
||||
m_scriptsLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
while (!m_scriptsLock.TryEnterReadLock(60000))
|
||||
{
|
||||
m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
|
||||
if (m_scriptsLock.IsWriteLockHeld)
|
||||
{
|
||||
m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scriptsLock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
private void lockScriptsForWrite(bool locked)
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
if (m_scriptsLock.RecursiveReadCount > 0)
|
||||
{
|
||||
m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
|
||||
m_scriptsLock.ExitReadLock();
|
||||
}
|
||||
if (m_scriptsLock.RecursiveWriteCount > 0)
|
||||
{
|
||||
m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
|
||||
m_scriptsLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
while (!m_scriptsLock.TryEnterWriteLock(60000))
|
||||
{
|
||||
m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
|
||||
if (m_scriptsLock.IsWriteLockHeld)
|
||||
{
|
||||
m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scriptsLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public string ScriptEngineName
|
||||
{
|
||||
get { return "XEngine"; }
|
||||
|
@ -261,8 +322,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
lock (m_Scripts)
|
||||
{
|
||||
lockScriptsForRead(true);
|
||||
foreach (IScriptInstance instance in m_Scripts.Values)
|
||||
{
|
||||
// Force a final state save
|
||||
|
@ -293,11 +353,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
UnloadAppDomain(instance.AppDomain);
|
||||
}
|
||||
}
|
||||
lockScriptsForRead(false);
|
||||
lockScriptsForWrite(true);
|
||||
m_Scripts.Clear();
|
||||
lockScriptsForWrite(false);
|
||||
m_PrimObjects.Clear();
|
||||
m_Assemblies.Clear();
|
||||
m_DomainScripts.Clear();
|
||||
}
|
||||
|
||||
lock (m_ScriptEngines)
|
||||
{
|
||||
m_ScriptEngines.Remove(this);
|
||||
|
@ -356,22 +419,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
List<IScriptInstance> instances = new List<IScriptInstance>();
|
||||
|
||||
lock (m_Scripts)
|
||||
{
|
||||
lockScriptsForRead(true);
|
||||
foreach (IScriptInstance instance in m_Scripts.Values)
|
||||
instances.Add(instance);
|
||||
}
|
||||
lockScriptsForRead(false);
|
||||
|
||||
foreach (IScriptInstance i in instances)
|
||||
{
|
||||
string assembly = String.Empty;
|
||||
|
||||
lock (m_Scripts)
|
||||
{
|
||||
|
||||
if (!m_Assemblies.ContainsKey(i.AssetID))
|
||||
continue;
|
||||
assembly = m_Assemblies[i.AssetID];
|
||||
}
|
||||
|
||||
|
||||
i.SaveState(assembly);
|
||||
}
|
||||
|
@ -673,14 +734,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
return false;
|
||||
}
|
||||
|
||||
lock (m_Scripts)
|
||||
{
|
||||
|
||||
|
||||
ScriptInstance instance = null;
|
||||
// Create the object record
|
||||
|
||||
lockScriptsForRead(true);
|
||||
if ((!m_Scripts.ContainsKey(itemID)) ||
|
||||
(m_Scripts[itemID].AssetID != assetID))
|
||||
{
|
||||
lockScriptsForRead(false);
|
||||
|
||||
UUID appDomain = assetID;
|
||||
|
||||
if (part.ParentGroup.IsAttachment)
|
||||
|
@ -691,9 +754,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
try
|
||||
{
|
||||
AppDomainSetup appSetup = new AppDomainSetup();
|
||||
// appSetup.ApplicationBase = Path.Combine(
|
||||
// "ScriptEngines",
|
||||
// m_Scene.RegionInfo.RegionID.ToString());
|
||||
// appSetup.ApplicationBase = Path.Combine(
|
||||
// "ScriptEngines",
|
||||
// m_Scene.RegionInfo.RegionID.ToString());
|
||||
|
||||
Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
|
||||
Evidence evidence = new Evidence(baseEvidence);
|
||||
|
@ -753,10 +816,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
instance.AppDomain = appDomain;
|
||||
instance.LineMap = linemap;
|
||||
|
||||
lockScriptsForWrite(true);
|
||||
m_Scripts[itemID] = instance;
|
||||
lockScriptsForWrite(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
lockScriptsForRead(false);
|
||||
}
|
||||
|
||||
lock (m_PrimObjects)
|
||||
{
|
||||
if (!m_PrimObjects.ContainsKey(localID))
|
||||
|
@ -777,21 +844,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
if (instance!=null)
|
||||
instance.Init();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnRemoveScript(uint localID, UUID itemID)
|
||||
{
|
||||
lock (m_Scripts)
|
||||
{
|
||||
lockScriptsForRead(true);
|
||||
// Do we even have it?
|
||||
if (!m_Scripts.ContainsKey(itemID))
|
||||
{
|
||||
lockScriptsForRead(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IScriptInstance instance=m_Scripts[itemID];
|
||||
lockScriptsForRead(false);
|
||||
lockScriptsForWrite(true);
|
||||
m_Scripts.Remove(itemID);
|
||||
|
||||
lockScriptsForWrite(false);
|
||||
instance.ClearQueue();
|
||||
instance.Stop(0);
|
||||
|
||||
|
@ -838,7 +910,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
handlerObjectRemoved(part.UUID);
|
||||
|
||||
CleanAssemblies();
|
||||
}
|
||||
|
||||
|
||||
ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
|
||||
if (handlerScriptRemoved != null)
|
||||
|
@ -1091,12 +1163,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
private IScriptInstance GetInstance(UUID itemID)
|
||||
{
|
||||
IScriptInstance instance;
|
||||
lock (m_Scripts)
|
||||
{
|
||||
lockScriptsForRead(true);
|
||||
if (!m_Scripts.ContainsKey(itemID))
|
||||
{
|
||||
lockScriptsForRead(false);
|
||||
return null;
|
||||
instance = m_Scripts[itemID];
|
||||
}
|
||||
instance = m_Scripts[itemID];
|
||||
lockScriptsForRead(false);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -1200,11 +1274,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
{
|
||||
List<IScriptInstance> instances = new List<IScriptInstance>();
|
||||
|
||||
lock (m_Scripts)
|
||||
{
|
||||
lockScriptsForRead(true);
|
||||
foreach (IScriptInstance instance in m_Scripts.Values)
|
||||
instances.Add(instance);
|
||||
}
|
||||
lockScriptsForRead(false);
|
||||
|
||||
foreach (IScriptInstance i in instances)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue