diff options
Diffstat (limited to '')
4 files changed, 101 insertions, 23 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 8d503bd..c7f4c20 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -111,6 +111,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
111 | 111 | ||
112 | #region IAvatarFactoryModule | 112 | #region IAvatarFactoryModule |
113 | 113 | ||
114 | /// </summary> | ||
115 | /// <param name="sp"></param> | ||
116 | /// <param name="texture"></param> | ||
117 | /// <param name="visualParam"></param> | ||
118 | public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) | ||
119 | { | ||
120 | SetAppearance(sp, appearance.Texture, appearance.VisualParams); | ||
121 | } | ||
122 | |||
114 | /// <summary> | 123 | /// <summary> |
115 | /// Set appearance data (texture asset IDs and slider settings) | 124 | /// Set appearance data (texture asset IDs and slider settings) |
116 | /// </summary> | 125 | /// </summary> |
@@ -156,14 +165,23 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
156 | changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; | 165 | changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; |
157 | 166 | ||
158 | // WriteBakedTexturesReport(sp, m_log.DebugFormat); | 167 | // WriteBakedTexturesReport(sp, m_log.DebugFormat); |
159 | if (!ValidateBakedTextureCache(sp)) | 168 | |
169 | // If bake textures are missing and this is not an NPC, request a rebake from client | ||
170 | if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) | ||
160 | RequestRebake(sp, true); | 171 | RequestRebake(sp, true); |
161 | 172 | ||
162 | // This appears to be set only in the final stage of the appearance | 173 | // This appears to be set only in the final stage of the appearance |
163 | // update transaction. In theory, we should be able to do an immediate | 174 | // update transaction. In theory, we should be able to do an immediate |
164 | // appearance send and save here. | 175 | // appearance send and save here. |
165 | } | 176 | } |
166 | 177 | ||
178 | // NPC should send to clients immediately and skip saving appearance | ||
179 | if (((ScenePresence)sp).PresenceType == PresenceType.Npc) | ||
180 | { | ||
181 | SendAppearance((ScenePresence)sp); | ||
182 | return; | ||
183 | } | ||
184 | |||
167 | // save only if there were changes, send no matter what (doesn't hurt to send twice) | 185 | // save only if there were changes, send no matter what (doesn't hurt to send twice) |
168 | if (changed) | 186 | if (changed) |
169 | QueueAppearanceSave(sp.ControllingClient.AgentId); | 187 | QueueAppearanceSave(sp.ControllingClient.AgentId); |
@@ -174,6 +192,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
174 | // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); | 192 | // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); |
175 | } | 193 | } |
176 | 194 | ||
195 | private void SendAppearance(ScenePresence sp) | ||
196 | { | ||
197 | // Send the appearance to everyone in the scene | ||
198 | sp.SendAppearanceToAllOtherAgents(); | ||
199 | |||
200 | // Send animations back to the avatar as well | ||
201 | sp.Animator.SendAnimPack(); | ||
202 | } | ||
203 | |||
177 | public bool SendAppearance(UUID agentId) | 204 | public bool SendAppearance(UUID agentId) |
178 | { | 205 | { |
179 | // m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId); | 206 | // m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId); |
@@ -185,12 +212,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
185 | return false; | 212 | return false; |
186 | } | 213 | } |
187 | 214 | ||
188 | // Send the appearance to everyone in the scene | 215 | SendAppearance(sp); |
189 | sp.SendAppearanceToAllOtherAgents(); | ||
190 | |||
191 | // Send animations back to the avatar as well | ||
192 | sp.Animator.SendAnimPack(); | ||
193 | |||
194 | return true; | 216 | return true; |
195 | } | 217 | } |
196 | 218 | ||
@@ -626,4 +648,4 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
626 | outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); | 648 | outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); |
627 | } | 649 | } |
628 | } | 650 | } |
629 | } \ No newline at end of file | 651 | } |
diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs index 39a760c..34aca33 100644 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs | |||
@@ -35,6 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
35 | 35 | ||
36 | public interface IAvatarFactoryModule | 36 | public interface IAvatarFactoryModule |
37 | { | 37 | { |
38 | void SetAppearance(IScenePresence sp, AvatarAppearance appearance); | ||
38 | void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams); | 39 | void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams); |
39 | 40 | ||
40 | /// <summary> | 41 | /// <summary> |
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index 42008da..130513d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs | |||
@@ -30,6 +30,7 @@ using System.Collections; | |||
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Collections.Specialized; | 31 | using System.Collections.Specialized; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | using System.Threading; | ||
33 | 34 | ||
34 | using Nwc.XmlRpc; | 35 | using Nwc.XmlRpc; |
35 | 36 | ||
@@ -167,6 +168,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
167 | 168 | ||
168 | private bool m_debugEnabled = false; | 169 | private bool m_debugEnabled = false; |
169 | 170 | ||
171 | private Dictionary<string, bool> m_pendingRequests = new Dictionary<string,bool>(); | ||
172 | |||
170 | private ExpiringCache<string, OSDMap> m_memoryCache; | 173 | private ExpiringCache<string, OSDMap> m_memoryCache; |
171 | private int m_cacheTimeout = 30; | 174 | private int m_cacheTimeout = 30; |
172 | 175 | ||
@@ -1348,6 +1351,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
1348 | // Immediately forward the request if the cache is disabled. | 1351 | // Immediately forward the request if the cache is disabled. |
1349 | if (m_cacheTimeout == 0) | 1352 | if (m_cacheTimeout == 0) |
1350 | { | 1353 | { |
1354 | m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: cache is disabled"); | ||
1351 | return WebUtil.PostToService(m_groupsServerURI, requestArgs); | 1355 | return WebUtil.PostToService(m_groupsServerURI, requestArgs); |
1352 | } | 1356 | } |
1353 | 1357 | ||
@@ -1355,6 +1359,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
1355 | if (requestArgs["RequestMethod"] == "RemoveGeneric" | 1359 | if (requestArgs["RequestMethod"] == "RemoveGeneric" |
1356 | || requestArgs["RequestMethod"] == "AddGeneric") | 1360 | || requestArgs["RequestMethod"] == "AddGeneric") |
1357 | { | 1361 | { |
1362 | m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: clearing generics cache"); | ||
1363 | |||
1358 | // Any and all updates cause the cache to clear | 1364 | // Any and all updates cause the cache to clear |
1359 | m_memoryCache.Clear(); | 1365 | m_memoryCache.Clear(); |
1360 | 1366 | ||
@@ -1366,18 +1372,67 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
1366 | 1372 | ||
1367 | // Create the cache key for the request and see if we have it cached | 1373 | // Create the cache key for the request and see if we have it cached |
1368 | string CacheKey = WebUtil.BuildQueryString(requestArgs); | 1374 | string CacheKey = WebUtil.BuildQueryString(requestArgs); |
1369 | OSDMap response = null; | 1375 | |
1370 | if (!m_memoryCache.TryGetValue(CacheKey, out response)) | 1376 | // This code uses a leader/follower pattern. On a cache miss, the request is added |
1377 | // to a queue; the first thread to add it to the queue completes the request while | ||
1378 | // follow on threads busy wait for the results, this situation seems to happen | ||
1379 | // often when checking permissions | ||
1380 | while (true) | ||
1371 | { | 1381 | { |
1372 | // if it wasn't in the cache, pass the request to the Simian Grid Services | 1382 | OSDMap response = null; |
1373 | response = WebUtil.PostToService(m_groupsServerURI, requestArgs); | 1383 | bool firstRequest = false; |
1374 | 1384 | ||
1375 | // and cache the response | 1385 | lock (m_memoryCache) |
1376 | m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout)); | 1386 | { |
1387 | if (m_memoryCache.TryGetValue(CacheKey, out response)) | ||
1388 | return response; | ||
1389 | |||
1390 | if (! m_pendingRequests.ContainsKey(CacheKey)) | ||
1391 | { | ||
1392 | m_pendingRequests.Add(CacheKey,true); | ||
1393 | firstRequest = true; | ||
1394 | } | ||
1395 | } | ||
1396 | |||
1397 | if (firstRequest) | ||
1398 | { | ||
1399 | // if it wasn't in the cache, pass the request to the Simian Grid Services | ||
1400 | try | ||
1401 | { | ||
1402 | response = WebUtil.PostToService(m_groupsServerURI, requestArgs); | ||
1403 | } | ||
1404 | catch (Exception e) | ||
1405 | { | ||
1406 | m_log.InfoFormat("[SIMIAN GROUPS CONNECTOR] request failed {0}",CacheKey); | ||
1407 | } | ||
1408 | |||
1409 | // and cache the response | ||
1410 | lock (m_memoryCache) | ||
1411 | { | ||
1412 | m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout)); | ||
1413 | m_pendingRequests.Remove(CacheKey); | ||
1414 | } | ||
1415 | |||
1416 | return response; | ||
1417 | } | ||
1418 | |||
1419 | Thread.Sleep(50); // waiting for a web request to complete, 50msecs is reasonable | ||
1377 | } | 1420 | } |
1378 | 1421 | ||
1379 | // return cached response | 1422 | // if (!m_memoryCache.TryGetValue(CacheKey, out response)) |
1380 | return response; | 1423 | // { |
1424 | // m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: query not in the cache"); | ||
1425 | // Util.PrintCallStack(); | ||
1426 | |||
1427 | // // if it wasn't in the cache, pass the request to the Simian Grid Services | ||
1428 | // response = WebUtil.PostToService(m_groupsServerURI, requestArgs); | ||
1429 | |||
1430 | // // and cache the response | ||
1431 | // m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout)); | ||
1432 | // } | ||
1433 | |||
1434 | // // return cached response | ||
1435 | // return response; | ||
1381 | } | 1436 | } |
1382 | #endregion | 1437 | #endregion |
1383 | 1438 | ||
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index dc6eefc..5359354 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs | |||
@@ -96,15 +96,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
96 | if (!m_avatars.ContainsKey(agentId)) | 96 | if (!m_avatars.ContainsKey(agentId)) |
97 | return false; | 97 | return false; |
98 | 98 | ||
99 | // Delete existing sp attachments | ||
99 | scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false); | 100 | scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false); |
100 | 101 | ||
101 | AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true); | 102 | // Set new sp appearance. Also sends to clients. |
102 | sp.Appearance = npcAppearance; | 103 | scene.RequestModuleInterface<IAvatarFactoryModule>().SetAppearance(sp, new AvatarAppearance(appearance, true)); |
104 | |||
105 | // Rez needed sp attachments | ||
103 | scene.AttachmentsModule.RezAttachments(sp); | 106 | scene.AttachmentsModule.RezAttachments(sp); |
104 | 107 | ||
105 | IAvatarFactoryModule module = scene.RequestModuleInterface<IAvatarFactoryModule>(); | ||
106 | module.SendAppearance(sp.UUID); | ||
107 | |||
108 | return true; | 108 | return true; |
109 | } | 109 | } |
110 | 110 | ||