aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment
diff options
context:
space:
mode:
authorMW2008-02-14 16:38:38 +0000
committerMW2008-02-14 16:38:38 +0000
commit4616563cc47f1ed2bfa574e3d8d952a618bde3a6 (patch)
tree7ca024327c50962827742b39b2f8af2e168ab329 /OpenSim/Region/Environment
parent* Removed some catch-all-ignores from UDPServer in an attempt to look for #305. (diff)
downloadopensim-SC_OLD-4616563cc47f1ed2bfa574e3d8d952a618bde3a6.zip
opensim-SC_OLD-4616563cc47f1ed2bfa574e3d8d952a618bde3a6.tar.gz
opensim-SC_OLD-4616563cc47f1ed2bfa574e3d8d952a618bde3a6.tar.bz2
opensim-SC_OLD-4616563cc47f1ed2bfa574e3d8d952a618bde3a6.tar.xz
Added "better" multi thread handling to AvatarFactoryModule, which uses EventWaitHandles, I'm a bit concerned about what effect this might have on performance in a large grid. But I've spent long enough on this problem for one day and as its valentines day, I will be killed and tortured (most likely not in that order) if I don't stop work for the day soon.
Diffstat (limited to 'OpenSim/Region/Environment')
-rw-r--r--OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs143
1 files changed, 120 insertions, 23 deletions
diff --git a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs
index d7f23f8..7933593 100644
--- a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs
+++ b/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs
@@ -28,6 +28,7 @@
28 28
29using System; 29using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Threading;
31using libsecondlife; 32using libsecondlife;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -51,18 +52,118 @@ namespace OpenSim.Region.Environment.Modules
51 private BaseDatabaseConnector m_databaseMapper; 52 private BaseDatabaseConnector m_databaseMapper;
52 private AppearanceTableMapper m_appearanceMapper; 53 private AppearanceTableMapper m_appearanceMapper;
53 54
55 private Dictionary<LLUUID, EventWaitHandle> m_fetchesInProgress = new Dictionary<LLUUID, EventWaitHandle>();
56 private object m_syncLock = new object();
57
54 public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance) 58 public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
55 { 59 {
56 //check cache 60 appearance = CheckCache(avatarId);
57 lock (m_avatarsAppearance) 61 if (appearance != null)
58 { 62 {
59 if (m_avatarsAppearance.ContainsKey(avatarId)) 63 return true;
64 }
65
66 //not in cache so check to see if another thread is already fetching it
67 //should only let one thread at a time do this part
68 EventWaitHandle waitHandle = null;
69 lock (m_syncLock)
70 {
71 if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle))
60 { 72 {
61 appearance = m_avatarsAppearance[avatarId]; 73 waitHandle.WaitOne();
62 return true; 74 appearance = CheckCache(avatarId);
75 if (appearance != null)
76 {
77 waitHandle = null;
78 return true;
79 }
80 else
81 {
82 waitHandle = null;
83 return false;
84 }
85 }
86 else
87 {
88 //no thread already fetching this appearance, so add a wait handle to list
89 //for any following threads that want the same appearance
90 waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
91 m_fetchesInProgress.Add(avatarId, waitHandle);
63 } 92 }
64 } 93 }
65 94
95
96 //this is the first thread to request this appearance
97 //so let it check the db and if not found then create a default appearance
98 //and add that to the cache
99 appearance = CheckDatabase(avatarId);
100 if (appearance != null)
101 {
102 //appearance has now been added to cache so lets pulse any waiting threads
103 lock (m_syncLock)
104 {
105 m_fetchesInProgress.Remove(avatarId);
106 waitHandle.Set();
107 }
108 waitHandle = null;
109 return true;
110 }
111
112 //not found a appearance for the user, so create a new default one
113 appearance = CreateDefault(avatarId);
114 if (appearance != null)
115 {
116 //update database
117 if (m_enablePersist)
118 {
119 m_appearanceMapper.Add(avatarId.UUID, appearance);
120 }
121
122 //add appearance to dictionary cache
123 lock (m_avatarsAppearance)
124 {
125 m_avatarsAppearance[avatarId] = appearance;
126 }
127
128 //appearance has now been added to cache so lets pulse any waiting threads
129 lock (m_syncLock)
130 {
131 m_fetchesInProgress.Remove(avatarId);
132 waitHandle.Set();
133 }
134 waitHandle = null;
135 return true;
136 }
137 else
138 {
139 //something went wrong, so release the wait handle and remove it
140 //all waiting threads will fail to find cached appearance
141 //but its better for them to fail than wait for ever
142 lock (m_syncLock)
143 {
144 m_fetchesInProgress.Remove(avatarId);
145 waitHandle.Set();
146 }
147 waitHandle = null;
148 return false;
149 }
150
151 }
152
153 private AvatarAppearance CreateDefault(LLUUID avatarId)
154 {
155 AvatarAppearance appearance = null;
156 AvatarWearable[] wearables;
157 byte[] visualParams;
158 GetDefaultAvatarAppearance(out wearables, out visualParams);
159 appearance = new AvatarAppearance(avatarId, wearables, visualParams);
160
161 return appearance;
162 }
163
164 private AvatarAppearance CheckDatabase(LLUUID avatarId)
165 {
166 AvatarAppearance appearance = null;
66 //check db 167 //check db
67 if (m_enablePersist) 168 if (m_enablePersist)
68 { 169 {
@@ -74,28 +175,24 @@ namespace OpenSim.Region.Environment.Modules
74 { 175 {
75 m_avatarsAppearance[avatarId] = appearance; 176 m_avatarsAppearance[avatarId] = appearance;
76 } 177 }
77 return true;
78 } 178 }
79 } 179 }
180 return appearance;
181 }
80 182
81 //not found a appearance for the user, so create a new one 183 private AvatarAppearance CheckCache(LLUUID avatarId)
82 AvatarWearable[] wearables; 184 {
83 byte[] visualParams; 185 AvatarAppearance appearance = null;
84 GetDefaultAvatarAppearance(out wearables, out visualParams); 186 //check cache
85 appearance = new AvatarAppearance(avatarId, wearables, visualParams);
86
87 //add appearance to dictionary cache
88 lock (m_avatarsAppearance) 187 lock (m_avatarsAppearance)
89 { 188 {
90 m_avatarsAppearance[avatarId] = appearance; 189 if (m_avatarsAppearance.ContainsKey(avatarId))
91 } 190 {
92 191 appearance = m_avatarsAppearance[avatarId];
93 //update database 192 // return true;
94 if (m_enablePersist) 193 }
95 {
96 m_appearanceMapper.Add(avatarId.UUID, appearance);
97 } 194 }
98 return true; 195 return appearance;
99 } 196 }
100 197
101 public void Initialise(Scene scene, IConfigSource source) 198 public void Initialise(Scene scene, IConfigSource source)
@@ -175,11 +272,11 @@ namespace OpenSim.Region.Environment.Modules
175 if (baseItem != null) 272 if (baseItem != null)
176 { 273 {
177 assetId = baseItem.assetID; 274 assetId = baseItem.assetID;
178 275
179 if (m_avatarsAppearance.ContainsKey(clientView.AgentId)) 276 if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
180 { 277 {
181 AvatarAppearance avatAppearance = null; 278 AvatarAppearance avatAppearance = null;
182 279
183 lock (m_avatarsAppearance) 280 lock (m_avatarsAppearance)
184 { 281 {
185 avatAppearance = m_avatarsAppearance[clientView.AgentId]; 282 avatAppearance = m_avatarsAppearance[clientView.AgentId];