aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
authorDan Lake2010-03-19 05:51:16 -0700
committerJohn Hurliman2010-03-19 15:16:35 -0700
commit859bc717a4fe4cd5810ad9889cfb9b1e7f5c2046 (patch)
treedcce6c74d201b52c1a04ec9ec2cb90ce068fc020 /OpenSim/Region/Framework/Scenes/SceneGraph.cs
parentInconsistent locking of ScenePresence array in SceneGraph. Fixed by eliminati... (diff)
downloadopensim-SC-859bc717a4fe4cd5810ad9889cfb9b1e7f5c2046.zip
opensim-SC-859bc717a4fe4cd5810ad9889cfb9b1e7f5c2046.tar.gz
opensim-SC-859bc717a4fe4cd5810ad9889cfb9b1e7f5c2046.tar.bz2
opensim-SC-859bc717a4fe4cd5810ad9889cfb9b1e7f5c2046.tar.xz
Cleaned up access to scenepresences in scenegraph. GetScenePresences and GetAvatars have been removed to consolidate locking and iteration within SceneGraph. All callers which used these to then iterate over presences have been refactored to instead pass their delegates to Scene.ForEachScenePresence(Action<ScenePresence>).
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs186
1 files changed, 79 insertions, 107 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index d259c42..b6e5995 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -699,116 +699,84 @@ namespace OpenSim.Region.Framework.Scenes
699 return null; 699 return null;
700 } 700 }
701 701
702 // The idea is to have a group of method that return a list of avatars meeting some requirement
703 // ie it could be all m_scenePresences within a certain range of the calling prim/avatar.
704 //
705 // GetAvatars returns a new list of all root agent presences in the scene
706 // GetScenePresences returns a new list of all presences in the scene or a filter may be passed.
707 // GetScenePresence returns the presence with matching UUID or the first presence matching the passed filter.
708 // ForEachScenePresence requests the Scene to run a delegate function against all presences.
709
710 /// <summary> 702 /// <summary>
711 /// Request a list of all avatars in this region (no child agents) 703 /// Request a copy of m_scenePresences in this World
712 /// This list is a new object, so it can be iterated over without locking. 704 /// There is no guarantee that presences will remain in the scene after the list is returned.
705 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
706 /// pass a delegate to ForEachScenePresence.
713 /// </summary> 707 /// </summary>
714 /// <returns></returns> 708 /// <returns></returns>
715 public List<ScenePresence> GetAvatars() 709 private List<ScenePresence> GetScenePresences()
716 { 710 {
717 return GetScenePresences(delegate(ScenePresence scenePresence) 711 lock (m_scenePresences)
718 { 712 return new List<ScenePresence>(m_scenePresenceArray);
719 return !scenePresence.IsChildAgent;
720 });
721 } 713 }
722 714
723 /// <summary> 715 /// <summary>
724 /// Request a list of m_scenePresences in this World 716 /// Request a scene presence by UUID. Fast, indexed lookup.
725 /// Returns a copy so it can be iterated without a lock.
726 /// There is no guarantee that presences will remain in the scene after the list is returned.
727 /// </summary> 717 /// </summary>
728 /// <returns></returns> 718 /// <param name="agentID"></param>
729 protected internal List<ScenePresence> GetScenePresences() 719 /// <returns>null if the presence was not found</returns>
720 protected internal ScenePresence GetScenePresence(UUID agentID)
730 { 721 {
731 List<ScenePresence> result; 722 ScenePresence sp;
732 lock (m_scenePresences) 723 lock (m_scenePresences)
733 { 724 {
734 result = new List<ScenePresence>(m_scenePresenceArray.Length); 725 m_scenePresences.TryGetValue(agentID, out sp);
735 result.AddRange(m_scenePresenceArray);
736 } 726 }
737 return result; 727 return sp;
738 } 728 }
739 729
740 /// <summary> 730 /// <summary>
741 /// Request a filtered list of m_scenePresences in this World 731 /// Request the scene presence by name.
742 /// Returns a copy so it can be iterated without a lock.
743 /// There is no guarantee that presences will remain in the scene after the list is returned.
744 /// </summary> 732 /// </summary>
745 /// <returns></returns> 733 /// <param name="firstName"></param>
746 protected internal List<ScenePresence> GetScenePresences(FilterAvatarList filter) 734 /// <param name="lastName"></param>
735 /// <returns>null if the presence was not found</returns>
736 protected internal ScenePresence GetScenePresence(string firstName, string lastName)
747 { 737 {
748 List<ScenePresence> result = new List<ScenePresence>(); 738 foreach (ScenePresence presence in GetScenePresences())
749 // Check each ScenePresence against the filter
750 ForEachScenePresence(delegate(ScenePresence presence)
751 { 739 {
752 if (filter(presence)) 740 if (presence.Firstname == firstName && presence.Lastname == lastName)
753 result.Add(presence); 741 return presence;
754 }); 742 }
755 return result; 743 return null;
756 } 744 }
757 745
758 /// <summary> 746 /// <summary>
759 /// Request the ScenePresence in this region matching filter. 747 /// Request the scene presence by localID.
760 /// Only the first match is returned.
761 ///
762 /// </summary> 748 /// </summary>
763 /// <param name="filter"></param> 749 /// <param name="localID"></param>
764 /// <returns></returns> 750 /// <returns>null if the presence was not found</returns>
765 protected internal ScenePresence GetScenePresence(FilterAvatarList filter) 751 protected internal ScenePresence GetScenePresence(uint localID)
766 { 752 {
767 ScenePresence result = null; 753 foreach (ScenePresence presence in GetScenePresences())
768 // Get all of the ScenePresences 754 if (presence.LocalId == localID)
769 List<ScenePresence> presences = GetScenePresences(); 755 return presence;
770 foreach (ScenePresence presence in presences) 756 return null;
771 {
772 if (filter(presence))
773 {
774 result = presence;
775 break;
776 }
777 }
778 return result;
779 } 757 }
780 758
781 protected internal ScenePresence GetScenePresence(string firstName, string lastName) 759 protected internal bool TryGetAvatar(UUID agentID, out ScenePresence avatar)
782 { 760 {
783 return GetScenePresence(delegate(ScenePresence presence) 761 lock (m_scenePresences)
784 { 762 {
785 return(presence.Firstname == firstName && presence.Lastname == lastName); 763 m_scenePresences.TryGetValue(agentID, out avatar);
786 }); 764 }
787 } 765 return (avatar != null);
788
789 /// <summary>
790 /// Request a scene presence by UUID
791 /// </summary>
792 /// <param name="agentID"></param>
793 /// <returns>null if the agent was not found</returns>
794 protected internal ScenePresence GetScenePresence(UUID agentID)
795 {
796 ScenePresence sp;
797 TryGetAvatar(agentID, out sp);
798 return sp;
799 } 766 }
800 767
801 /// <summary> 768 protected internal bool TryGetAvatarByName(string name, out ScenePresence avatar)
802 /// Request the ScenePresence in this region by localID.
803 /// </summary>
804 /// <param name="localID"></param>
805 /// <returns></returns>
806 protected internal ScenePresence GetScenePresence(uint localID)
807 { 769 {
808 return GetScenePresence(delegate(ScenePresence presence) 770 avatar = null;
771 foreach (ScenePresence presence in GetScenePresences())
809 { 772 {
810 return (presence.LocalId == localID); 773 if (String.Compare(name, presence.ControllingClient.Name, true) == 0)
811 }); 774 {
775 avatar = presence;
776 break;
777 }
778 }
779 return (avatar != null);
812 } 780 }
813 781
814 /// <summary> 782 /// <summary>
@@ -962,24 +930,6 @@ namespace OpenSim.Region.Framework.Scenes
962 return group.GetChildPart(fullID); 930 return group.GetChildPart(fullID);
963 } 931 }
964 932
965 protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
966 {
967 lock (m_scenePresences)
968 {
969 m_scenePresences.TryGetValue(avatarId, out avatar);
970 }
971 return (avatar != null);
972 }
973
974 protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
975 {
976 avatar = GetScenePresence(delegate(ScenePresence presence)
977 {
978 return (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0);
979 });
980 return (avatar != null);
981 }
982
983 /// <summary> 933 /// <summary>
984 /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over 934 /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over
985 /// it 935 /// it
@@ -1042,6 +992,10 @@ namespace OpenSim.Region.Framework.Scenes
1042 return UUID.Zero; 992 return UUID.Zero;
1043 } 993 }
1044 994
995 /// <summary>
996 /// Performs action on all scene object groups.
997 /// </summary>
998 /// <param name="action"></param>
1045 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 999 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1046 { 1000 {
1047 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1001 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
@@ -1061,23 +1015,41 @@ namespace OpenSim.Region.Framework.Scenes
1061 1015
1062 1016
1063 /// <summary> 1017 /// <summary>
1064 /// Performs action on all scene presences. 1018 /// Performs action on all scene presences. This can ultimately run the actions in parallel but
1019 /// any delegates passed in will need to implement their own locking on data they reference and
1020 /// modify outside of the scope of the delegate.
1065 /// </summary> 1021 /// </summary>
1066 /// <param name="action"></param> 1022 /// <param name="action"></param>
1067 public void ForEachScenePresence(Action<ScenePresence> action) 1023 public void ForEachScenePresence(Action<ScenePresence> action)
1068 { 1024 {
1069 List<ScenePresence> presences = GetScenePresences(); 1025 // Once all callers have their delegates configured for parallelism, we can unleash this
1070 try 1026 /*
1027 Action<ScenePresence> protectedAction = new Action<ScenePresence>(delegate(ScenePresence sp)
1028 {
1029 try
1030 {
1031 action(sp);
1032 }
1033 catch (Exception e)
1034 {
1035 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1036 m_log.Info("[BUG] Stack Trace: " + e.StackTrace);
1037 }
1038 });
1039 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
1040 */
1041 // For now, perform actiona serially
1042 foreach (ScenePresence sp in GetScenePresences())
1071 { 1043 {
1072 foreach(ScenePresence presence in presences) 1044 try
1073 { 1045 {
1074 action(presence); 1046 action(sp);
1047 }
1048 catch (Exception e)
1049 {
1050 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1051 m_log.Info("[BUG] Stack Trace: " + e.StackTrace);
1075 } 1052 }
1076 }
1077 catch (Exception e)
1078 {
1079 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1080 m_log.Info("[BUG] Stack Trace: " + e.StackTrace);
1081 } 1053 }
1082 } 1054 }
1083 1055