aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs534
1 files changed, 348 insertions, 186 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index c5a6171..2a4e5a2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -106,6 +106,72 @@ namespace OpenSim.Region.Framework.Scenes
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged;
108 private long timeLastChanged; 108 private long timeLastChanged;
109 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
110
111 public void lockPartsForRead(bool locked)
112 {
113 if (locked)
114 {
115 if (m_partsLock.RecursiveReadCount > 0)
116 {
117 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.");
118 m_partsLock.ExitReadLock();
119 }
120 if (m_partsLock.RecursiveWriteCount > 0)
121 {
122 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
123 m_partsLock.ExitWriteLock();
124 }
125
126 while (!m_partsLock.TryEnterReadLock(60000))
127 {
128 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.");
129 if (m_partsLock.IsWriteLockHeld)
130 {
131 m_partsLock = new System.Threading.ReaderWriterLockSlim();
132 }
133 }
134 }
135 else
136 {
137 if (m_partsLock.RecursiveReadCount > 0)
138 {
139 m_partsLock.ExitReadLock();
140 }
141 }
142 }
143 public void lockPartsForWrite(bool locked)
144 {
145 if (locked)
146 {
147 if (m_partsLock.RecursiveReadCount > 0)
148 {
149 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.");
150 m_partsLock.ExitReadLock();
151 }
152 if (m_partsLock.RecursiveWriteCount > 0)
153 {
154 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
155 m_partsLock.ExitWriteLock();
156 }
157
158 while (!m_partsLock.TryEnterWriteLock(60000))
159 {
160 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.");
161 if (m_partsLock.IsWriteLockHeld)
162 {
163 m_partsLock = new System.Threading.ReaderWriterLockSlim();
164 }
165 }
166 }
167 else
168 {
169 if (m_partsLock.RecursiveWriteCount > 0)
170 {
171 m_partsLock.ExitWriteLock();
172 }
173 }
174 }
109 175
110 public bool HasGroupChanged 176 public bool HasGroupChanged
111 { 177 {
@@ -258,13 +324,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 324 set
259 { 325 {
260 m_regionHandle = value; 326 m_regionHandle = value;
261 lock (m_parts) 327 lockPartsForRead(true);
262 { 328 {
263 foreach (SceneObjectPart part in m_parts.Values) 329 foreach (SceneObjectPart part in m_parts.Values)
264 { 330 {
331
265 part.RegionHandle = m_regionHandle; 332 part.RegionHandle = m_regionHandle;
333
266 } 334 }
267 } 335 }
336 lockPartsForRead(false);
268 } 337 }
269 } 338 }
270 339
@@ -298,6 +367,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 367 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 368 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 369 }
370
371 lockPartsForRead(true);
372
301 if (RootPart.GetStatusSandbox()) 373 if (RootPart.GetStatusSandbox())
302 { 374 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 375 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,16 +377,15 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 377 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 378 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 379 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
380 lockPartsForRead(false);
308 return; 381 return;
309 } 382 }
310 } 383 }
311 lock (m_parts) 384
312 { 385 foreach (SceneObjectPart part in m_parts.Values)
313 foreach (SceneObjectPart part in m_parts.Values) 386 part.GroupPosition = val;
314 { 387
315 part.GroupPosition = val; 388 lockPartsForRead(false);
316 }
317 }
318 389
319 //if (m_rootPart.PhysActor != null) 390 //if (m_rootPart.PhysActor != null)
320 //{ 391 //{
@@ -504,13 +575,16 @@ namespace OpenSim.Region.Framework.Scenes
504 575
505 public void SetFromItemID(UUID AssetId) 576 public void SetFromItemID(UUID AssetId)
506 { 577 {
507 lock (m_parts) 578 lockPartsForRead(true);
508 { 579 {
509 foreach (SceneObjectPart part in m_parts.Values) 580 foreach (SceneObjectPart part in m_parts.Values)
510 { 581 {
582
511 part.FromItemID = AssetId; 583 part.FromItemID = AssetId;
584
512 } 585 }
513 } 586 }
587 lockPartsForRead(false);
514 } 588 }
515 589
516 public UUID GetFromItemID() 590 public UUID GetFromItemID()
@@ -577,10 +651,11 @@ namespace OpenSim.Region.Framework.Scenes
577 Vector3 maxScale = Vector3.Zero; 651 Vector3 maxScale = Vector3.Zero;
578 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 652 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
579 653
580 lock (m_parts) 654 lockPartsForRead(true);
581 { 655 {
582 foreach (SceneObjectPart part in m_parts.Values) 656 foreach (SceneObjectPart part in m_parts.Values)
583 { 657 {
658
584 Vector3 partscale = part.Scale; 659 Vector3 partscale = part.Scale;
585 Vector3 partoffset = part.OffsetPosition; 660 Vector3 partoffset = part.OffsetPosition;
586 661
@@ -591,8 +666,11 @@ namespace OpenSim.Region.Framework.Scenes
591 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 666 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
592 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 667 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
593 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 668 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
669
594 } 670 }
595 } 671 }
672 lockPartsForRead(false);
673
596 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 674 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
597 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 675 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
598 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 676 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -608,10 +686,11 @@ namespace OpenSim.Region.Framework.Scenes
608 686
609 EntityIntersection result = new EntityIntersection(); 687 EntityIntersection result = new EntityIntersection();
610 688
611 lock (m_parts) 689 lockPartsForRead(true);
612 { 690 {
613 foreach (SceneObjectPart part in m_parts.Values) 691 foreach (SceneObjectPart part in m_parts.Values)
614 { 692 {
693
615 // Temporary commented to stop compiler warning 694 // Temporary commented to stop compiler warning
616 //Vector3 partPosition = 695 //Vector3 partPosition =
617 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 696 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -639,8 +718,10 @@ namespace OpenSim.Region.Framework.Scenes
639 result.distance = inter.distance; 718 result.distance = inter.distance;
640 } 719 }
641 } 720 }
721
642 } 722 }
643 } 723 }
724 lockPartsForRead(false);
644 return result; 725 return result;
645 } 726 }
646 727
@@ -653,10 +734,11 @@ namespace OpenSim.Region.Framework.Scenes
653 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 734 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
654 { 735 {
655 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 736 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
656 lock (m_parts) 737 lockPartsForRead(true);
657 { 738 {
658 foreach (SceneObjectPart part in m_parts.Values) 739 foreach (SceneObjectPart part in m_parts.Values)
659 { 740 {
741
660 Vector3 worldPos = part.GetWorldPosition(); 742 Vector3 worldPos = part.GetWorldPosition();
661 Vector3 offset = worldPos - AbsolutePosition; 743 Vector3 offset = worldPos - AbsolutePosition;
662 Quaternion worldRot; 744 Quaternion worldRot;
@@ -715,6 +797,8 @@ namespace OpenSim.Region.Framework.Scenes
715 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 797 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
716 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 798 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
717 799
800
801
718 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 802 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
719 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 803 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
720 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 804 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -886,6 +970,7 @@ namespace OpenSim.Region.Framework.Scenes
886 minZ = backBottomLeft.Z; 970 minZ = backBottomLeft.Z;
887 } 971 }
888 } 972 }
973 lockPartsForRead(false);
889 974
890 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 975 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
891 976
@@ -914,17 +999,20 @@ namespace OpenSim.Region.Framework.Scenes
914 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 999 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
915 1000
916 // Capture script state while holding the lock 1001 // Capture script state while holding the lock
917 lock (m_parts) 1002 lockPartsForRead(true);
918 { 1003 {
919 foreach (SceneObjectPart part in m_parts.Values) 1004 foreach (SceneObjectPart part in m_parts.Values)
920 { 1005 {
1006
921 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1007 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
922 foreach (UUID itemid in pstates.Keys) 1008 foreach (UUID itemid in pstates.Keys)
923 { 1009 {
924 states.Add(itemid, pstates[itemid]); 1010 states.Add(itemid, pstates[itemid]);
925 } 1011 }
1012
926 } 1013 }
927 } 1014 }
1015 lockPartsForRead(false);
928 1016
929 if (states.Count > 0) 1017 if (states.Count > 0)
930 { 1018 {
@@ -1086,13 +1174,16 @@ namespace OpenSim.Region.Framework.Scenes
1086 1174
1087 public override void UpdateMovement() 1175 public override void UpdateMovement()
1088 { 1176 {
1089 lock (m_parts) 1177 lockPartsForRead(true);
1090 { 1178 {
1091 foreach (SceneObjectPart part in m_parts.Values) 1179 foreach (SceneObjectPart part in m_parts.Values)
1092 { 1180 {
1181
1093 part.UpdateMovement(); 1182 part.UpdateMovement();
1183
1094 } 1184 }
1095 } 1185 }
1186 lockPartsForRead(false);
1096 } 1187 }
1097 1188
1098 public ushort GetTimeDilation() 1189 public ushort GetTimeDilation()
@@ -1136,7 +1227,7 @@ namespace OpenSim.Region.Framework.Scenes
1136 /// <param name="part"></param> 1227 /// <param name="part"></param>
1137 public void AddPart(SceneObjectPart part) 1228 public void AddPart(SceneObjectPart part)
1138 { 1229 {
1139 lock (m_parts) 1230 lockPartsForWrite(true);
1140 { 1231 {
1141 part.SetParent(this); 1232 part.SetParent(this);
1142 m_parts.Add(part.UUID, part); 1233 m_parts.Add(part.UUID, part);
@@ -1146,6 +1237,7 @@ namespace OpenSim.Region.Framework.Scenes
1146 if (part.LinkNum == 2 && RootPart != null) 1237 if (part.LinkNum == 2 && RootPart != null)
1147 RootPart.LinkNum = 1; 1238 RootPart.LinkNum = 1;
1148 } 1239 }
1240 lockPartsForWrite(false);
1149 } 1241 }
1150 1242
1151 /// <summary> 1243 /// <summary>
@@ -1153,28 +1245,33 @@ namespace OpenSim.Region.Framework.Scenes
1153 /// </summary> 1245 /// </summary>
1154 private void UpdateParentIDs() 1246 private void UpdateParentIDs()
1155 { 1247 {
1156 lock (m_parts) 1248 lockPartsForRead(true);
1157 { 1249 {
1158 foreach (SceneObjectPart part in m_parts.Values) 1250 foreach (SceneObjectPart part in m_parts.Values)
1159 { 1251 {
1252
1160 if (part.UUID != m_rootPart.UUID) 1253 if (part.UUID != m_rootPart.UUID)
1161 { 1254 {
1162 part.ParentID = m_rootPart.LocalId; 1255 part.ParentID = m_rootPart.LocalId;
1163 } 1256 }
1257
1164 } 1258 }
1165 } 1259 }
1260 lockPartsForRead(false);
1166 } 1261 }
1167 1262
1168 public void RegenerateFullIDs() 1263 public void RegenerateFullIDs()
1169 { 1264 {
1170 lock (m_parts) 1265 lockPartsForRead(true);
1171 { 1266 {
1172 foreach (SceneObjectPart part in m_parts.Values) 1267 foreach (SceneObjectPart part in m_parts.Values)
1173 { 1268 {
1269
1174 part.UUID = UUID.Random(); 1270 part.UUID = UUID.Random();
1175 1271
1176 } 1272 }
1177 } 1273 }
1274 lockPartsForRead(false);
1178 } 1275 }
1179 1276
1180 // helper provided for parts. 1277 // helper provided for parts.
@@ -1255,29 +1352,33 @@ namespace OpenSim.Region.Framework.Scenes
1255 1352
1256 DetachFromBackup(); 1353 DetachFromBackup();
1257 1354
1258 lock (m_parts) 1355 lockPartsForRead(true);
1356 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1357 lockPartsForRead(false);
1358
1359 foreach (SceneObjectPart part in values)
1259 { 1360 {
1260 foreach (SceneObjectPart part in m_parts.Values)
1261 {
1262// part.Inventory.RemoveScriptInstances(); 1361// part.Inventory.RemoveScriptInstances();
1263 1362
1264 ScenePresence[] avatars = Scene.GetScenePresences(); 1363 ScenePresence[] avatars = Scene.GetScenePresences();
1265 for (int i = 0; i < avatars.Length; i++) 1364 for (int i = 0; i < avatars.Length; i++)
1365 {
1366 if (avatars[i].ParentID == LocalId)
1266 { 1367 {
1267 if (avatars[i].ParentID == LocalId) 1368 avatars[i].StandUp();
1268 { 1369 }
1269 avatars[i].StandUp();
1270 }
1271 1370
1272 if (!silent) 1371 if (!silent)
1273 { 1372 {
1274 part.UpdateFlag = 0; 1373 part.UpdateFlag = 0;
1275 if (part == m_rootPart) 1374 if (part == m_rootPart)
1276 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1375 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1277 }
1278 } 1376 }
1279 } 1377 }
1378
1280 } 1379 }
1380
1381
1281 } 1382 }
1282 1383
1283 public void AddScriptLPS(int count) 1384 public void AddScriptLPS(int count)
@@ -1302,17 +1403,20 @@ namespace OpenSim.Region.Framework.Scenes
1302 1403
1303 scriptEvents aggregateScriptEvents=0; 1404 scriptEvents aggregateScriptEvents=0;
1304 1405
1305 lock (m_parts) 1406 lockPartsForRead(true);
1306 { 1407 {
1307 foreach (SceneObjectPart part in m_parts.Values) 1408 foreach (SceneObjectPart part in m_parts.Values)
1308 { 1409 {
1410
1309 if (part == null) 1411 if (part == null)
1310 continue; 1412 continue;
1311 if (part != RootPart) 1413 if (part != RootPart)
1312 part.ObjectFlags = objectflagupdate; 1414 part.ObjectFlags = objectflagupdate;
1313 aggregateScriptEvents |= part.AggregateScriptEvents; 1415 aggregateScriptEvents |= part.AggregateScriptEvents;
1416
1314 } 1417 }
1315 } 1418 }
1419 lockPartsForRead(false);
1316 1420
1317 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1421 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1318 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1422 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1354,42 +1458,52 @@ namespace OpenSim.Region.Framework.Scenes
1354 /// <param name="m_physicalPrim"></param> 1458 /// <param name="m_physicalPrim"></param>
1355 public void ApplyPhysics(bool m_physicalPrim) 1459 public void ApplyPhysics(bool m_physicalPrim)
1356 { 1460 {
1357 lock (m_parts) 1461 lockPartsForRead(true);
1462
1463 if (m_parts.Count > 1)
1358 { 1464 {
1359 if (m_parts.Count > 1) 1465 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1466 lockPartsForRead(false);
1467 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1468 foreach (SceneObjectPart part in values)
1360 { 1469 {
1361 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1470
1362 foreach (SceneObjectPart part in m_parts.Values) 1471 if (part.LocalId != m_rootPart.LocalId)
1363 { 1472 {
1364 if (part.LocalId != m_rootPart.LocalId) 1473 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1365 {
1366 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1367 }
1368 } 1474 }
1369 1475
1370 // Hack to get the physics scene geometries in the right spot
1371 ResetChildPrimPhysicsPositions();
1372 }
1373 else
1374 {
1375 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1376 } 1476 }
1477 // Hack to get the physics scene geometries in the right spot
1478 ResetChildPrimPhysicsPositions();
1479 }
1480 else
1481 {
1482 lockPartsForRead(false);
1483 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1377 } 1484 }
1378 } 1485 }
1379 1486
1380 public void SetOwnerId(UUID userId) 1487 public void SetOwnerId(UUID userId)
1381 { 1488 {
1382 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1489 ForEachPart(delegate(SceneObjectPart part)
1490 {
1491
1492 part.OwnerID = userId;
1493
1494 });
1383 } 1495 }
1384 1496
1385 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1497 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1386 { 1498 {
1387 lock (m_parts) 1499 lockPartsForRead(true);
1500 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1501 lockPartsForRead(false);
1502 foreach (SceneObjectPart part in values)
1388 { 1503 {
1389 foreach (SceneObjectPart part in m_parts.Values) 1504
1390 { 1505 whatToDo(part);
1391 whatToDo(part); 1506
1392 }
1393 } 1507 }
1394 } 1508 }
1395 1509
@@ -1488,14 +1602,17 @@ namespace OpenSim.Region.Framework.Scenes
1488 { 1602 {
1489 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1603 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1490 1604
1491 lock (m_parts) 1605 lockPartsForRead(true);
1492 { 1606 {
1493 foreach (SceneObjectPart part in m_parts.Values) 1607 foreach (SceneObjectPart part in m_parts.Values)
1494 { 1608 {
1609
1495 if (part != RootPart) 1610 if (part != RootPart)
1496 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1611 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1612
1497 } 1613 }
1498 } 1614 }
1615 lockPartsForRead(false);
1499 } 1616 }
1500 1617
1501 /// <summary> 1618 /// <summary>
@@ -1593,10 +1710,11 @@ namespace OpenSim.Region.Framework.Scenes
1593 1710
1594 List<SceneObjectPart> partList; 1711 List<SceneObjectPart> partList;
1595 1712
1596 lock (m_parts) 1713 lockPartsForRead(true);
1597 { 1714
1598 partList = new List<SceneObjectPart>(m_parts.Values); 1715 partList = new List<SceneObjectPart>(m_parts.Values);
1599 } 1716
1717 lockPartsForRead(false);
1600 1718
1601 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1719 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1602 { 1720 {
@@ -1893,10 +2011,11 @@ namespace OpenSim.Region.Framework.Scenes
1893 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2011 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1894 newPart.SetParent(this); 2012 newPart.SetParent(this);
1895 2013
1896 lock (m_parts) 2014 lockPartsForWrite(true);
1897 { 2015 {
1898 m_parts.Add(newPart.UUID, newPart); 2016 m_parts.Add(newPart.UUID, newPart);
1899 } 2017 }
2018 lockPartsForWrite(false);
1900 2019
1901 SetPartAsNonRoot(newPart); 2020 SetPartAsNonRoot(newPart);
1902 2021
@@ -1959,7 +2078,7 @@ namespace OpenSim.Region.Framework.Scenes
1959 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2078 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1960 // return; 2079 // return;
1961 2080
1962 lock (m_parts) 2081 lockPartsForRead(true);
1963 { 2082 {
1964 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2083 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1965 2084
@@ -1979,34 +2098,43 @@ namespace OpenSim.Region.Framework.Scenes
1979 { 2098 {
1980 if (!IsSelected) 2099 if (!IsSelected)
1981 part.UpdateLookAt(); 2100 part.UpdateLookAt();
2101
1982 part.SendScheduledUpdates(); 2102 part.SendScheduledUpdates();
2103
1983 } 2104 }
1984 } 2105 }
2106 lockPartsForRead(false);
1985 } 2107 }
1986 2108
1987 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2109 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1988 { 2110 {
1989 RootPart.AddFullUpdateToAvatar(presence); 2111 RootPart.AddFullUpdateToAvatar(presence);
1990 2112
1991 lock (m_parts) 2113 lockPartsForRead(true);
1992 { 2114 {
1993 foreach (SceneObjectPart part in m_parts.Values) 2115 foreach (SceneObjectPart part in m_parts.Values)
1994 { 2116 {
2117
1995 if (part != RootPart) 2118 if (part != RootPart)
1996 part.AddFullUpdateToAvatar(presence); 2119 part.AddFullUpdateToAvatar(presence);
2120
1997 } 2121 }
1998 } 2122 }
2123 lockPartsForRead(false);
1999 } 2124 }
2000 2125
2001 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2126 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
2002 { 2127 {
2003 lock (m_parts) 2128 lockPartsForRead(true);
2004 { 2129 {
2005 foreach (SceneObjectPart part in m_parts.Values) 2130 foreach (SceneObjectPart part in m_parts.Values)
2006 { 2131 {
2132
2007 part.AddTerseUpdateToAvatar(presence); 2133 part.AddTerseUpdateToAvatar(presence);
2134
2008 } 2135 }
2009 } 2136 }
2137 lockPartsForRead(false);
2010 } 2138 }
2011 2139
2012 /// <summary> 2140 /// <summary>
@@ -2017,14 +2145,17 @@ namespace OpenSim.Region.Framework.Scenes
2017 checkAtTargets(); 2145 checkAtTargets();
2018 RootPart.ScheduleFullUpdate(); 2146 RootPart.ScheduleFullUpdate();
2019 2147
2020 lock (m_parts) 2148 lockPartsForRead(true);
2021 { 2149 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2150 foreach (SceneObjectPart part in m_parts.Values)
2023 { 2151 {
2152
2024 if (part != RootPart) 2153 if (part != RootPart)
2025 part.ScheduleFullUpdate(); 2154 part.ScheduleFullUpdate();
2155
2026 } 2156 }
2027 } 2157 }
2158 lockPartsForRead(false);
2028 } 2159 }
2029 2160
2030 /// <summary> 2161 /// <summary>
@@ -2032,13 +2163,16 @@ namespace OpenSim.Region.Framework.Scenes
2032 /// </summary> 2163 /// </summary>
2033 public void ScheduleGroupForTerseUpdate() 2164 public void ScheduleGroupForTerseUpdate()
2034 { 2165 {
2035 lock (m_parts) 2166 lockPartsForRead(true);
2036 { 2167 {
2037 foreach (SceneObjectPart part in m_parts.Values) 2168 foreach (SceneObjectPart part in m_parts.Values)
2038 { 2169 {
2170
2039 part.ScheduleTerseUpdate(); 2171 part.ScheduleTerseUpdate();
2172
2040 } 2173 }
2041 } 2174 }
2175 lockPartsForRead(false);
2042 } 2176 }
2043 2177
2044 /// <summary> 2178 /// <summary>
@@ -2051,14 +2185,17 @@ namespace OpenSim.Region.Framework.Scenes
2051 2185
2052 RootPart.SendFullUpdateToAllClients(); 2186 RootPart.SendFullUpdateToAllClients();
2053 2187
2054 lock (m_parts) 2188 lockPartsForRead(true);
2055 { 2189 {
2056 foreach (SceneObjectPart part in m_parts.Values) 2190 foreach (SceneObjectPart part in m_parts.Values)
2057 { 2191 {
2192
2058 if (part != RootPart) 2193 if (part != RootPart)
2059 part.SendFullUpdateToAllClients(); 2194 part.SendFullUpdateToAllClients();
2195
2060 } 2196 }
2061 } 2197 }
2198 lockPartsForRead(false);
2062 } 2199 }
2063 2200
2064 /// <summary> 2201 /// <summary>
@@ -2089,14 +2226,15 @@ namespace OpenSim.Region.Framework.Scenes
2089 { 2226 {
2090 if (IsDeleted) 2227 if (IsDeleted)
2091 return; 2228 return;
2092 2229
2093 lock (m_parts) 2230 lockPartsForRead(true);
2094 { 2231 {
2095 foreach (SceneObjectPart part in m_parts.Values) 2232 foreach (SceneObjectPart part in m_parts.Values)
2096 { 2233 {
2097 part.SendTerseUpdateToAllClients(); 2234 part.SendTerseUpdateToAllClients();
2098 } 2235 }
2099 } 2236 }
2237 lockPartsForRead(false);
2100 } 2238 }
2101 2239
2102 #endregion 2240 #endregion
@@ -2110,16 +2248,18 @@ namespace OpenSim.Region.Framework.Scenes
2110 /// <returns>null if no child part with that linknum or child part</returns> 2248 /// <returns>null if no child part with that linknum or child part</returns>
2111 public SceneObjectPart GetLinkNumPart(int linknum) 2249 public SceneObjectPart GetLinkNumPart(int linknum)
2112 { 2250 {
2113 lock (m_parts) 2251 lockPartsForRead(true);
2114 { 2252 {
2115 foreach (SceneObjectPart part in m_parts.Values) 2253 foreach (SceneObjectPart part in m_parts.Values)
2116 { 2254 {
2117 if (part.LinkNum == linknum) 2255 if (part.LinkNum == linknum)
2118 { 2256 {
2257 lockPartsForRead(false);
2119 return part; 2258 return part;
2120 } 2259 }
2121 } 2260 }
2122 } 2261 }
2262 lockPartsForRead(false);
2123 2263
2124 return null; 2264 return null;
2125 } 2265 }
@@ -2147,17 +2287,19 @@ namespace OpenSim.Region.Framework.Scenes
2147 public SceneObjectPart GetChildPart(uint localID) 2287 public SceneObjectPart GetChildPart(uint localID)
2148 { 2288 {
2149 //m_log.DebugFormat("Entered looking for {0}", localID); 2289 //m_log.DebugFormat("Entered looking for {0}", localID);
2150 lock (m_parts) 2290 lockPartsForRead(true);
2151 { 2291 {
2152 foreach (SceneObjectPart part in m_parts.Values) 2292 foreach (SceneObjectPart part in m_parts.Values)
2153 { 2293 {
2154 //m_log.DebugFormat("Found {0}", part.LocalId); 2294 //m_log.DebugFormat("Found {0}", part.LocalId);
2155 if (part.LocalId == localID) 2295 if (part.LocalId == localID)
2156 { 2296 {
2297 lockPartsForRead(false);
2157 return part; 2298 return part;
2158 } 2299 }
2159 } 2300 }
2160 } 2301 }
2302 lockPartsForRead(false);
2161 2303
2162 return null; 2304 return null;
2163 } 2305 }
@@ -2187,17 +2329,19 @@ namespace OpenSim.Region.Framework.Scenes
2187 public bool HasChildPrim(uint localID) 2329 public bool HasChildPrim(uint localID)
2188 { 2330 {
2189 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2331 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2190 lock (m_parts) 2332 lockPartsForRead(true);
2191 { 2333 {
2192 foreach (SceneObjectPart part in m_parts.Values) 2334 foreach (SceneObjectPart part in m_parts.Values)
2193 { 2335 {
2194 //m_log.DebugFormat("Found {0}", part.LocalId); 2336 //m_log.DebugFormat("Found {0}", part.LocalId);
2195 if (part.LocalId == localID) 2337 if (part.LocalId == localID)
2196 { 2338 {
2339 lockPartsForRead(false);
2197 return true; 2340 return true;
2198 } 2341 }
2199 } 2342 }
2200 } 2343 }
2344 lockPartsForRead(false);
2201 2345
2202 return false; 2346 return false;
2203 } 2347 }
@@ -2247,53 +2391,57 @@ namespace OpenSim.Region.Framework.Scenes
2247 if (m_rootPart.LinkNum == 0) 2391 if (m_rootPart.LinkNum == 0)
2248 m_rootPart.LinkNum = 1; 2392 m_rootPart.LinkNum = 1;
2249 2393
2250 lock (m_parts) 2394 lockPartsForWrite(true);
2251 { 2395
2252 m_parts.Add(linkPart.UUID, linkPart); 2396 m_parts.Add(linkPart.UUID, linkPart);
2397
2398 lockPartsForWrite(false);
2253 2399
2254 // Insert in terms of link numbers, the new links 2400 // Insert in terms of link numbers, the new links
2255 // before the current ones (with the exception of 2401 // before the current ones (with the exception of
2256 // the root prim. Shuffle the old ones up 2402 // the root prim. Shuffle the old ones up
2257 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2403 lockPartsForRead(true);
2404 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2405 {
2406 if (kvp.Value.LinkNum != 1)
2258 { 2407 {
2259 if (kvp.Value.LinkNum != 1) 2408 // Don't update root prim link number
2260 { 2409 kvp.Value.LinkNum += objectGroup.PrimCount;
2261 // Don't update root prim link number
2262 kvp.Value.LinkNum += objectGroup.PrimCount;
2263 }
2264 } 2410 }
2411 }
2412 lockPartsForRead(false);
2265 2413
2266 linkPart.LinkNum = 2; 2414 linkPart.LinkNum = 2;
2267 2415
2268 linkPart.SetParent(this); 2416 linkPart.SetParent(this);
2269 linkPart.AddFlag(PrimFlags.CreateSelected); 2417 linkPart.AddFlag(PrimFlags.CreateSelected);
2270 2418
2271 //if (linkPart.PhysActor != null) 2419 //if (linkPart.PhysActor != null)
2272 //{ 2420 //{
2273 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2421 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2274 2422
2275 //linkPart.PhysActor = null; 2423 //linkPart.PhysActor = null;
2276 //} 2424 //}
2277 2425
2278 //TODO: rest of parts 2426 //TODO: rest of parts
2279 int linkNum = 3; 2427 int linkNum = 3;
2280 foreach (SceneObjectPart part in objectGroup.Children.Values) 2428 foreach (SceneObjectPart part in objectGroup.Children.Values)
2429 {
2430 if (part.UUID != objectGroup.m_rootPart.UUID)
2281 { 2431 {
2282 if (part.UUID != objectGroup.m_rootPart.UUID) 2432 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2283 {
2284 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2285 }
2286 part.ClearUndoState();
2287 } 2433 }
2434 part.ClearUndoState();
2288 } 2435 }
2289 2436
2290 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2437 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2291 objectGroup.m_isDeleted = true; 2438 objectGroup.m_isDeleted = true;
2439
2440 objectGroup.lockPartsForWrite(true);
2292 2441
2293 lock (objectGroup.m_parts) 2442 objectGroup.m_parts.Clear();
2294 { 2443
2295 objectGroup.m_parts.Clear(); 2444 objectGroup.lockPartsForWrite(false);
2296 }
2297 2445
2298 // Can't do this yet since backup still makes use of the root part without any synchronization 2446 // Can't do this yet since backup still makes use of the root part without any synchronization
2299// objectGroup.m_rootPart = null; 2447// objectGroup.m_rootPart = null;
@@ -2363,11 +2511,12 @@ namespace OpenSim.Region.Framework.Scenes
2363 Quaternion worldRot = linkPart.GetWorldRotation(); 2511 Quaternion worldRot = linkPart.GetWorldRotation();
2364 2512
2365 // Remove the part from this object 2513 // Remove the part from this object
2366 lock (m_parts) 2514 lockPartsForWrite(true);
2367 { 2515 {
2368 m_parts.Remove(linkPart.UUID); 2516 m_parts.Remove(linkPart.UUID);
2369 } 2517 }
2370 2518 lockPartsForWrite(false);
2519 lockPartsForRead(true);
2371 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2520 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2372 RootPart.LinkNum = 0; 2521 RootPart.LinkNum = 0;
2373 else 2522 else
@@ -2378,6 +2527,7 @@ namespace OpenSim.Region.Framework.Scenes
2378 p.LinkNum--; 2527 p.LinkNum--;
2379 } 2528 }
2380 } 2529 }
2530 lockPartsForRead(false);
2381 2531
2382 linkPart.ParentID = 0; 2532 linkPart.ParentID = 0;
2383 linkPart.LinkNum = 0; 2533 linkPart.LinkNum = 0;
@@ -2699,9 +2849,12 @@ namespace OpenSim.Region.Framework.Scenes
2699 2849
2700 if (selectionPart != null) 2850 if (selectionPart != null)
2701 { 2851 {
2702 lock (m_parts) 2852 lockPartsForRead(true);
2853 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2854 lockPartsForRead(false);
2855 foreach (SceneObjectPart part in parts)
2703 { 2856 {
2704 foreach (SceneObjectPart part in m_parts.Values) 2857 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2705 { 2858 {
2706 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2859 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2707 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2860 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2711,12 +2864,13 @@ namespace OpenSim.Region.Framework.Scenes
2711 break; 2864 break;
2712 } 2865 }
2713 } 2866 }
2867 }
2714 2868
2715 foreach (SceneObjectPart part in m_parts.Values) 2869 foreach (SceneObjectPart part in parts)
2716 { 2870 {
2717 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2871 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2718 }
2719 } 2872 }
2873
2720 } 2874 }
2721 } 2875 }
2722 2876
@@ -2802,11 +2956,9 @@ namespace OpenSim.Region.Framework.Scenes
2802 scale.Y = m_scene.m_maxNonphys; 2956 scale.Y = m_scene.m_maxNonphys;
2803 if (scale.Z > m_scene.m_maxNonphys) 2957 if (scale.Z > m_scene.m_maxNonphys)
2804 scale.Z = m_scene.m_maxNonphys; 2958 scale.Z = m_scene.m_maxNonphys;
2805
2806 SceneObjectPart part = GetChildPart(localID); 2959 SceneObjectPart part = GetChildPart(localID);
2807 if (part != null) 2960 if (part != null)
2808 { 2961 {
2809 part.Resize(scale);
2810 if (part.PhysActor != null) 2962 if (part.PhysActor != null)
2811 { 2963 {
2812 if (part.PhysActor.IsPhysical) 2964 if (part.PhysActor.IsPhysical)
@@ -2821,7 +2973,7 @@ namespace OpenSim.Region.Framework.Scenes
2821 part.PhysActor.Size = scale; 2973 part.PhysActor.Size = scale;
2822 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2974 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2823 } 2975 }
2824 //if (part.UUID != m_rootPart.UUID) 2976 part.Resize(scale);
2825 2977
2826 HasGroupChanged = true; 2978 HasGroupChanged = true;
2827 ScheduleGroupForFullUpdate(); 2979 ScheduleGroupForFullUpdate();
@@ -2863,73 +3015,71 @@ namespace OpenSim.Region.Framework.Scenes
2863 float y = (scale.Y / part.Scale.Y); 3015 float y = (scale.Y / part.Scale.Y);
2864 float z = (scale.Z / part.Scale.Z); 3016 float z = (scale.Z / part.Scale.Z);
2865 3017
2866 lock (m_parts) 3018 lockPartsForRead(true);
3019 if (x > 1.0f || y > 1.0f || z > 1.0f)
2867 { 3020 {
2868 if (x > 1.0f || y > 1.0f || z > 1.0f) 3021 foreach (SceneObjectPart obPart in m_parts.Values)
2869 { 3022 {
2870 foreach (SceneObjectPart obPart in m_parts.Values) 3023 if (obPart.UUID != m_rootPart.UUID)
2871 { 3024 {
2872 if (obPart.UUID != m_rootPart.UUID) 3025 Vector3 oldSize = new Vector3(obPart.Scale);
2873 { 3026 obPart.IgnoreUndoUpdate = true;
2874 obPart.IgnoreUndoUpdate = true;
2875 Vector3 oldSize = new Vector3(obPart.Scale);
2876 3027
2877 float f = 1.0f; 3028 float f = 1.0f;
2878 float a = 1.0f; 3029 float a = 1.0f;
2879 3030
2880 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3031 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3032 {
3033 if (oldSize.X*x > m_scene.m_maxPhys)
2881 { 3034 {
2882 if (oldSize.X*x > m_scene.m_maxPhys) 3035 f = m_scene.m_maxPhys / oldSize.X;
2883 { 3036 a = f / x;
2884 f = m_scene.m_maxPhys / oldSize.X; 3037 x *= a;
2885 a = f / x; 3038 y *= a;
2886 x *= a; 3039 z *= a;
2887 y *= a;
2888 z *= a;
2889 }
2890 if (oldSize.Y*y > m_scene.m_maxPhys)
2891 {
2892 f = m_scene.m_maxPhys / oldSize.Y;
2893 a = f / y;
2894 x *= a;
2895 y *= a;
2896 z *= a;
2897 }
2898 if (oldSize.Z*z > m_scene.m_maxPhys)
2899 {
2900 f = m_scene.m_maxPhys / oldSize.Z;
2901 a = f / z;
2902 x *= a;
2903 y *= a;
2904 z *= a;
2905 }
2906 } 3040 }
2907 else 3041 if (oldSize.Y*y > m_scene.m_maxPhys)
3042 {
3043 f = m_scene.m_maxPhys / oldSize.Y;
3044 a = f / y;
3045 x *= a;
3046 y *= a;
3047 z *= a;
3048 }
3049 if (oldSize.Z*z > m_scene.m_maxPhys)
3050 {
3051 f = m_scene.m_maxPhys / oldSize.Z;
3052 a = f / z;
3053 x *= a;
3054 y *= a;
3055 z *= a;
3056 }
3057 }
3058 else
3059 {
3060 if (oldSize.X*x > m_scene.m_maxNonphys)
3061 {
3062 f = m_scene.m_maxNonphys / oldSize.X;
3063 a = f / x;
3064 x *= a;
3065 y *= a;
3066 z *= a;
3067 }
3068 if (oldSize.Y*y > m_scene.m_maxNonphys)
3069 {
3070 f = m_scene.m_maxNonphys / oldSize.Y;
3071 a = f / y;
3072 x *= a;
3073 y *= a;
3074 z *= a;
3075 }
3076 if (oldSize.Z*z > m_scene.m_maxNonphys)
2908 { 3077 {
2909 if (oldSize.X*x > m_scene.m_maxNonphys) 3078 f = m_scene.m_maxNonphys / oldSize.Z;
2910 { 3079 a = f / z;
2911 f = m_scene.m_maxNonphys / oldSize.X; 3080 x *= a;
2912 a = f / x; 3081 y *= a;
2913 x *= a; 3082 z *= a;
2914 y *= a;
2915 z *= a;
2916 }
2917 if (oldSize.Y*y > m_scene.m_maxNonphys)
2918 {
2919 f = m_scene.m_maxNonphys / oldSize.Y;
2920 a = f / y;
2921 x *= a;
2922 y *= a;
2923 z *= a;
2924 }
2925 if (oldSize.Z*z > m_scene.m_maxNonphys)
2926 {
2927 f = m_scene.m_maxNonphys / oldSize.Z;
2928 a = f / z;
2929 x *= a;
2930 y *= a;
2931 z *= a;
2932 }
2933 } 3083 }
2934 obPart.IgnoreUndoUpdate = false; 3084 obPart.IgnoreUndoUpdate = false;
2935 obPart.StoreUndoState(); 3085 obPart.StoreUndoState();
@@ -2937,6 +3087,7 @@ namespace OpenSim.Region.Framework.Scenes
2937 } 3087 }
2938 } 3088 }
2939 } 3089 }
3090 lockPartsForRead(false);
2940 3091
2941 Vector3 prevScale = part.Scale; 3092 Vector3 prevScale = part.Scale;
2942 prevScale.X *= x; 3093 prevScale.X *= x;
@@ -2944,7 +3095,7 @@ namespace OpenSim.Region.Framework.Scenes
2944 prevScale.Z *= z; 3095 prevScale.Z *= z;
2945 part.Resize(prevScale); 3096 part.Resize(prevScale);
2946 3097
2947 lock (m_parts) 3098 lockPartsForRead(true);
2948 { 3099 {
2949 foreach (SceneObjectPart obPart in m_parts.Values) 3100 foreach (SceneObjectPart obPart in m_parts.Values)
2950 { 3101 {
@@ -2966,6 +3117,7 @@ namespace OpenSim.Region.Framework.Scenes
2966 obPart.StoreUndoState(); 3117 obPart.StoreUndoState();
2967 } 3118 }
2968 } 3119 }
3120 lockPartsForRead(false);
2969 3121
2970 if (part.PhysActor != null) 3122 if (part.PhysActor != null)
2971 { 3123 {
@@ -3068,7 +3220,7 @@ namespace OpenSim.Region.Framework.Scenes
3068 axDiff *= Quaternion.Inverse(partRotation); 3220 axDiff *= Quaternion.Inverse(partRotation);
3069 diff = axDiff; 3221 diff = axDiff;
3070 3222
3071 lock (m_parts) 3223 lockPartsForRead(true);
3072 { 3224 {
3073 foreach (SceneObjectPart obPart in m_parts.Values) 3225 foreach (SceneObjectPart obPart in m_parts.Values)
3074 { 3226 {
@@ -3078,6 +3230,7 @@ namespace OpenSim.Region.Framework.Scenes
3078 } 3230 }
3079 } 3231 }
3080 } 3232 }
3233 lockPartsForRead(false);
3081 3234
3082 AbsolutePosition = newPos; 3235 AbsolutePosition = newPos;
3083 3236
@@ -3211,7 +3364,7 @@ namespace OpenSim.Region.Framework.Scenes
3211 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3364 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3212 } 3365 }
3213 3366
3214 lock (m_parts) 3367 lockPartsForRead(true);
3215 { 3368 {
3216 foreach (SceneObjectPart prim in m_parts.Values) 3369 foreach (SceneObjectPart prim in m_parts.Values)
3217 { 3370 {
@@ -3230,6 +3383,7 @@ namespace OpenSim.Region.Framework.Scenes
3230 } 3383 }
3231 } 3384 }
3232 } 3385 }
3386
3233 foreach (SceneObjectPart childpart in Children.Values) 3387 foreach (SceneObjectPart childpart in Children.Values)
3234 { 3388 {
3235 if (childpart != m_rootPart) 3389 if (childpart != m_rootPart)
@@ -3238,6 +3392,9 @@ namespace OpenSim.Region.Framework.Scenes
3238 childpart.StoreUndoState(); 3392 childpart.StoreUndoState();
3239 } 3393 }
3240 } 3394 }
3395
3396 lockPartsForRead(false);
3397
3241 m_rootPart.ScheduleTerseUpdate(); 3398 m_rootPart.ScheduleTerseUpdate();
3242 } 3399 }
3243 3400
@@ -3359,7 +3516,7 @@ namespace OpenSim.Region.Framework.Scenes
3359 if (atTargets.Count > 0) 3516 if (atTargets.Count > 0)
3360 { 3517 {
3361 uint[] localids = new uint[0]; 3518 uint[] localids = new uint[0];
3362 lock (m_parts) 3519 lockPartsForRead(true);
3363 { 3520 {
3364 localids = new uint[m_parts.Count]; 3521 localids = new uint[m_parts.Count];
3365 int cntr = 0; 3522 int cntr = 0;
@@ -3369,6 +3526,7 @@ namespace OpenSim.Region.Framework.Scenes
3369 cntr++; 3526 cntr++;
3370 } 3527 }
3371 } 3528 }
3529 lockPartsForRead(false);
3372 3530
3373 for (int ctr = 0; ctr < localids.Length; ctr++) 3531 for (int ctr = 0; ctr < localids.Length; ctr++)
3374 { 3532 {
@@ -3387,7 +3545,7 @@ namespace OpenSim.Region.Framework.Scenes
3387 { 3545 {
3388 //trigger not_at_target 3546 //trigger not_at_target
3389 uint[] localids = new uint[0]; 3547 uint[] localids = new uint[0];
3390 lock (m_parts) 3548 lockPartsForRead(true);
3391 { 3549 {
3392 localids = new uint[m_parts.Count]; 3550 localids = new uint[m_parts.Count];
3393 int cntr = 0; 3551 int cntr = 0;
@@ -3397,7 +3555,8 @@ namespace OpenSim.Region.Framework.Scenes
3397 cntr++; 3555 cntr++;
3398 } 3556 }
3399 } 3557 }
3400 3558 lockPartsForRead(false);
3559
3401 for (int ctr = 0; ctr < localids.Length; ctr++) 3560 for (int ctr = 0; ctr < localids.Length; ctr++)
3402 { 3561 {
3403 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3562 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3489,19 +3648,20 @@ namespace OpenSim.Region.Framework.Scenes
3489 public float GetMass() 3648 public float GetMass()
3490 { 3649 {
3491 float retmass = 0f; 3650 float retmass = 0f;
3492 lock (m_parts) 3651 lockPartsForRead(true);
3493 { 3652 {
3494 foreach (SceneObjectPart part in m_parts.Values) 3653 foreach (SceneObjectPart part in m_parts.Values)
3495 { 3654 {
3496 retmass += part.GetMass(); 3655 retmass += part.GetMass();
3497 } 3656 }
3498 } 3657 }
3658 lockPartsForRead(false);
3499 return retmass; 3659 return retmass;
3500 } 3660 }
3501 3661
3502 public void CheckSculptAndLoad() 3662 public void CheckSculptAndLoad()
3503 { 3663 {
3504 lock (m_parts) 3664 lockPartsForRead(true);
3505 { 3665 {
3506 if (!IsDeleted) 3666 if (!IsDeleted)
3507 { 3667 {
@@ -3526,6 +3686,7 @@ namespace OpenSim.Region.Framework.Scenes
3526 } 3686 }
3527 } 3687 }
3528 } 3688 }
3689 lockPartsForRead(false);
3529 } 3690 }
3530 3691
3531 protected void AssetReceived(string id, Object sender, AssetBase asset) 3692 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3546,7 +3707,7 @@ namespace OpenSim.Region.Framework.Scenes
3546 /// <param name="client"></param> 3707 /// <param name="client"></param>
3547 public void SetGroup(UUID GroupID, IClientAPI client) 3708 public void SetGroup(UUID GroupID, IClientAPI client)
3548 { 3709 {
3549 lock (m_parts) 3710 lockPartsForRead(true);
3550 { 3711 {
3551 foreach (SceneObjectPart part in m_parts.Values) 3712 foreach (SceneObjectPart part in m_parts.Values)
3552 { 3713 {
@@ -3556,7 +3717,7 @@ namespace OpenSim.Region.Framework.Scenes
3556 3717
3557 HasGroupChanged = true; 3718 HasGroupChanged = true;
3558 } 3719 }
3559 3720 lockPartsForRead(false);
3560 ScheduleGroupForFullUpdate(); 3721 ScheduleGroupForFullUpdate();
3561 } 3722 }
3562 3723
@@ -3575,11 +3736,12 @@ namespace OpenSim.Region.Framework.Scenes
3575 3736
3576 public void SetAttachmentPoint(byte point) 3737 public void SetAttachmentPoint(byte point)
3577 { 3738 {
3578 lock (m_parts) 3739 lockPartsForRead(true);
3579 { 3740 {
3580 foreach (SceneObjectPart part in m_parts.Values) 3741 foreach (SceneObjectPart part in m_parts.Values)
3581 part.SetAttachmentPoint(point); 3742 part.SetAttachmentPoint(point);
3582 } 3743 }
3744 lockPartsForRead(false);
3583 } 3745 }
3584 3746
3585 #region ISceneObject 3747 #region ISceneObject