Convert multiple lock()s which directly hinder script performance in linksets to ReaderWriterLockSlim.

avinationmerge
CasperW 2009-11-27 18:29:03 +01:00
parent 8bbb88ea4e
commit 9888f95068
3 changed files with 541 additions and 305 deletions

View File

@ -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

View File

@ -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.

View File

@ -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)
@ -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)
{