diff options
author | John Hurliman | 2010-09-10 12:04:12 -0700 |
---|---|---|
committer | John Hurliman | 2010-09-10 12:04:12 -0700 |
commit | dd277a0d02f1aa79f4fcb5d108cbc696e90500c2 (patch) | |
tree | 7e396d347e43504ec23c59c3749f995f15c2e254 /OpenSim/Region/Framework/Scenes/SceneGraph.cs | |
parent | * Run SimianGrid session updates asynchronously instead of from the main hear... (diff) | |
download | opensim-SC-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.zip opensim-SC-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.tar.gz opensim-SC-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.tar.bz2 opensim-SC-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.tar.xz |
First pass at cleaning up thread safety in EntityManager and SceneGraph
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 263 |
1 files changed, 127 insertions, 136 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index dfb26b9..3d3e822 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -348,68 +348,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
348 | if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) | 348 | if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) |
349 | return false; | 349 | return false; |
350 | 350 | ||
351 | lock (sceneObject) | 351 | if (Entities.ContainsKey(sceneObject.UUID)) |
352 | { | 352 | return false; |
353 | if (Entities.ContainsKey(sceneObject.UUID)) | 353 | |
354 | { | 354 | // Clamp child prim sizes and add child prims to the m_numPrim count |
355 | // m_log.WarnFormat( | 355 | lock (sceneObject.Children) |
356 | // "[SCENE GRAPH]: Scene object {0} {1} was already in region {2} on add request", | 356 | { |
357 | // sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); | 357 | if (m_parentScene.m_clampPrimSize) |
358 | return false; | ||
359 | } | ||
360 | |||
361 | // m_log.DebugFormat( | ||
362 | // "[SCENE GRAPH]: Adding object {0} {1} to region {2}", | ||
363 | // sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); | ||
364 | |||
365 | lock (sceneObject.Children) | ||
366 | { | 358 | { |
367 | if (m_parentScene.m_clampPrimSize) | 359 | foreach (SceneObjectPart part in sceneObject.Children.Values) |
368 | { | 360 | { |
369 | foreach (SceneObjectPart part in sceneObject.Children.Values) | 361 | Vector3 scale = part.Shape.Scale; |
370 | { | 362 | |
371 | Vector3 scale = part.Shape.Scale; | 363 | if (scale.X > m_parentScene.m_maxNonphys) |
372 | 364 | scale.X = m_parentScene.m_maxNonphys; | |
373 | if (scale.X > m_parentScene.m_maxNonphys) | 365 | if (scale.Y > m_parentScene.m_maxNonphys) |
374 | scale.X = m_parentScene.m_maxNonphys; | 366 | scale.Y = m_parentScene.m_maxNonphys; |
375 | if (scale.Y > m_parentScene.m_maxNonphys) | 367 | if (scale.Z > m_parentScene.m_maxNonphys) |
376 | scale.Y = m_parentScene.m_maxNonphys; | 368 | scale.Z = m_parentScene.m_maxNonphys; |
377 | if (scale.Z > m_parentScene.m_maxNonphys) | 369 | |
378 | scale.Z = m_parentScene.m_maxNonphys; | 370 | part.Shape.Scale = scale; |
379 | |||
380 | part.Shape.Scale = scale; | ||
381 | } | ||
382 | } | 371 | } |
383 | |||
384 | m_numPrim += sceneObject.Children.Count; | ||
385 | } | 372 | } |
386 | |||
387 | sceneObject.AttachToScene(m_parentScene); | ||
388 | 373 | ||
389 | if (sendClientUpdates) | 374 | m_numPrim += sceneObject.Children.Count; |
390 | sceneObject.ScheduleGroupForFullUpdate(); | 375 | } |
391 | |||
392 | Entities.Add(sceneObject); | ||
393 | 376 | ||
394 | if (attachToBackup) | 377 | sceneObject.AttachToScene(m_parentScene); |
395 | sceneObject.AttachToBackup(); | ||
396 | 378 | ||
397 | if (OnObjectCreate != null) | 379 | if (sendClientUpdates) |
398 | OnObjectCreate(sceneObject); | 380 | sceneObject.ScheduleGroupForFullUpdate(); |
399 | 381 | ||
400 | lock (SceneObjectGroupsByFullID) | 382 | Entities.Add(sceneObject); |
401 | { | 383 | |
402 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; | 384 | if (attachToBackup) |
403 | foreach (SceneObjectPart part in sceneObject.Children.Values) | 385 | sceneObject.AttachToBackup(); |
404 | SceneObjectGroupsByFullID[part.UUID] = sceneObject; | 386 | |
405 | } | 387 | if (OnObjectCreate != null) |
406 | 388 | OnObjectCreate(sceneObject); | |
407 | lock (SceneObjectGroupsByLocalID) | 389 | |
408 | { | 390 | lock (SceneObjectGroupsByFullID) |
409 | SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; | 391 | { |
410 | foreach (SceneObjectPart part in sceneObject.Children.Values) | 392 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; |
411 | SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; | 393 | foreach (SceneObjectPart part in sceneObject.Children.Values) |
412 | } | 394 | SceneObjectGroupsByFullID[part.UUID] = sceneObject; |
395 | } | ||
396 | |||
397 | lock (SceneObjectGroupsByLocalID) | ||
398 | { | ||
399 | SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; | ||
400 | foreach (SceneObjectPart part in sceneObject.Children.Values) | ||
401 | SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; | ||
413 | } | 402 | } |
414 | 403 | ||
415 | return true; | 404 | return true; |
@@ -421,42 +410,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
421 | /// <returns>true if the object was deleted, false if there was no object to delete</returns> | 410 | /// <returns>true if the object was deleted, false if there was no object to delete</returns> |
422 | public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) | 411 | public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) |
423 | { | 412 | { |
424 | if (Entities.ContainsKey(uuid)) | 413 | EntityBase entity; |
425 | { | 414 | if (!Entities.TryGetValue(uuid, out entity) && entity is SceneObjectGroup) |
426 | SceneObjectGroup grp = (SceneObjectGroup)Entities[uuid]; | 415 | return false; |
427 | 416 | ||
428 | if (!resultOfObjectLinked) | 417 | SceneObjectGroup grp = (SceneObjectGroup)entity; |
429 | { | ||
430 | m_numPrim -= grp.PrimCount; | ||
431 | 418 | ||
432 | if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) | 419 | if (!resultOfObjectLinked) |
433 | RemovePhysicalPrim(grp.PrimCount); | 420 | { |
434 | } | 421 | m_numPrim -= grp.PrimCount; |
435 | 422 | ||
436 | if (OnObjectRemove != null) | 423 | if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) |
437 | OnObjectRemove(Entities[uuid]); | 424 | RemovePhysicalPrim(grp.PrimCount); |
425 | } | ||
438 | 426 | ||
439 | lock (SceneObjectGroupsByFullID) | 427 | if (OnObjectRemove != null) |
440 | { | 428 | OnObjectRemove(Entities[uuid]); |
441 | foreach (SceneObjectPart part in grp.Children.Values) | ||
442 | SceneObjectGroupsByFullID.Remove(part.UUID); | ||
443 | SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); | ||
444 | } | ||
445 | lock (SceneObjectGroupsByLocalID) | ||
446 | { | ||
447 | foreach (SceneObjectPart part in grp.Children.Values) | ||
448 | SceneObjectGroupsByLocalID.Remove(part.LocalId); | ||
449 | SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); | ||
450 | } | ||
451 | 429 | ||
452 | Entities.Remove(uuid); | 430 | lock (SceneObjectGroupsByFullID) |
453 | //SceneObjectGroup part; | 431 | { |
454 | //((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) | 432 | foreach (SceneObjectPart part in grp.Children.Values) |
433 | SceneObjectGroupsByFullID.Remove(part.UUID); | ||
434 | SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); | ||
435 | } | ||
455 | 436 | ||
456 | return true; | 437 | lock (SceneObjectGroupsByLocalID) |
438 | { | ||
439 | foreach (SceneObjectPart part in grp.Children.Values) | ||
440 | SceneObjectGroupsByLocalID.Remove(part.LocalId); | ||
441 | SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); | ||
457 | } | 442 | } |
458 | 443 | ||
459 | return false; | 444 | return Entities.Remove(uuid); |
460 | } | 445 | } |
461 | 446 | ||
462 | /// <summary> | 447 | /// <summary> |
@@ -468,9 +453,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
468 | protected internal void AddToUpdateList(SceneObjectGroup obj) | 453 | protected internal void AddToUpdateList(SceneObjectGroup obj) |
469 | { | 454 | { |
470 | lock (m_updateList) | 455 | lock (m_updateList) |
471 | { | ||
472 | m_updateList[obj.UUID] = obj; | 456 | m_updateList[obj.UUID] = obj; |
473 | } | ||
474 | } | 457 | } |
475 | 458 | ||
476 | /// <summary> | 459 | /// <summary> |
@@ -480,34 +463,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
480 | { | 463 | { |
481 | if (!Monitor.TryEnter(m_updateLock)) | 464 | if (!Monitor.TryEnter(m_updateLock)) |
482 | return; | 465 | return; |
483 | 466 | try | |
484 | List<SceneObjectGroup> updates; | ||
485 | |||
486 | // Some updates add more updates to the updateList. | ||
487 | // Get the current list of updates and clear the list before iterating | ||
488 | lock (m_updateList) | ||
489 | { | ||
490 | updates = new List<SceneObjectGroup>(m_updateList.Values); | ||
491 | m_updateList.Clear(); | ||
492 | } | ||
493 | |||
494 | // Go through all updates | ||
495 | for (int i = 0; i < updates.Count; i++) | ||
496 | { | 467 | { |
497 | SceneObjectGroup sog = updates[i]; | 468 | List<SceneObjectGroup> updates; |
498 | 469 | ||
499 | // Don't abort the whole update if one entity happens to give us an exception. | 470 | // Some updates add more updates to the updateList. |
500 | try | 471 | // Get the current list of updates and clear the list before iterating |
472 | lock (m_updateList) | ||
501 | { | 473 | { |
502 | sog.Update(); | 474 | updates = new List<SceneObjectGroup>(m_updateList.Values); |
475 | m_updateList.Clear(); | ||
503 | } | 476 | } |
504 | catch (Exception e) | 477 | |
478 | // Go through all updates | ||
479 | for (int i = 0; i < updates.Count; i++) | ||
505 | { | 480 | { |
506 | m_log.ErrorFormat( | 481 | SceneObjectGroup sog = updates[i]; |
507 | "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); | 482 | |
483 | // Don't abort the whole update if one entity happens to give us an exception. | ||
484 | try | ||
485 | { | ||
486 | sog.Update(); | ||
487 | } | ||
488 | catch (Exception e) | ||
489 | { | ||
490 | m_log.ErrorFormat( | ||
491 | "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); | ||
492 | } | ||
508 | } | 493 | } |
509 | } | 494 | } |
510 | Monitor.Exit(m_updateLock); | 495 | finally |
496 | { | ||
497 | Monitor.Exit(m_updateLock); | ||
498 | } | ||
511 | } | 499 | } |
512 | 500 | ||
513 | protected internal void AddPhysicalPrim(int number) | 501 | protected internal void AddPhysicalPrim(int number) |
@@ -864,8 +852,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
864 | /// <returns>null if no scene object group containing that prim is found</returns> | 852 | /// <returns>null if no scene object group containing that prim is found</returns> |
865 | public SceneObjectGroup GetGroupByPrim(uint localID) | 853 | public SceneObjectGroup GetGroupByPrim(uint localID) |
866 | { | 854 | { |
867 | if (Entities.ContainsKey(localID)) | 855 | EntityBase entity; |
868 | return Entities[localID] as SceneObjectGroup; | 856 | if (Entities.TryGetValue(localID, out entity)) |
857 | return entity as SceneObjectGroup; | ||
869 | 858 | ||
870 | //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); | 859 | //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); |
871 | SceneObjectGroup sog; | 860 | SceneObjectGroup sog; |
@@ -879,23 +868,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
879 | } | 868 | } |
880 | } | 869 | } |
881 | 870 | ||
882 | List<EntityBase> EntityList = GetEntities(); | 871 | EntityBase[] entityList = GetEntities(); |
883 | foreach (EntityBase ent in EntityList) | 872 | foreach (EntityBase ent in entityList) |
884 | { | 873 | { |
885 | //m_log.DebugFormat("Looking at entity {0}", ent.UUID); | 874 | //m_log.DebugFormat("Looking at entity {0}", ent.UUID); |
886 | if (ent is SceneObjectGroup) | 875 | if (ent is SceneObjectGroup) |
887 | { | 876 | { |
888 | if (((SceneObjectGroup)ent).HasChildPrim(localID)) | 877 | sog = (SceneObjectGroup)ent; |
878 | if (sog.HasChildPrim(localID)) | ||
889 | { | 879 | { |
890 | sog = (SceneObjectGroup)ent; | ||
891 | lock (SceneObjectGroupsByLocalID) | 880 | lock (SceneObjectGroupsByLocalID) |
892 | { | ||
893 | SceneObjectGroupsByLocalID[localID] = sog; | 881 | SceneObjectGroupsByLocalID[localID] = sog; |
894 | } | ||
895 | return sog; | 882 | return sog; |
896 | } | 883 | } |
897 | } | 884 | } |
898 | } | 885 | } |
886 | |||
899 | return null; | 887 | return null; |
900 | } | 888 | } |
901 | 889 | ||
@@ -921,23 +909,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
921 | } | 909 | } |
922 | } | 910 | } |
923 | 911 | ||
924 | List<EntityBase> EntityList = GetEntities(); | 912 | EntityBase[] entityList = GetEntities(); |
925 | 913 | foreach (EntityBase ent in entityList) | |
926 | foreach (EntityBase ent in EntityList) | ||
927 | { | 914 | { |
928 | if (ent is SceneObjectGroup) | 915 | if (ent is SceneObjectGroup) |
929 | { | 916 | { |
930 | if (((SceneObjectGroup)ent).HasChildPrim(fullID)) | 917 | sog = (SceneObjectGroup)ent; |
918 | if (sog.HasChildPrim(fullID)) | ||
931 | { | 919 | { |
932 | sog = (SceneObjectGroup)ent; | ||
933 | lock (SceneObjectGroupsByFullID) | 920 | lock (SceneObjectGroupsByFullID) |
934 | { | ||
935 | SceneObjectGroupsByFullID[fullID] = sog; | 921 | SceneObjectGroupsByFullID[fullID] = sog; |
936 | } | ||
937 | return sog; | 922 | return sog; |
938 | } | 923 | } |
939 | } | 924 | } |
940 | } | 925 | } |
926 | |||
941 | return null; | 927 | return null; |
942 | } | 928 | } |
943 | 929 | ||
@@ -946,7 +932,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
946 | // Primitive Ray Tracing | 932 | // Primitive Ray Tracing |
947 | float closestDistance = 280f; | 933 | float closestDistance = 280f; |
948 | EntityIntersection result = new EntityIntersection(); | 934 | EntityIntersection result = new EntityIntersection(); |
949 | List<EntityBase> EntityList = GetEntities(); | 935 | EntityBase[] EntityList = GetEntities(); |
950 | foreach (EntityBase ent in EntityList) | 936 | foreach (EntityBase ent in EntityList) |
951 | { | 937 | { |
952 | if (ent is SceneObjectGroup) | 938 | if (ent is SceneObjectGroup) |
@@ -984,23 +970,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
984 | /// <returns>null if the part was not found</returns> | 970 | /// <returns>null if the part was not found</returns> |
985 | protected internal SceneObjectPart GetSceneObjectPart(string name) | 971 | protected internal SceneObjectPart GetSceneObjectPart(string name) |
986 | { | 972 | { |
987 | List<EntityBase> EntityList = GetEntities(); | 973 | SceneObjectPart sop = null; |
988 | 974 | ||
989 | // FIXME: use a dictionary here | 975 | Entities.Find( |
990 | foreach (EntityBase ent in EntityList) | 976 | delegate(EntityBase entity) |
991 | { | ||
992 | if (ent is SceneObjectGroup) | ||
993 | { | 977 | { |
994 | foreach (SceneObjectPart p in ((SceneObjectGroup) ent).GetParts()) | 978 | if (entity is SceneObjectGroup) |
995 | { | 979 | { |
996 | if (p.Name == name) | 980 | foreach (SceneObjectPart p in ((SceneObjectGroup)entity).GetParts()) |
997 | { | 981 | { |
998 | return p; | 982 | if (p.Name == name) |
983 | { | ||
984 | sop = p; | ||
985 | return true; | ||
986 | } | ||
999 | } | 987 | } |
1000 | } | 988 | } |
989 | |||
990 | return false; | ||
1001 | } | 991 | } |
1002 | } | 992 | ); |
1003 | return null; | 993 | |
994 | return sop; | ||
1004 | } | 995 | } |
1005 | 996 | ||
1006 | /// <summary> | 997 | /// <summary> |
@@ -1021,7 +1012,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1021 | /// it | 1012 | /// it |
1022 | /// </summary> | 1013 | /// </summary> |
1023 | /// <returns></returns> | 1014 | /// <returns></returns> |
1024 | protected internal List<EntityBase> GetEntities() | 1015 | protected internal EntityBase[] GetEntities() |
1025 | { | 1016 | { |
1026 | return Entities.GetEntities(); | 1017 | return Entities.GetEntities(); |
1027 | } | 1018 | } |
@@ -1030,7 +1021,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1030 | { | 1021 | { |
1031 | Dictionary<uint, float> topScripts = new Dictionary<uint, float>(); | 1022 | Dictionary<uint, float> topScripts = new Dictionary<uint, float>(); |
1032 | 1023 | ||
1033 | List<EntityBase> EntityList = GetEntities(); | 1024 | EntityBase[] EntityList = GetEntities(); |
1034 | int limit = 0; | 1025 | int limit = 0; |
1035 | foreach (EntityBase ent in EntityList) | 1026 | foreach (EntityBase ent in EntityList) |
1036 | { | 1027 | { |
@@ -1726,8 +1717,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1726 | UUID objid = UUID.Zero; | 1717 | UUID objid = UUID.Zero; |
1727 | SceneObjectPart obj = null; | 1718 | SceneObjectPart obj = null; |
1728 | 1719 | ||
1729 | List<EntityBase> EntityList = GetEntities(); | 1720 | EntityBase[] entityList = GetEntities(); |
1730 | foreach (EntityBase ent in EntityList) | 1721 | foreach (EntityBase ent in entityList) |
1731 | { | 1722 | { |
1732 | if (ent is SceneObjectGroup) | 1723 | if (ent is SceneObjectGroup) |
1733 | { | 1724 | { |