aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
authorDan Lake2010-03-17 06:40:00 -0700
committerJohn Hurliman2010-03-17 11:21:27 -0700
commit73e9b0be725a73a489b29f3fe2df236c897ef3b5 (patch)
tree0d039d61d327e98ed22e4bce30de65c24fc5780d /OpenSim/Region/Framework/Scenes/SceneGraph.cs
parentminor logging changes to BaseHttpServer, OSHttpRequest (diff)
downloadopensim-SC_OLD-73e9b0be725a73a489b29f3fe2df236c897ef3b5.zip
opensim-SC_OLD-73e9b0be725a73a489b29f3fe2df236c897ef3b5.tar.gz
opensim-SC_OLD-73e9b0be725a73a489b29f3fe2df236c897ef3b5.tar.bz2
opensim-SC_OLD-73e9b0be725a73a489b29f3fe2df236c897ef3b5.tar.xz
Inconsistent locking of ScenePresence array in SceneGraph. Fixed by eliminating option to return the actual list. Callers can now either request a copy of the array as a new List or ask the SceneGraph to call a delegate function on every ScenePresence. Iteration and locking of the ScenePresences now takes place only within the SceneGraph class.
This patch also applies a fix to Combat/CombatModule.cs which had unlocked iteration of the ScenePresences and inconsistent try/catch around the use of those ScenePresences.
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs193
1 files changed, 130 insertions, 63 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index d944834..d259c42 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -165,9 +165,10 @@ namespace OpenSim.Region.Framework.Scenes
165 165
166 protected internal void UpdatePresences() 166 protected internal void UpdatePresences()
167 { 167 {
168 ScenePresence[] updateScenePresences = GetScenePresences(); 168 ForEachScenePresence(delegate(ScenePresence presence)
169 for (int i = 0; i < updateScenePresences.Length; i++) 169 {
170 updateScenePresences[i].Update(); 170 presence.Update();
171 });
171 } 172 }
172 173
173 protected internal float UpdatePhysics(double elapsed) 174 protected internal float UpdatePhysics(double elapsed)
@@ -196,9 +197,10 @@ namespace OpenSim.Region.Framework.Scenes
196 197
197 protected internal void UpdateScenePresenceMovement() 198 protected internal void UpdateScenePresenceMovement()
198 { 199 {
199 ScenePresence[] moveEntities = GetScenePresences(); 200 ForEachScenePresence(delegate(ScenePresence presence)
200 for (int i = 0; i < moveEntities.Length; i++) 201 {
201 moveEntities[i].UpdateMovement(); 202 presence.UpdateMovement();
203 });
202 } 204 }
203 205
204 #endregion 206 #endregion
@@ -616,18 +618,16 @@ namespace OpenSim.Region.Framework.Scenes
616 618
617 public void RecalculateStats() 619 public void RecalculateStats()
618 { 620 {
619 ScenePresence[] presences = GetScenePresences();
620 int rootcount = 0; 621 int rootcount = 0;
621 int childcount = 0; 622 int childcount = 0;
622 623
623 for (int i = 0; i < presences.Length; i++) 624 ForEachScenePresence(delegate(ScenePresence presence)
624 { 625 {
625 ScenePresence user = presences[i]; 626 if (presence.IsChildAgent)
626 if (user.IsChildAgent)
627 ++childcount; 627 ++childcount;
628 else 628 else
629 ++rootcount; 629 ++rootcount;
630 } 630 });
631 631
632 m_numRootAgents = rootcount; 632 m_numRootAgents = rootcount;
633 m_numChildAgents = childcount; 633 m_numChildAgents = childcount;
@@ -674,25 +674,6 @@ namespace OpenSim.Region.Framework.Scenes
674 #endregion 674 #endregion
675 675
676 #region Get Methods 676 #region Get Methods
677
678 /// <summary>
679 /// Request a List of all scene presences in this scene. This is a new list, so no
680 /// locking is required to iterate over it.
681 /// </summary>
682 /// <returns></returns>
683 protected internal ScenePresence[] GetScenePresences()
684 {
685 return m_scenePresenceArray;
686 }
687
688 protected internal List<ScenePresence> GetAvatars()
689 {
690 List<ScenePresence> result =
691 GetScenePresences(delegate(ScenePresence scenePresence) { return !scenePresence.IsChildAgent; });
692
693 return result;
694 }
695
696 /// <summary> 677 /// <summary>
697 /// Get the controlling client for the given avatar, if there is one. 678 /// Get the controlling client for the given avatar, if there is one.
698 /// 679 ///
@@ -718,45 +699,119 @@ namespace OpenSim.Region.Framework.Scenes
718 return null; 699 return null;
719 } 700 }
720 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>
711 /// Request a list of all avatars in this region (no child agents)
712 /// This list is a new object, so it can be iterated over without locking.
713 /// </summary>
714 /// <returns></returns>
715 public List<ScenePresence> GetAvatars()
716 {
717 return GetScenePresences(delegate(ScenePresence scenePresence)
718 {
719 return !scenePresence.IsChildAgent;
720 });
721 }
722
723 /// <summary>
724 /// Request a list of m_scenePresences in this World
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>
728 /// <returns></returns>
729 protected internal List<ScenePresence> GetScenePresences()
730 {
731 List<ScenePresence> result;
732 lock (m_scenePresences)
733 {
734 result = new List<ScenePresence>(m_scenePresenceArray.Length);
735 result.AddRange(m_scenePresenceArray);
736 }
737 return result;
738 }
739
721 /// <summary> 740 /// <summary>
722 /// Request a filtered list of m_scenePresences in this World 741 /// Request a filtered list of m_scenePresences in this World
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.
723 /// </summary> 744 /// </summary>
724 /// <returns></returns> 745 /// <returns></returns>
725 protected internal List<ScenePresence> GetScenePresences(FilterAvatarList filter) 746 protected internal List<ScenePresence> GetScenePresences(FilterAvatarList filter)
726 { 747 {
727 // No locking of scene presences here since we're passing back a list...
728
729 List<ScenePresence> result = new List<ScenePresence>(); 748 List<ScenePresence> result = new List<ScenePresence>();
730 ScenePresence[] scenePresences = GetScenePresences(); 749 // Check each ScenePresence against the filter
750 ForEachScenePresence(delegate(ScenePresence presence)
751 {
752 if (filter(presence))
753 result.Add(presence);
754 });
755 return result;
756 }
731 757
732 for (int i = 0; i < scenePresences.Length; i++) 758 /// <summary>
759 /// Request the ScenePresence in this region matching filter.
760 /// Only the first match is returned.
761 ///
762 /// </summary>
763 /// <param name="filter"></param>
764 /// <returns></returns>
765 protected internal ScenePresence GetScenePresence(FilterAvatarList filter)
766 {
767 ScenePresence result = null;
768 // Get all of the ScenePresences
769 List<ScenePresence> presences = GetScenePresences();
770 foreach (ScenePresence presence in presences)
733 { 771 {
734 ScenePresence avatar = scenePresences[i]; 772 if (filter(presence))
735 if (filter(avatar)) 773 {
736 result.Add(avatar); 774 result = presence;
775 break;
776 }
737 } 777 }
738
739 return result; 778 return result;
740 } 779 }
741 780
781 protected internal ScenePresence GetScenePresence(string firstName, string lastName)
782 {
783 return GetScenePresence(delegate(ScenePresence presence)
784 {
785 return(presence.Firstname == firstName && presence.Lastname == lastName);
786 });
787 }
788
742 /// <summary> 789 /// <summary>
743 /// Request a scene presence by UUID 790 /// Request a scene presence by UUID
744 /// </summary> 791 /// </summary>
745 /// <param name="avatarID"></param> 792 /// <param name="agentID"></param>
746 /// <returns>null if the agent was not found</returns> 793 /// <returns>null if the agent was not found</returns>
747 protected internal ScenePresence GetScenePresence(UUID agentID) 794 protected internal ScenePresence GetScenePresence(UUID agentID)
748 { 795 {
749 ScenePresence sp; 796 ScenePresence sp;
750 797 TryGetAvatar(agentID, out sp);
751 lock (m_scenePresences)
752 {
753 m_scenePresences.TryGetValue(agentID, out sp);
754 }
755
756 return sp; 798 return sp;
757 } 799 }
758 800
759 /// <summary> 801 /// <summary>
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 {
808 return GetScenePresence(delegate(ScenePresence presence)
809 {
810 return (presence.LocalId == localID);
811 });
812 }
813
814 /// <summary>
760 /// Get a scene object group that contains the prim with the given local id 815 /// Get a scene object group that contains the prim with the given local id
761 /// </summary> 816 /// </summary>
762 /// <param name="localID"></param> 817 /// <param name="localID"></param>
@@ -910,29 +965,19 @@ namespace OpenSim.Region.Framework.Scenes
910 protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar) 965 protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
911 { 966 {
912 lock (m_scenePresences) 967 lock (m_scenePresences)
913 return m_scenePresences.TryGetValue(avatarId, out avatar); 968 {
969 m_scenePresences.TryGetValue(avatarId, out avatar);
970 }
971 return (avatar != null);
914 } 972 }
915 973
916 protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) 974 protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
917 { 975 {
918 ScenePresence[] presences = GetScenePresences(); 976 avatar = GetScenePresence(delegate(ScenePresence presence)
919
920 for (int i = 0; i < presences.Length; i++)
921 { 977 {
922 ScenePresence presence = presences[i]; 978 return (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0);
923 979 });
924 if (!presence.IsChildAgent) 980 return (avatar != null);
925 {
926 if (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0)
927 {
928 avatar = presence;
929 return true;
930 }
931 }
932 }
933
934 avatar = null;
935 return false;
936 } 981 }
937 982
938 /// <summary> 983 /// <summary>
@@ -1013,6 +1058,28 @@ namespace OpenSim.Region.Framework.Scenes
1013 } 1058 }
1014 } 1059 }
1015 } 1060 }
1061
1062
1063 /// <summary>
1064 /// Performs action on all scene presences.
1065 /// </summary>
1066 /// <param name="action"></param>
1067 public void ForEachScenePresence(Action<ScenePresence> action)
1068 {
1069 List<ScenePresence> presences = GetScenePresences();
1070 try
1071 {
1072 foreach(ScenePresence presence in presences)
1073 {
1074 action(presence);
1075 }
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 }
1082 }
1016 1083
1017 #endregion 1084 #endregion
1018 1085