From bbaf450c30a0822c8ffcc40bf75961f2c3c214e4 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Mon, 28 May 2012 02:14:14 +0200
Subject: Modify SceneManeger to use a DoubleDictionary and work without locks.
 Changes to the scenes dictionary are exceedingly rare and using atomic
 operations makes the chance of collisions nearly nil in any case.

---
 OpenSim/Region/Framework/Scenes/SceneManager.cs | 266 ++++++++----------------
 1 file changed, 90 insertions(+), 176 deletions(-)

diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index e4eaf3a..e3fed49 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -53,12 +53,12 @@ namespace OpenSim.Region.Framework.Scenes
             get { return m_instance; } 
         }
 
-        private readonly List<Scene> m_localScenes = new List<Scene>();
+        private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
         private Scene m_currentScene = null;
 
         public List<Scene> Scenes
         {
-            get { return new List<Scene>(m_localScenes); }
+            get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); }
         }
 
         public Scene CurrentScene
@@ -72,13 +72,10 @@ namespace OpenSim.Region.Framework.Scenes
             {
                 if (m_currentScene == null)
                 {
-                    lock (m_localScenes)
-                    {
-                        if (m_localScenes.Count > 0)
-                            return m_localScenes[0];
-                        else
-                            return null;
-                    }
+                    List<Scene> sceneList = Scenes;
+                    if (sceneList.Count == 0)
+                        return null;
+                    return sceneList[0];
                 }
                 else
                 {
@@ -90,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes
         public SceneManager()
         {
             m_instance = this;
-            m_localScenes = new List<Scene>();
+            m_localScenes = new DoubleDictionary<UUID, string, Scene>();
         }
 
         public void Close()
@@ -98,20 +95,18 @@ namespace OpenSim.Region.Framework.Scenes
             // collect known shared modules in sharedModules
             Dictionary<string, IRegionModule> sharedModules = new Dictionary<string, IRegionModule>();
 
-            lock (m_localScenes)
+            List<Scene> sceneList = Scenes;
+            for (int i = 0; i < sceneList.Count; i++)
             {
-                for (int i = 0; i < m_localScenes.Count; i++)
+                // extract known shared modules from scene
+                foreach (string k in sceneList[i].Modules.Keys)
                 {
-                    // extract known shared modules from scene
-                    foreach (string k in m_localScenes[i].Modules.Keys)
-                    {
-                        if (m_localScenes[i].Modules[k].IsSharedModule &&
-                            !sharedModules.ContainsKey(k))
-                            sharedModules[k] = m_localScenes[i].Modules[k];
-                    }
-                    // close scene/region
-                    m_localScenes[i].Close();
+                    if (sceneList[i].Modules[k].IsSharedModule &&
+                        !sharedModules.ContainsKey(k))
+                        sharedModules[k] = sceneList[i].Modules[k];
                 }
+                // close scene/region
+                sceneList[i].Close();
             }
 
             // all regions/scenes are now closed, we can now safely
@@ -120,31 +115,22 @@ namespace OpenSim.Region.Framework.Scenes
             {
                 mod.Close();
             }
+
+            m_localScenes.Clear();
         }
 
         public void Close(Scene cscene)
         {
-            lock (m_localScenes)
-            {
-                if (m_localScenes.Contains(cscene))
-                {
-                    for (int i = 0; i < m_localScenes.Count; i++)
-                    {
-                        if (m_localScenes[i].Equals(cscene))
-                        {
-                            m_localScenes[i].Close();
-                        }
-                    }
-                }
-            }
+            if (!m_localScenes.ContainsKey(cscene.RegionInfo.RegionID))
+                return;
+            cscene.Close();
         }
 
         public void Add(Scene scene)
         {
             scene.OnRestart += HandleRestart;
 
-            lock (m_localScenes)
-                m_localScenes.Add(scene);
+            m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
         }
 
         public void HandleRestart(RegionInfo rdata)
@@ -152,24 +138,7 @@ namespace OpenSim.Region.Framework.Scenes
             m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main");
             int RegionSceneElement = -1;
 
-            lock (m_localScenes)
-            {
-                for (int i = 0; i < m_localScenes.Count; i++)
-                {
-                    if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
-                    {
-                        RegionSceneElement = i;
-                    }
-                }
-
-                // Now we make sure the region is no longer known about by the SceneManager
-                // Prevents duplicates.
-
-                if (RegionSceneElement >= 0)
-                {
-                    m_localScenes.RemoveAt(RegionSceneElement);
-                }
-            }
+            m_localScenes.Remove(rdata.RegionID);
 
             // Send signal to main that we're restarting this sim.
             OnRestartSim(rdata);
@@ -179,32 +148,29 @@ namespace OpenSim.Region.Framework.Scenes
         {
             RegionInfo Result = null;
 
-            lock (m_localScenes)
-            {
-                for (int i = 0; i < m_localScenes.Count; i++)
-                {
-                    if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle)
+            Scene s = m_localScenes.FindValue(delegate(Scene x)
                     {
-                        // Inform other regions to tell their avatar about me
-                        Result = m_localScenes[i].RegionInfo;
-                    }
-                }
+                        if (x.RegionInfo.RegionHandle == regionHandle)
+                            return true;
+                        return false;
+                    });
 
-                if (Result != null)
+            if (s != null)
+            {
+                List<Scene> sceneList = Scenes;
+
+                for (int i = 0; i < sceneList.Count; i++)
                 {
-                    for (int i = 0; i < m_localScenes.Count; i++)
+                    if (sceneList[i]!= s)
                     {
-                        if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle)
-                        {
-                            // Inform other regions to tell their avatar about me
-                            //m_localScenes[i].OtherRegionUp(Result);
-                        }
+                        // Inform other regions to tell their avatar about me
+                        //sceneList[i].OtherRegionUp(Result);
                     }
                 }
-                else
-                {
-                    m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
-                }
+            }
+            else
+            {
+                m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
             }
         }
 
@@ -308,8 +274,8 @@ namespace OpenSim.Region.Framework.Scenes
         {
             if (m_currentScene == null)
             {
-                lock (m_localScenes)
-                    m_localScenes.ForEach(func);
+                List<Scene> sceneList = Scenes;
+                sceneList.ForEach(func);
             }
             else
             {
@@ -338,16 +304,12 @@ namespace OpenSim.Region.Framework.Scenes
             }
             else
             {
-                lock (m_localScenes)
+                Scene s;
+
+                if (m_localScenes.TryGetValue(regionName, out s))
                 {
-                    foreach (Scene scene in m_localScenes)
-                    {
-                        if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
-                        {
-                            m_currentScene = scene;
-                            return true;
-                        }
-                    }
+                    m_currentScene = s;
+                    return true;
                 }
 
                 return false;
@@ -358,16 +320,12 @@ namespace OpenSim.Region.Framework.Scenes
         {
 //            m_log.Debug("Searching for Region: '" + regionID + "'");
 
-            lock (m_localScenes)
+            Scene s;
+
+            if (m_localScenes.TryGetValue(regionID, out s))
             {
-                foreach (Scene scene in m_localScenes)
-                {
-                    if (scene.RegionInfo.RegionID == regionID)
-                    {
-                        m_currentScene = scene;
-                        return true;
-                    }
-                }
+                m_currentScene = s;
+                return true;
             }
 
             return false;
@@ -375,52 +333,24 @@ namespace OpenSim.Region.Framework.Scenes
 
         public bool TryGetScene(string regionName, out Scene scene)
         {
-            lock (m_localScenes)
-            {
-                foreach (Scene mscene in m_localScenes)
-                {
-                    if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0)
-                    {
-                        scene = mscene;
-                        return true;
-                    }
-                }
-            }
-
-            scene = null;
-            return false;
+            return m_localScenes.TryGetValue(regionName, out scene);
         }
 
         public bool TryGetScene(UUID regionID, out Scene scene)
         {
-            lock (m_localScenes)
-            {
-                foreach (Scene mscene in m_localScenes)
-                {
-                    if (mscene.RegionInfo.RegionID == regionID)
-                    {
-                        scene = mscene;
-                        return true;
-                    }
-                }
-            }
-            
-            scene = null;
-            return false;
+            return m_localScenes.TryGetValue(regionID, out scene);
         }
 
         public bool TryGetScene(uint locX, uint locY, out Scene scene)
         {
-            lock (m_localScenes)
+            List<Scene> sceneList = Scenes;
+            foreach (Scene mscene in sceneList)
             {
-                foreach (Scene mscene in m_localScenes)
+                if (mscene.RegionInfo.RegionLocX == locX &&
+                    mscene.RegionInfo.RegionLocY == locY)
                 {
-                    if (mscene.RegionInfo.RegionLocX == locX &&
-                        mscene.RegionInfo.RegionLocY == locY)
-                    {
-                        scene = mscene;
-                        return true;
-                    }
+                    scene = mscene;
+                    return true;
                 }
             }
             
@@ -430,16 +360,14 @@ namespace OpenSim.Region.Framework.Scenes
 
         public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene)
         {
-            lock (m_localScenes)
+            List<Scene> sceneList = Scenes;
+            foreach (Scene mscene in sceneList)
             {
-                foreach (Scene mscene in m_localScenes)
+                if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
+                    (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
                 {
-                    if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
-                        (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
-                    {
-                        scene = mscene;
-                        return true;
-                    }
+                    scene = mscene;
+                    return true;
                 }
             }
             
@@ -504,15 +432,10 @@ namespace OpenSim.Region.Framework.Scenes
 
         public RegionInfo GetRegionInfo(UUID regionID)
         {
-            lock (m_localScenes)
+            Scene s;
+            if (m_localScenes.TryGetValue(regionID, out s))
             {
-                foreach (Scene scene in m_localScenes)
-                {
-                    if (scene.RegionInfo.RegionID == regionID)
-                    {
-                        return scene.RegionInfo;
-                    }
-                }
+                return s.RegionInfo;
             }
 
             return null;
@@ -530,14 +453,12 @@ namespace OpenSim.Region.Framework.Scenes
 
         public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar)
         {
-            lock (m_localScenes)
+            List<Scene> sceneList = Scenes;
+            foreach (Scene scene in sceneList)
             {
-                foreach (Scene scene in m_localScenes)
+                if (scene.TryGetScenePresence(avatarId, out avatar))
                 {
-                    if (scene.TryGetScenePresence(avatarId, out avatar))
-                    {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
@@ -547,15 +468,13 @@ namespace OpenSim.Region.Framework.Scenes
 
         public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar)
         {
-            lock (m_localScenes)
+            List<Scene> sceneList = Scenes;
+            foreach (Scene scene in sceneList)
             {
-                foreach (Scene scene in m_localScenes)
-                {
-                    avatar = scene.GetScenePresence(avatarId);
+                avatar = scene.GetScenePresence(avatarId);
 
-                    if (avatar != null && !avatar.IsChildAgent)
-                        return true;
-                }
+                if (avatar != null && !avatar.IsChildAgent)
+                    return true;
             }
 
             avatar = null;
@@ -564,22 +483,19 @@ namespace OpenSim.Region.Framework.Scenes
 
         public void CloseScene(Scene scene)
         {
-            lock (m_localScenes)
-                m_localScenes.Remove(scene);
+            m_localScenes.Remove(scene.RegionInfo.RegionID);
 
             scene.Close();
         }
 
         public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
         {
-            lock (m_localScenes)
+            List<Scene> sceneList = Scenes;
+            foreach (Scene scene in sceneList)
             {
-                foreach (Scene scene in m_localScenes)
+                if (scene.TryGetAvatarByName(avatarName, out avatar))
                 {
-                    if (scene.TryGetAvatarByName(avatarName, out avatar))
-                    {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
@@ -589,14 +505,12 @@ namespace OpenSim.Region.Framework.Scenes
 
         public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp)
         {
-            lock (m_localScenes)
+            List<Scene> sceneList = Scenes;
+            foreach (Scene scene in sceneList)
             {
-                foreach (Scene scene in m_localScenes)
-                {
-                    sp = scene.GetScenePresence(firstName, lastName);
-                    if (sp != null && !sp.IsChildAgent)
-                        return true;
-                }
+                sp = scene.GetScenePresence(firstName, lastName);
+                if (sp != null && !sp.IsChildAgent)
+                    return true;
             }
 
             sp = null;
@@ -605,8 +519,8 @@ namespace OpenSim.Region.Framework.Scenes
 
         public void ForEachScene(Action<Scene> action)
         {
-            lock (m_localScenes)
-                m_localScenes.ForEach(action);
+            List<Scene> sceneList = Scenes;
+            sceneList.ForEach(action);
         }
     }
 }
-- 
cgit v1.1