diff --git a/OpenSim/Region/Environment/Scenes/EntityList.cs b/OpenSim/Region/Environment/Scenes/EntityList.cs deleted file mode 100644 index 2488ab318e..0000000000 --- a/OpenSim/Region/Environment/Scenes/EntityList.cs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using OpenMetaverse.Packets; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Environment.Types; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Environment.Scenes -{ - public class EntityList - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // we are intentionally using non generics here as testing has - // shown synchronized collections are faster than manually - // locked generics. - - private Hashtable m_obj_by_uuid; - private Hashtable m_obj_by_local; - - private Hashtable m_pres_by_uuid; - - public EntityList() - { - m_obj_by_uuid = Hashtable.Synchronized(new Hashtable()); - m_obj_by_local = Hashtable.Synchronized(new Hashtable()); - m_pres_by_uuid = Hashtable.Synchronized(new Hashtable()); - } - - // Interface definition - // - // Add(SOG) - // Add(SP) - // RemoveObject(SOG) - // RemovePresence(SP) - // List() - // ListObjects() - // ListPresenes() - // RemoveAll() - // FindObject(UUID) - // FindObject(int) - // FindPresence(UUID) - - public void Add(SceneObjectGroup obj) - { - m_obj_by_uuid[obj.UUID] = obj; - m_obj_by_local[obj.LocalId] = obj.UUID; - } - - public void Add(ScenePresence pres) - { - m_pres_by_uuid[pres.UUID] = pres; - } - - public SceneObjectGroup RemoveObject(UUID uuid) - { - SceneObjectGroup sog = null; - try - { - sog = (SceneObjectGroup)m_obj_by_uuid[uuid]; - m_obj_by_uuid.Remove(uuid); - m_obj_by_local.Remove(sog.LocalId); - } - catch (Exception e) - { - m_log.ErrorFormat("RemoveObject failed for {0}", uuid, e); - sog = null; - } - return sog; - } - - public ScenePresence RemovePresence(UUID uuid) - { - ScenePresence sp = null; - try - { - sp = (ScenePresence)m_pres_by_uuid[uuid]; - m_pres_by_uuid.Remove(uuid); - } - catch (Exception e) - { - m_log.ErrorFormat("RemovePresence failed for {0}", uuid, e); - sp = null; - } - return sp; - } - - public SceneObjectGroup FindObject(UUID uuid) - { - try - { - SceneObjectGroup sog = (SceneObjectGroup)m_obj_by_uuid[uuid]; - return sog; - } - catch (Exception e) - { - m_log.ErrorFormat("FindObject failed for {0}", uuid, e); - return null; - } - } - - public SceneObjectGroup FindObject(uint local) - { - try - { - UUID uuid = (UUID)m_obj_by_local[local]; - SceneObjectGroup sog = (SceneObjectGroup)m_obj_by_uuid[uuid]; - return sog; - } - catch (Exception e) - { - m_log.ErrorFormat("FindObject failed for {0}", local, e); - return null; - } - } - - public ScenePresence FindPresense(UUID uuid) - { - try - { - ScenePresence sp = (ScenePresence)m_pres_by_uuid[uuid]; - return sp; - } - catch (Exception) - { - return null; - } - } - } -} diff --git a/OpenSim/Region/Environment/Scenes/EntityManager.cs b/OpenSim/Region/Environment/Scenes/EntityManager.cs index 25f73b4b35..e7592fe9c9 100644 --- a/OpenSim/Region/Environment/Scenes/EntityManager.cs +++ b/OpenSim/Region/Environment/Scenes/EntityManager.cs @@ -28,14 +28,19 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using log4net; using OpenMetaverse; + namespace OpenSim.Region.Environment.Scenes { public class EntityManager : IEnumerable { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly Dictionary m_eb_uuid = new Dictionary(); private readonly Dictionary m_eb_localID = new Dictionary(); + private readonly Dictionary m_pres_uuid = new Dictionary(); private readonly Object m_lock = new Object(); [Obsolete("Use Add() instead.")] @@ -48,8 +53,15 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - m_eb_uuid.Add(entity.UUID, entity); - m_eb_localID.Add(entity.LocalId, entity); + try + { + m_eb_uuid.Add(entity.UUID, entity); + m_eb_localID.Add(entity.LocalId, entity); + } + catch(Exception e) + { + m_log.ErrorFormat("Add Entity failed: ", e); + } } } @@ -57,8 +69,15 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - m_eb_uuid[entity.UUID] = entity; - m_eb_localID[entity.LocalId] = entity; + try + { + m_eb_uuid[entity.UUID] = entity; + m_eb_localID[entity.LocalId] = entity; + } + catch(Exception e) + { + m_log.ErrorFormat("Insert or Replace Entity failed: ", e); + } } } @@ -86,7 +105,14 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - return m_eb_uuid.ContainsKey(id); + try + { + return m_eb_uuid.ContainsKey(id); + } + catch + { + return false; + } } } @@ -94,7 +120,14 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - return m_eb_localID.ContainsKey(localID); + try + { + return m_eb_localID.ContainsKey(localID); + } + catch + { + return false; + } } } @@ -102,10 +135,17 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID); - bool b = m_eb_localID.Remove(localID); - - return a && b; + try + { + bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID); + bool b = m_eb_localID.Remove(localID); + return a && b; + } + catch (Exception e) + { + m_log.ErrorFormat("Remove Entity failed for {0}", localID, e); + return false; + } } } @@ -113,10 +153,17 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId); - bool b = m_eb_uuid.Remove(id); - - return a && b; + try + { + bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId); + bool b = m_eb_uuid.Remove(id); + return a && b; + } + catch (Exception e) + { + m_log.ErrorFormat("Remove Entity failed for {0}", id, e); + return false; + } } } @@ -126,13 +173,21 @@ namespace OpenSim.Region.Environment.Scenes lock (m_lock) { - foreach (KeyValuePair pair in m_eb_uuid) + try { - if (pair.Value is T) + foreach (KeyValuePair pair in m_eb_uuid) { - tmp.Add(pair.Value); + if (pair.Value is T) + { + tmp.Add(pair.Value); + } } } + catch (Exception e) + { + m_log.ErrorFormat("GetAllByType failed for {0}", e); + tmp = null; + } } return tmp; @@ -152,7 +207,14 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - return m_eb_uuid[id]; + try + { + return m_eb_uuid[id]; + } + catch + { + return null; + } } } set @@ -167,7 +229,14 @@ namespace OpenSim.Region.Environment.Scenes { lock (m_lock) { - return m_eb_localID[localID]; + try + { + return m_eb_localID[localID]; + } + catch + { + return null; + } } } set @@ -205,5 +274,6 @@ namespace OpenSim.Region.Environment.Scenes { return GetEnumerator(); } + } } diff --git a/OpenSim/Region/Environment/Scenes/Tests/EntityListTests.cs b/OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs similarity index 51% rename from OpenSim/Region/Environment/Scenes/Tests/EntityListTests.cs rename to OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs index 405eddd81c..5923a2cc95 100644 --- a/OpenSim/Region/Environment/Scenes/Tests/EntityListTests.cs +++ b/OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs @@ -32,11 +32,10 @@ using System.Text; using System.Collections.Generic; using Nini.Config; using NUnit.Framework; -using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Region.Environment.Scenes; -using OpenSim.Tests.Common.Mock; +using OpenMetaverse; namespace OpenSim.Region.Environment.Scenes.Tests { @@ -44,7 +43,7 @@ namespace OpenSim.Region.Environment.Scenes.Tests /// Scene oriented tests /// [TestFixture] - public class EntityListTests + public class EntityManagerTests { static public Random random; SceneObjectGroup found; @@ -55,116 +54,72 @@ namespace OpenSim.Region.Environment.Scenes.Tests { random = new Random(); SceneObjectGroup found; - EntityList entlist = new EntityList(); + EntityManager entman = new EntityManager(); SceneObjectGroup sog = NewSOG(); UUID obj1 = sog.UUID; uint li1 = sog.LocalId; - entlist.Add(sog); + entman.Add(sog); sog = NewSOG(); UUID obj2 = sog.UUID; uint li2 = sog.LocalId; - entlist.Add(sog); - - found = entlist.FindObject(obj1); + entman.Add(sog); + + found = (SceneObjectGroup)entman[obj1]; Assert.That(found.UUID ,Is.EqualTo(obj1) ); - found = entlist.FindObject(li1); + found = (SceneObjectGroup)entman[li1]; Assert.That(found.UUID ,Is.EqualTo(obj1) ); - found = entlist.FindObject(obj2); + found = (SceneObjectGroup)entman[obj2]; Assert.That(found.UUID ,Is.EqualTo(obj2) ); - found = entlist.FindObject(li2); + found = (SceneObjectGroup)entman[li2]; Assert.That(found.UUID ,Is.EqualTo(obj2) ); - entlist.RemoveObject(obj1); - entlist.RemoveObject(obj2); + entman.Remove(obj1); + entman.Remove(li2); - found = entlist.FindObject(obj1); - Assert.That(found, Is.Null); - found = entlist.FindObject(obj2); - Assert.That(found, Is.Null); + Assert.That(entman.ContainsKey(obj1), Is.False); + Assert.That(entman.ContainsKey(li1), Is.False); + Assert.That(entman.ContainsKey(obj2), Is.False); + Assert.That(entman.ContainsKey(li2), Is.False); } [Test] public void T011_ThreadAddRemoveTest() { - EntityList entlist = new EntityList(); - Dictionary dict = new Dictionary(); - List trdlist = new List(); - for (int i=0; i<80; i++) + // This test adds and removes with mutiple threads, attempting to break the + // uuid and localid dictionary coherence. + EntityManager entman = new EntityManager(); + SceneObjectGroup sog = NewSOG(); + for (int j=0; j<20; j++) { - SceneObjectGroup sog = NewSOG(); - TestThreads test = new TestThreads(entlist,sog); - Thread start = new Thread(new ThreadStart(test.TestAddSceneObject)); - start.Start(); - trdlist.Add(start); - dict.Add(sog.UUID, sog.LocalId); - } - foreach (Thread thread in trdlist) - { - thread.Join(); - } - foreach (KeyValuePair item in dict) - { - found = entlist.FindObject(item.Key); - Assert.That(found.UUID,Is.EqualTo(item.Key)); - found = entlist.FindObject(item.Value); - Assert.That(found.UUID,Is.EqualTo(item.Key)); + List trdlist = new List(); - // Start Removing - TestThreads test = new TestThreads(entlist,found); - Thread start = new Thread(new ThreadStart(test.TestRemoveSceneObject)); - start.Start(); - trdlist.Add(start); - } - foreach (Thread thread in trdlist) - { - thread.Join(); - } - foreach (KeyValuePair item in dict) - { - found = entlist.FindObject(item.Key); - Assert.That(found,Is.Null); - found = entlist.FindObject(item.Value); - Assert.That(found,Is.Null); - } - } - - [Test] - public void T012_MultipleUUIDEntry() - { - EntityList entlist = new EntityList(); - UUID id = UUID.Random(); - //int exceptions = 0; - //Dictionary dict = new Dictionary(); - List trdlist = new List(); - SceneObjectGroup sog = NewSOG(id); - uint lid = sog.LocalId; - for (int i=0; i<30; i++) - { - try + for (int i=0; i<4; i++) { - TestThreads test = new TestThreads(entlist,sog); + // Adds scene object + NewTestThreads test = new NewTestThreads(entman,sog); Thread start = new Thread(new ThreadStart(test.TestAddSceneObject)); start.Start(); trdlist.Add(start); + + // Removes it + test = new NewTestThreads(entman,sog); + start = new Thread(new ThreadStart(test.TestRemoveSceneObject)); + start.Start(); + trdlist.Add(start); } - catch + foreach (Thread thread in trdlist) { + thread.Join(); + } + if (entman.ContainsKey(sog.UUID) || entman.ContainsKey(sog.LocalId)) { + found = (SceneObjectGroup)entman[sog.UUID]; + Assert.That(found.UUID,Is.EqualTo(sog.UUID)); + found = (SceneObjectGroup)entman[sog.LocalId]; + Assert.That(found.UUID,Is.EqualTo(sog.UUID)); } } - foreach (Thread thread in trdlist) - { - thread.Join(); - } - found = entlist.FindObject(sog.UUID); - Assert.That(found.UUID,Is.EqualTo(sog.UUID)); - found = entlist.FindObject(lid); - Assert.That(found.UUID,Is.EqualTo(sog.UUID)); - - entlist.RemoveObject(id); - found = entlist.FindObject(id); - Assert.That(found,Is.Null); } - + private SceneObjectGroup NewSOG() { SceneObjectGroup sog = new SceneObjectGroup(); @@ -182,26 +137,7 @@ namespace OpenSim.Region.Environment.Scenes.Tests return sog; } - - private SceneObjectGroup NewSOG(UUID id) - { - SceneObjectGroup sog = new SceneObjectGroup(); - SceneObjectPart sop = new SceneObjectPart(UUID.Random(), PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); - sop.UUID = id; - sop.Name = RandomName(); - sop.Description = sop.Name; - sop.Text = RandomName(); - sop.SitName = RandomName(); - sop.TouchName = RandomName(); - sop.ObjectFlags |= (uint)PrimFlags.Phantom; - - sog.SetRootPart(sop); - - scene.AddNewSceneObject(sog, false); - - return sog; - } - + private static string RandomName() { StringBuilder name = new StringBuilder(); @@ -216,23 +152,27 @@ namespace OpenSim.Region.Environment.Scenes.Tests } } - public class TestThreads + public class NewTestThreads { - private EntityList entlist; + private EntityManager entman; private SceneObjectGroup sog; + private Random random; - public TestThreads(EntityList entlist, SceneObjectGroup sog) + public NewTestThreads(EntityManager entman, SceneObjectGroup sog) { - this.entlist = entlist; + this.entman = entman; this.sog = sog; + this.random = new Random(); } public void TestAddSceneObject() { - entlist.Add(sog); + Thread.Sleep(random.Next(0,50)); + entman.Add(sog); } public void TestRemoveSceneObject() { - entlist.RemoveObject(sog.UUID); + Thread.Sleep(random.Next(0,50)); + entman.Remove(sog.UUID); } } } \ No newline at end of file