aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Environment/Scenes/EntityList.cs161
-rw-r--r--OpenSim/Region/Environment/Scenes/EntityManager.cs108
-rw-r--r--OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs (renamed from OpenSim/Region/Environment/Scenes/Tests/EntityListTests.cs)162
3 files changed, 140 insertions, 291 deletions
diff --git a/OpenSim/Region/Environment/Scenes/EntityList.cs b/OpenSim/Region/Environment/Scenes/EntityList.cs
deleted file mode 100644
index 2488ab3..0000000
--- a/OpenSim/Region/Environment/Scenes/EntityList.cs
+++ /dev/null
@@ -1,161 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenMetaverse;
33using OpenMetaverse.Packets;
34using log4net;
35using OpenSim.Framework;
36using OpenSim.Region.Environment.Types;
37using OpenSim.Region.Physics.Manager;
38
39namespace OpenSim.Region.Environment.Scenes
40{
41 public class EntityList
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 // we are intentionally using non generics here as testing has
46 // shown synchronized collections are faster than manually
47 // locked generics.
48
49 private Hashtable m_obj_by_uuid;
50 private Hashtable m_obj_by_local;
51
52 private Hashtable m_pres_by_uuid;
53
54 public EntityList()
55 {
56 m_obj_by_uuid = Hashtable.Synchronized(new Hashtable());
57 m_obj_by_local = Hashtable.Synchronized(new Hashtable());
58 m_pres_by_uuid = Hashtable.Synchronized(new Hashtable());
59 }
60
61 // Interface definition
62 //
63 // Add(SOG)
64 // Add(SP)
65 // RemoveObject(SOG)
66 // RemovePresence(SP)
67 // List()
68 // ListObjects()
69 // ListPresenes()
70 // RemoveAll()
71 // FindObject(UUID)
72 // FindObject(int)
73 // FindPresence(UUID)
74
75 public void Add(SceneObjectGroup obj)
76 {
77 m_obj_by_uuid[obj.UUID] = obj;
78 m_obj_by_local[obj.LocalId] = obj.UUID;
79 }
80
81 public void Add(ScenePresence pres)
82 {
83 m_pres_by_uuid[pres.UUID] = pres;
84 }
85
86 public SceneObjectGroup RemoveObject(UUID uuid)
87 {
88 SceneObjectGroup sog = null;
89 try
90 {
91 sog = (SceneObjectGroup)m_obj_by_uuid[uuid];
92 m_obj_by_uuid.Remove(uuid);
93 m_obj_by_local.Remove(sog.LocalId);
94 }
95 catch (Exception e)
96 {
97 m_log.ErrorFormat("RemoveObject failed for {0}", uuid, e);
98 sog = null;
99 }
100 return sog;
101 }
102
103 public ScenePresence RemovePresence(UUID uuid)
104 {
105 ScenePresence sp = null;
106 try
107 {
108 sp = (ScenePresence)m_pres_by_uuid[uuid];
109 m_pres_by_uuid.Remove(uuid);
110 }
111 catch (Exception e)
112 {
113 m_log.ErrorFormat("RemovePresence failed for {0}", uuid, e);
114 sp = null;
115 }
116 return sp;
117 }
118
119 public SceneObjectGroup FindObject(UUID uuid)
120 {
121 try
122 {
123 SceneObjectGroup sog = (SceneObjectGroup)m_obj_by_uuid[uuid];
124 return sog;
125 }
126 catch (Exception e)
127 {
128 m_log.ErrorFormat("FindObject failed for {0}", uuid, e);
129 return null;
130 }
131 }
132
133 public SceneObjectGroup FindObject(uint local)
134 {
135 try
136 {
137 UUID uuid = (UUID)m_obj_by_local[local];
138 SceneObjectGroup sog = (SceneObjectGroup)m_obj_by_uuid[uuid];
139 return sog;
140 }
141 catch (Exception e)
142 {
143 m_log.ErrorFormat("FindObject failed for {0}", local, e);
144 return null;
145 }
146 }
147
148 public ScenePresence FindPresense(UUID uuid)
149 {
150 try
151 {
152 ScenePresence sp = (ScenePresence)m_pres_by_uuid[uuid];
153 return sp;
154 }
155 catch (Exception)
156 {
157 return null;
158 }
159 }
160 }
161}
diff --git a/OpenSim/Region/Environment/Scenes/EntityManager.cs b/OpenSim/Region/Environment/Scenes/EntityManager.cs
index 25f73b4..e7592fe 100644
--- a/OpenSim/Region/Environment/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Environment/Scenes/EntityManager.cs
@@ -28,14 +28,19 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
31using OpenMetaverse; 33using OpenMetaverse;
32 34
35
33namespace OpenSim.Region.Environment.Scenes 36namespace OpenSim.Region.Environment.Scenes
34{ 37{
35 public class EntityManager : IEnumerable<EntityBase> 38 public class EntityManager : IEnumerable<EntityBase>
36 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
37 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>(); 41 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>();
38 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>(); 42 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>();
43 private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>();
39 private readonly Object m_lock = new Object(); 44 private readonly Object m_lock = new Object();
40 45
41 [Obsolete("Use Add() instead.")] 46 [Obsolete("Use Add() instead.")]
@@ -48,8 +53,15 @@ namespace OpenSim.Region.Environment.Scenes
48 { 53 {
49 lock (m_lock) 54 lock (m_lock)
50 { 55 {
51 m_eb_uuid.Add(entity.UUID, entity); 56 try
52 m_eb_localID.Add(entity.LocalId, entity); 57 {
58 m_eb_uuid.Add(entity.UUID, entity);
59 m_eb_localID.Add(entity.LocalId, entity);
60 }
61 catch(Exception e)
62 {
63 m_log.ErrorFormat("Add Entity failed: ", e);
64 }
53 } 65 }
54 } 66 }
55 67
@@ -57,8 +69,15 @@ namespace OpenSim.Region.Environment.Scenes
57 { 69 {
58 lock (m_lock) 70 lock (m_lock)
59 { 71 {
60 m_eb_uuid[entity.UUID] = entity; 72 try
61 m_eb_localID[entity.LocalId] = entity; 73 {
74 m_eb_uuid[entity.UUID] = entity;
75 m_eb_localID[entity.LocalId] = entity;
76 }
77 catch(Exception e)
78 {
79 m_log.ErrorFormat("Insert or Replace Entity failed: ", e);
80 }
62 } 81 }
63 } 82 }
64 83
@@ -86,7 +105,14 @@ namespace OpenSim.Region.Environment.Scenes
86 { 105 {
87 lock (m_lock) 106 lock (m_lock)
88 { 107 {
89 return m_eb_uuid.ContainsKey(id); 108 try
109 {
110 return m_eb_uuid.ContainsKey(id);
111 }
112 catch
113 {
114 return false;
115 }
90 } 116 }
91 } 117 }
92 118
@@ -94,7 +120,14 @@ namespace OpenSim.Region.Environment.Scenes
94 { 120 {
95 lock (m_lock) 121 lock (m_lock)
96 { 122 {
97 return m_eb_localID.ContainsKey(localID); 123 try
124 {
125 return m_eb_localID.ContainsKey(localID);
126 }
127 catch
128 {
129 return false;
130 }
98 } 131 }
99 } 132 }
100 133
@@ -102,10 +135,17 @@ namespace OpenSim.Region.Environment.Scenes
102 { 135 {
103 lock (m_lock) 136 lock (m_lock)
104 { 137 {
105 bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID); 138 try
106 bool b = m_eb_localID.Remove(localID); 139 {
107 140 bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID);
108 return a && b; 141 bool b = m_eb_localID.Remove(localID);
142 return a && b;
143 }
144 catch (Exception e)
145 {
146 m_log.ErrorFormat("Remove Entity failed for {0}", localID, e);
147 return false;
148 }
109 } 149 }
110 } 150 }
111 151
@@ -113,10 +153,17 @@ namespace OpenSim.Region.Environment.Scenes
113 { 153 {
114 lock (m_lock) 154 lock (m_lock)
115 { 155 {
116 bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId); 156 try
117 bool b = m_eb_uuid.Remove(id); 157 {
118 158 bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId);
119 return a && b; 159 bool b = m_eb_uuid.Remove(id);
160 return a && b;
161 }
162 catch (Exception e)
163 {
164 m_log.ErrorFormat("Remove Entity failed for {0}", id, e);
165 return false;
166 }
120 } 167 }
121 } 168 }
122 169
@@ -126,13 +173,21 @@ namespace OpenSim.Region.Environment.Scenes
126 173
127 lock (m_lock) 174 lock (m_lock)
128 { 175 {
129 foreach (KeyValuePair<UUID, EntityBase> pair in m_eb_uuid) 176 try
130 { 177 {
131 if (pair.Value is T) 178 foreach (KeyValuePair<UUID, EntityBase> pair in m_eb_uuid)
132 { 179 {
133 tmp.Add(pair.Value); 180 if (pair.Value is T)
181 {
182 tmp.Add(pair.Value);
183 }
134 } 184 }
135 } 185 }
186 catch (Exception e)
187 {
188 m_log.ErrorFormat("GetAllByType failed for {0}", e);
189 tmp = null;
190 }
136 } 191 }
137 192
138 return tmp; 193 return tmp;
@@ -152,7 +207,14 @@ namespace OpenSim.Region.Environment.Scenes
152 { 207 {
153 lock (m_lock) 208 lock (m_lock)
154 { 209 {
155 return m_eb_uuid[id]; 210 try
211 {
212 return m_eb_uuid[id];
213 }
214 catch
215 {
216 return null;
217 }
156 } 218 }
157 } 219 }
158 set 220 set
@@ -167,7 +229,14 @@ namespace OpenSim.Region.Environment.Scenes
167 { 229 {
168 lock (m_lock) 230 lock (m_lock)
169 { 231 {
170 return m_eb_localID[localID]; 232 try
233 {
234 return m_eb_localID[localID];
235 }
236 catch
237 {
238 return null;
239 }
171 } 240 }
172 } 241 }
173 set 242 set
@@ -205,5 +274,6 @@ namespace OpenSim.Region.Environment.Scenes
205 { 274 {
206 return GetEnumerator(); 275 return GetEnumerator();
207 } 276 }
277
208 } 278 }
209} 279}
diff --git a/OpenSim/Region/Environment/Scenes/Tests/EntityListTests.cs b/OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs
index 405eddd..5923a2c 100644
--- a/OpenSim/Region/Environment/Scenes/Tests/EntityListTests.cs
+++ b/OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs
@@ -32,11 +32,10 @@ using System.Text;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using Nini.Config; 33using Nini.Config;
34using NUnit.Framework; 34using NUnit.Framework;
35using OpenMetaverse;
36using OpenSim.Framework; 35using OpenSim.Framework;
37using OpenSim.Framework.Communications; 36using OpenSim.Framework.Communications;
38using OpenSim.Region.Environment.Scenes; 37using OpenSim.Region.Environment.Scenes;
39using OpenSim.Tests.Common.Mock; 38using OpenMetaverse;
40 39
41namespace OpenSim.Region.Environment.Scenes.Tests 40namespace OpenSim.Region.Environment.Scenes.Tests
42{ 41{
@@ -44,7 +43,7 @@ namespace OpenSim.Region.Environment.Scenes.Tests
44 /// Scene oriented tests 43 /// Scene oriented tests
45 /// </summary> 44 /// </summary>
46 [TestFixture] 45 [TestFixture]
47 public class EntityListTests 46 public class EntityManagerTests
48 { 47 {
49 static public Random random; 48 static public Random random;
50 SceneObjectGroup found; 49 SceneObjectGroup found;
@@ -55,116 +54,72 @@ namespace OpenSim.Region.Environment.Scenes.Tests
55 { 54 {
56 random = new Random(); 55 random = new Random();
57 SceneObjectGroup found; 56 SceneObjectGroup found;
58 EntityList entlist = new EntityList(); 57 EntityManager entman = new EntityManager();
59 SceneObjectGroup sog = NewSOG(); 58 SceneObjectGroup sog = NewSOG();
60 UUID obj1 = sog.UUID; 59 UUID obj1 = sog.UUID;
61 uint li1 = sog.LocalId; 60 uint li1 = sog.LocalId;
62 entlist.Add(sog); 61 entman.Add(sog);
63 sog = NewSOG(); 62 sog = NewSOG();
64 UUID obj2 = sog.UUID; 63 UUID obj2 = sog.UUID;
65 uint li2 = sog.LocalId; 64 uint li2 = sog.LocalId;
66 entlist.Add(sog); 65 entman.Add(sog);
67 66
68 found = entlist.FindObject(obj1); 67 found = (SceneObjectGroup)entman[obj1];
69 Assert.That(found.UUID ,Is.EqualTo(obj1) ); 68 Assert.That(found.UUID ,Is.EqualTo(obj1) );
70 found = entlist.FindObject(li1); 69 found = (SceneObjectGroup)entman[li1];
71 Assert.That(found.UUID ,Is.EqualTo(obj1) ); 70 Assert.That(found.UUID ,Is.EqualTo(obj1) );
72 found = entlist.FindObject(obj2); 71 found = (SceneObjectGroup)entman[obj2];
73 Assert.That(found.UUID ,Is.EqualTo(obj2) ); 72 Assert.That(found.UUID ,Is.EqualTo(obj2) );
74 found = entlist.FindObject(li2); 73 found = (SceneObjectGroup)entman[li2];
75 Assert.That(found.UUID ,Is.EqualTo(obj2) ); 74 Assert.That(found.UUID ,Is.EqualTo(obj2) );
76 75
77 entlist.RemoveObject(obj1); 76 entman.Remove(obj1);
78 entlist.RemoveObject(obj2); 77 entman.Remove(li2);
79 78
80 found = entlist.FindObject(obj1); 79 Assert.That(entman.ContainsKey(obj1), Is.False);
81 Assert.That(found, Is.Null); 80 Assert.That(entman.ContainsKey(li1), Is.False);
82 found = entlist.FindObject(obj2); 81 Assert.That(entman.ContainsKey(obj2), Is.False);
83 Assert.That(found, Is.Null); 82 Assert.That(entman.ContainsKey(li2), Is.False);
84 } 83 }
85 84
86 [Test] 85 [Test]
87 public void T011_ThreadAddRemoveTest() 86 public void T011_ThreadAddRemoveTest()
88 { 87 {
89 EntityList entlist = new EntityList(); 88 // This test adds and removes with mutiple threads, attempting to break the
90 Dictionary<UUID, uint> dict = new Dictionary<UUID,uint>(); 89 // uuid and localid dictionary coherence.
91 List<Thread> trdlist = new List<Thread>(); 90 EntityManager entman = new EntityManager();
92 for (int i=0; i<80; i++) 91 SceneObjectGroup sog = NewSOG();
93 { 92 for (int j=0; j<20; j++)
94 SceneObjectGroup sog = NewSOG();
95 TestThreads test = new TestThreads(entlist,sog);
96 Thread start = new Thread(new ThreadStart(test.TestAddSceneObject));
97 start.Start();
98 trdlist.Add(start);
99 dict.Add(sog.UUID, sog.LocalId);
100 }
101 foreach (Thread thread in trdlist)
102 {
103 thread.Join();
104 }
105 foreach (KeyValuePair<UUID, uint> item in dict)
106 { 93 {
107 found = entlist.FindObject(item.Key); 94 List<Thread> trdlist = new List<Thread>();
108 Assert.That(found.UUID,Is.EqualTo(item.Key));
109 found = entlist.FindObject(item.Value);
110 Assert.That(found.UUID,Is.EqualTo(item.Key));
111 95
112 // Start Removing 96 for (int i=0; i<4; i++)
113 TestThreads test = new TestThreads(entlist,found);
114 Thread start = new Thread(new ThreadStart(test.TestRemoveSceneObject));
115 start.Start();
116 trdlist.Add(start);
117 }
118 foreach (Thread thread in trdlist)
119 {
120 thread.Join();
121 }
122 foreach (KeyValuePair<UUID, uint> item in dict)
123 {
124 found = entlist.FindObject(item.Key);
125 Assert.That(found,Is.Null);
126 found = entlist.FindObject(item.Value);
127 Assert.That(found,Is.Null);
128 }
129 }
130
131 [Test]
132 public void T012_MultipleUUIDEntry()
133 {
134 EntityList entlist = new EntityList();
135 UUID id = UUID.Random();
136 //int exceptions = 0;
137 //Dictionary<UUID, uint> dict = new Dictionary<UUID,uint>();
138 List<Thread> trdlist = new List<Thread>();
139 SceneObjectGroup sog = NewSOG(id);
140 uint lid = sog.LocalId;
141 for (int i=0; i<30; i++)
142 {
143 try
144 { 97 {
145 TestThreads test = new TestThreads(entlist,sog); 98 // Adds scene object
99 NewTestThreads test = new NewTestThreads(entman,sog);
146 Thread start = new Thread(new ThreadStart(test.TestAddSceneObject)); 100 Thread start = new Thread(new ThreadStart(test.TestAddSceneObject));
147 start.Start(); 101 start.Start();
148 trdlist.Add(start); 102 trdlist.Add(start);
103
104 // Removes it
105 test = new NewTestThreads(entman,sog);
106 start = new Thread(new ThreadStart(test.TestRemoveSceneObject));
107 start.Start();
108 trdlist.Add(start);
149 } 109 }
150 catch 110 foreach (Thread thread in trdlist)
151 { 111 {
112 thread.Join();
113 }
114 if (entman.ContainsKey(sog.UUID) || entman.ContainsKey(sog.LocalId)) {
115 found = (SceneObjectGroup)entman[sog.UUID];
116 Assert.That(found.UUID,Is.EqualTo(sog.UUID));
117 found = (SceneObjectGroup)entman[sog.LocalId];
118 Assert.That(found.UUID,Is.EqualTo(sog.UUID));
152 } 119 }
153 } 120 }
154 foreach (Thread thread in trdlist)
155 {
156 thread.Join();
157 }
158 found = entlist.FindObject(sog.UUID);
159 Assert.That(found.UUID,Is.EqualTo(sog.UUID));
160 found = entlist.FindObject(lid);
161 Assert.That(found.UUID,Is.EqualTo(sog.UUID));
162
163 entlist.RemoveObject(id);
164 found = entlist.FindObject(id);
165 Assert.That(found,Is.Null);
166 } 121 }
167 122
168 private SceneObjectGroup NewSOG() 123 private SceneObjectGroup NewSOG()
169 { 124 {
170 SceneObjectGroup sog = new SceneObjectGroup(); 125 SceneObjectGroup sog = new SceneObjectGroup();
@@ -182,26 +137,7 @@ namespace OpenSim.Region.Environment.Scenes.Tests
182 137
183 return sog; 138 return sog;
184 } 139 }
185 140
186 private SceneObjectGroup NewSOG(UUID id)
187 {
188 SceneObjectGroup sog = new SceneObjectGroup();
189 SceneObjectPart sop = new SceneObjectPart(UUID.Random(), PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero);
190 sop.UUID = id;
191 sop.Name = RandomName();
192 sop.Description = sop.Name;
193 sop.Text = RandomName();
194 sop.SitName = RandomName();
195 sop.TouchName = RandomName();
196 sop.ObjectFlags |= (uint)PrimFlags.Phantom;
197
198 sog.SetRootPart(sop);
199
200 scene.AddNewSceneObject(sog, false);
201
202 return sog;
203 }
204
205 private static string RandomName() 141 private static string RandomName()
206 { 142 {
207 StringBuilder name = new StringBuilder(); 143 StringBuilder name = new StringBuilder();
@@ -216,23 +152,27 @@ namespace OpenSim.Region.Environment.Scenes.Tests
216 } 152 }
217 } 153 }
218 154
219 public class TestThreads 155 public class NewTestThreads
220 { 156 {
221 private EntityList entlist; 157 private EntityManager entman;
222 private SceneObjectGroup sog; 158 private SceneObjectGroup sog;
159 private Random random;
223 160
224 public TestThreads(EntityList entlist, SceneObjectGroup sog) 161 public NewTestThreads(EntityManager entman, SceneObjectGroup sog)
225 { 162 {
226 this.entlist = entlist; 163 this.entman = entman;
227 this.sog = sog; 164 this.sog = sog;
165 this.random = new Random();
228 } 166 }
229 public void TestAddSceneObject() 167 public void TestAddSceneObject()
230 { 168 {
231 entlist.Add(sog); 169 Thread.Sleep(random.Next(0,50));
170 entman.Add(sog);
232 } 171 }
233 public void TestRemoveSceneObject() 172 public void TestRemoveSceneObject()
234 { 173 {
235 entlist.RemoveObject(sog.UUID); 174 Thread.Sleep(random.Next(0,50));
175 entman.Remove(sog.UUID);
236 } 176 }
237 } 177 }
238} \ No newline at end of file 178} \ No newline at end of file