diff options
author | Dan Lake | 2010-03-19 05:51:16 -0700 |
---|---|---|
committer | John Hurliman | 2010-03-19 15:16:35 -0700 |
commit | 859bc717a4fe4cd5810ad9889cfb9b1e7f5c2046 (patch) | |
tree | dcce6c74d201b52c1a04ec9ec2cb90ce068fc020 /OpenSim/Region/Framework/Scenes/SceneGraph.cs | |
parent | Inconsistent locking of ScenePresence array in SceneGraph. Fixed by eliminati... (diff) | |
download | opensim-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.cs | 186 |
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 | ||