diff options
Diffstat (limited to 'OpenSim/Region/CoreModules')
5 files changed, 177 insertions, 58 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs index 0d3cc23..937f76b 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs | |||
@@ -30,6 +30,7 @@ using System.Collections.Generic; | |||
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Text; | 32 | using System.Text; |
33 | using System.Threading; | ||
33 | using log4net; | 34 | using log4net; |
34 | using Nini.Config; | 35 | using Nini.Config; |
35 | using OpenMetaverse; | 36 | using OpenMetaverse; |
@@ -38,9 +39,12 @@ using OpenMetaverse.Imaging; | |||
38 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
39 | using OpenSim.Region.Framework.Interfaces; | 40 | using OpenSim.Region.Framework.Interfaces; |
40 | using OpenSim.Region.Framework.Scenes; | 41 | using OpenSim.Region.Framework.Scenes; |
42 | using OpenSim.Services.Interfaces; | ||
41 | 43 | ||
42 | namespace OpenSim.Region.CoreModules.Agent.TextureSender | 44 | namespace OpenSim.Region.CoreModules.Agent.TextureSender |
43 | { | 45 | { |
46 | public delegate void J2KDecodeDelegate(UUID AssetId); | ||
47 | |||
44 | public class J2KDecoderModule : IRegionModule, IJ2KDecoder | 48 | public class J2KDecoderModule : IRegionModule, IJ2KDecoder |
45 | { | 49 | { |
46 | #region IRegionModule Members | 50 | #region IRegionModule Members |
@@ -53,8 +57,12 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
53 | /// </summary> | 57 | /// </summary> |
54 | private readonly Dictionary<UUID, OpenJPEG.J2KLayerInfo[]> m_cacheddecode = new Dictionary<UUID, OpenJPEG.J2KLayerInfo[]>(); | 58 | private readonly Dictionary<UUID, OpenJPEG.J2KLayerInfo[]> m_cacheddecode = new Dictionary<UUID, OpenJPEG.J2KLayerInfo[]>(); |
55 | private bool OpenJpegFail = false; | 59 | private bool OpenJpegFail = false; |
56 | private readonly string CacheFolder = Util.dataDir() + "/j2kDecodeCache"; | 60 | private string CacheFolder = Util.dataDir() + "/j2kDecodeCache"; |
57 | private readonly J2KDecodeFileCache fCache; | 61 | private int CacheTimeout = 720; |
62 | private J2KDecodeFileCache fCache = null; | ||
63 | private Thread CleanerThread = null; | ||
64 | private IAssetService AssetService = null; | ||
65 | private Scene m_Scene = null; | ||
58 | 66 | ||
59 | /// <summary> | 67 | /// <summary> |
60 | /// List of client methods to notify of results of decode | 68 | /// List of client methods to notify of results of decode |
@@ -63,17 +71,37 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
63 | 71 | ||
64 | public J2KDecoderModule() | 72 | public J2KDecoderModule() |
65 | { | 73 | { |
66 | fCache = new J2KDecodeFileCache(CacheFolder); | ||
67 | } | 74 | } |
68 | 75 | ||
69 | public void Initialise(Scene scene, IConfigSource source) | 76 | public void Initialise(Scene scene, IConfigSource source) |
70 | { | 77 | { |
78 | if (m_Scene == null) | ||
79 | m_Scene = scene; | ||
80 | |||
81 | IConfig j2kConfig = source.Configs["J2KDecoder"]; | ||
82 | if (j2kConfig != null) | ||
83 | { | ||
84 | CacheFolder = j2kConfig.GetString("CacheDir", CacheFolder); | ||
85 | CacheTimeout = j2kConfig.GetInt("CacheTimeout", CacheTimeout); | ||
86 | } | ||
87 | |||
88 | if (fCache == null) | ||
89 | fCache = new J2KDecodeFileCache(CacheFolder, CacheTimeout); | ||
90 | |||
71 | scene.RegisterModuleInterface<IJ2KDecoder>(this); | 91 | scene.RegisterModuleInterface<IJ2KDecoder>(this); |
92 | |||
93 | if (CleanerThread == null && CacheTimeout != 0) | ||
94 | { | ||
95 | CleanerThread = new Thread(CleanCache); | ||
96 | CleanerThread.Name = "J2KCleanerThread"; | ||
97 | CleanerThread.IsBackground = true; | ||
98 | CleanerThread.Start(); | ||
99 | } | ||
72 | } | 100 | } |
73 | 101 | ||
74 | public void PostInitialise() | 102 | public void PostInitialise() |
75 | { | 103 | { |
76 | 104 | AssetService = m_Scene.AssetService; | |
77 | } | 105 | } |
78 | 106 | ||
79 | public void Close() | 107 | public void Close() |
@@ -329,8 +357,9 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
329 | // Cache Decoded layers | 357 | // Cache Decoded layers |
330 | lock (m_cacheddecode) | 358 | lock (m_cacheddecode) |
331 | { | 359 | { |
332 | if (!m_cacheddecode.ContainsKey(AssetId)) | 360 | if (m_cacheddecode.ContainsKey(AssetId)) |
333 | m_cacheddecode.Add(AssetId, layers); | 361 | m_cacheddecode.Remove(AssetId); |
362 | m_cacheddecode.Add(AssetId, layers); | ||
334 | 363 | ||
335 | } | 364 | } |
336 | 365 | ||
@@ -348,11 +377,34 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
348 | } | 377 | } |
349 | } | 378 | } |
350 | } | 379 | } |
380 | |||
381 | private void CleanCache() | ||
382 | { | ||
383 | m_log.Info("[J2KDecoderModule]: Cleaner thread started"); | ||
384 | |||
385 | while (true) | ||
386 | { | ||
387 | if (AssetService != null) | ||
388 | fCache.ScanCacheFiles(RedecodeTexture); | ||
389 | |||
390 | System.Threading.Thread.Sleep(600000); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | private void RedecodeTexture(UUID assetID) | ||
395 | { | ||
396 | AssetBase texture = AssetService.Get(assetID.ToString()); | ||
397 | if (texture == null) | ||
398 | return; | ||
399 | |||
400 | doJ2kDecode(assetID, texture.Data); | ||
401 | } | ||
351 | } | 402 | } |
352 | 403 | ||
353 | public class J2KDecodeFileCache | 404 | public class J2KDecodeFileCache |
354 | { | 405 | { |
355 | private readonly string m_cacheDecodeFolder; | 406 | private readonly string m_cacheDecodeFolder; |
407 | private readonly int m_cacheTimeout; | ||
356 | private bool enabled = true; | 408 | private bool enabled = true; |
357 | 409 | ||
358 | private static readonly ILog m_log | 410 | private static readonly ILog m_log |
@@ -362,9 +414,10 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
362 | /// Creates a new instance of a file cache | 414 | /// Creates a new instance of a file cache |
363 | /// </summary> | 415 | /// </summary> |
364 | /// <param name="pFolder">base folder for the cache. Will be created if it doesn't exist</param> | 416 | /// <param name="pFolder">base folder for the cache. Will be created if it doesn't exist</param> |
365 | public J2KDecodeFileCache(string pFolder) | 417 | public J2KDecodeFileCache(string pFolder, int timeout) |
366 | { | 418 | { |
367 | m_cacheDecodeFolder = pFolder; | 419 | m_cacheDecodeFolder = pFolder; |
420 | m_cacheTimeout = timeout; | ||
368 | if (!Directory.Exists(pFolder)) | 421 | if (!Directory.Exists(pFolder)) |
369 | { | 422 | { |
370 | Createj2KCacheFolder(pFolder); | 423 | Createj2KCacheFolder(pFolder); |
@@ -555,6 +608,16 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
555 | return String.Format("j2kCache_{0}.cache", AssetId); | 608 | return String.Format("j2kCache_{0}.cache", AssetId); |
556 | } | 609 | } |
557 | 610 | ||
611 | public UUID AssetIdFromFileName(string fileName) | ||
612 | { | ||
613 | string rawId = fileName.Replace("j2kCache_", "").Replace(".cache", ""); | ||
614 | UUID asset; | ||
615 | if (!UUID.TryParse(rawId, out asset)) | ||
616 | return UUID.Zero; | ||
617 | |||
618 | return asset; | ||
619 | } | ||
620 | |||
558 | /// <summary> | 621 | /// <summary> |
559 | /// Creates the Cache Folder | 622 | /// Creates the Cache Folder |
560 | /// </summary> | 623 | /// </summary> |
@@ -619,5 +682,23 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
619 | enabled = false; | 682 | enabled = false; |
620 | } | 683 | } |
621 | } | 684 | } |
685 | |||
686 | public void ScanCacheFiles(J2KDecodeDelegate decode) | ||
687 | { | ||
688 | DirectoryInfo dir = new DirectoryInfo(m_cacheDecodeFolder); | ||
689 | FileInfo[] files = dir.GetFiles("j2kCache_*.cache"); | ||
690 | |||
691 | foreach (FileInfo f in files) | ||
692 | { | ||
693 | TimeSpan fileAge = DateTime.Now - f.CreationTime; | ||
694 | |||
695 | if (m_cacheTimeout != 0 && fileAge >= TimeSpan.FromMinutes(m_cacheTimeout)) | ||
696 | { | ||
697 | File.Delete(f.Name); | ||
698 | decode(AssetIdFromFileName(f.Name)); | ||
699 | System.Threading.Thread.Sleep(5000); | ||
700 | } | ||
701 | } | ||
702 | } | ||
622 | } | 703 | } |
623 | } | 704 | } |
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index c91b63e..53b8ebc 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -1,29 +1,29 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (c) Contributors, http://osflotsam.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | 4 | * | |
5 | Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the Flotsam Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | 15 | * | |
16 | THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | 26 | */ |
27 | 27 | ||
28 | // Uncomment to make asset Get requests for existing | 28 | // Uncomment to make asset Get requests for existing |
29 | // #define WAIT_ON_INPROGRESS_REQUESTS | 29 | // #define WAIT_ON_INPROGRESS_REQUESTS |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index d51ed40..1696d82 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs | |||
@@ -45,6 +45,7 @@ using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; | |||
45 | using OpenSim.Region.CoreModules.World.Serialiser; | 45 | using OpenSim.Region.CoreModules.World.Serialiser; |
46 | using OpenSim.Region.Framework.Scenes; | 46 | using OpenSim.Region.Framework.Scenes; |
47 | using OpenSim.Region.Framework.Scenes.Serialization; | 47 | using OpenSim.Region.Framework.Scenes.Serialization; |
48 | using OpenSim.Services.Interfaces; | ||
48 | using OpenSim.Tests.Common; | 49 | using OpenSim.Tests.Common; |
49 | using OpenSim.Tests.Common.Mock; | 50 | using OpenSim.Tests.Common.Mock; |
50 | using OpenSim.Tests.Common.Setup; | 51 | using OpenSim.Tests.Common.Setup; |
@@ -102,18 +103,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
102 | Monitor.Wait(this, 60000); | 103 | Monitor.Wait(this, 60000); |
103 | } | 104 | } |
104 | 105 | ||
105 | /* | 106 | Console.WriteLine("here"); |
106 | cm.UserAdminService.AddUser(userFirstName, userLastName, string.Empty, string.Empty, 1000, 1000, userId); | ||
107 | CachedUserInfo userInfo = cm.UserProfileCacheService.GetUserDetails(userId, InventoryReceived); | ||
108 | userInfo.FetchInventory(); | ||
109 | for (int i = 0 ; i < 50 ; i++) | ||
110 | { | ||
111 | if (userInfo.HasReceivedInventory == true) | ||
112 | break; | ||
113 | Thread.Sleep(200); | ||
114 | } | ||
115 | Assert.That(userInfo.HasReceivedInventory, Is.True, "FetchInventory timed out (10 seconds)"); | ||
116 | */ | ||
117 | 107 | ||
118 | // Create asset | 108 | // Create asset |
119 | SceneObjectGroup object1; | 109 | SceneObjectGroup object1; |
@@ -148,7 +138,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
148 | item1.AssetID = asset1.FullID; | 138 | item1.AssetID = asset1.FullID; |
149 | item1.ID = item1Id; | 139 | item1.ID = item1Id; |
150 | //userInfo.RootFolder.FindFolderByPath("Objects").ID; | 140 | //userInfo.RootFolder.FindFolderByPath("Objects").ID; |
151 | InventoryFolderBase objsFolder = scene.InventoryService.GetFolderForType(userId, AssetType.Object); | 141 | //InventoryFolderBase objsFolder = scene.InventoryService.GetFolderForType(userId, AssetType.Object); |
142 | Console.WriteLine("here2"); | ||
143 | IInventoryService inventoryService = scene.InventoryService; | ||
144 | InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); | ||
145 | InventoryCollection rootContents = inventoryService.GetFolderContent(userId, rootFolder.ID); | ||
146 | InventoryFolderBase objsFolder = null; | ||
147 | foreach (InventoryFolderBase folder in rootContents.Folders) | ||
148 | if (folder.Name == "Objects") | ||
149 | objsFolder = folder; | ||
152 | item1.Folder = objsFolder.ID; | 150 | item1.Folder = objsFolder.ID; |
153 | scene.AddInventoryItem(userId, item1); | 151 | scene.AddInventoryItem(userId, item1); |
154 | 152 | ||
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index e577fbe..e83b1a8 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -484,6 +484,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
484 | GetParams(partsDelimiter, ref nextLine, 11, ref points); | 484 | GetParams(partsDelimiter, ref nextLine, 11, ref points); |
485 | graph.FillPolygon(myBrush, points); | 485 | graph.FillPolygon(myBrush, points); |
486 | } | 486 | } |
487 | else if (nextLine.StartsWith("Polygon")) | ||
488 | { | ||
489 | PointF[] points = null; | ||
490 | GetParams(partsDelimiter, ref nextLine, 7, ref points); | ||
491 | graph.DrawPolygon(drawPen, points); | ||
492 | } | ||
487 | else if (nextLine.StartsWith("Ellipse")) | 493 | else if (nextLine.StartsWith("Ellipse")) |
488 | { | 494 | { |
489 | float x = 0; | 495 | float x = 0; |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs index c8f04a5..3c3534f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs | |||
@@ -88,13 +88,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
88 | } | 88 | } |
89 | 89 | ||
90 | // If not, go get them and place them in the cache | 90 | // If not, go get them and place them in the cache |
91 | Dictionary<AssetType, InventoryFolderBase> folders = m_Connector.GetSystemFolders(presence.UUID); | 91 | Dictionary<AssetType, InventoryFolderBase> folders = CacheSystemFolders(presence.UUID); |
92 | m_log.DebugFormat("[INVENTORY CACHE]: OnMakeRootAgent in {0}, fetched system folders for {1} {2}: count {3}", | 92 | m_log.DebugFormat("[INVENTORY CACHE]: OnMakeRootAgent in {0}, fetched system folders for {1} {2}: count {3}", |
93 | presence.Scene.RegionInfo.RegionName, presence.Firstname, presence.Lastname, folders.Count); | 93 | presence.Scene.RegionInfo.RegionName, presence.Firstname, presence.Lastname, folders.Count); |
94 | |||
95 | if (folders.Count > 0) | ||
96 | lock (m_InventoryCache) | ||
97 | m_InventoryCache.Add(presence.UUID, folders); | ||
98 | } | 94 | } |
99 | 95 | ||
100 | void OnClientClosed(UUID clientID, Scene scene) | 96 | void OnClientClosed(UUID clientID, Scene scene) |
@@ -113,26 +109,64 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
113 | } | 109 | } |
114 | } | 110 | } |
115 | 111 | ||
116 | // Drop system folders | 112 | m_log.DebugFormat( |
113 | "[INVENTORY CACHE]: OnClientClosed in {0}, user {1} out of sim. Dropping system folders", | ||
114 | scene.RegionInfo.RegionName, clientID); | ||
115 | DropCachedSystemFolders(clientID); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /// <summary> | ||
120 | /// Cache a user's 'system' folders. | ||
121 | /// </summary> | ||
122 | /// <param name="userID"></param> | ||
123 | /// <returns>Folders cached</returns> | ||
124 | protected Dictionary<AssetType, InventoryFolderBase> CacheSystemFolders(UUID userID) | ||
125 | { | ||
126 | // If not, go get them and place them in the cache | ||
127 | Dictionary<AssetType, InventoryFolderBase> folders = m_Connector.GetSystemFolders(userID); | ||
128 | |||
129 | if (folders.Count > 0) | ||
117 | lock (m_InventoryCache) | 130 | lock (m_InventoryCache) |
118 | if (m_InventoryCache.ContainsKey(clientID)) | 131 | m_InventoryCache.Add(userID, folders); |
119 | { | ||
120 | m_log.DebugFormat("[INVENTORY CACHE]: OnClientClosed in {0}, user {1} out of sim. Dropping system folders", | ||
121 | scene.RegionInfo.RegionName, clientID); | ||
122 | 132 | ||
123 | m_InventoryCache.Remove(clientID); | 133 | return folders; |
124 | } | ||
125 | } | ||
126 | } | 134 | } |
127 | 135 | ||
136 | /// <summary> | ||
137 | /// Drop a user's cached 'system' folders | ||
138 | /// </summary> | ||
139 | /// <param name="userID"></param> | ||
140 | protected void DropCachedSystemFolders(UUID userID) | ||
141 | { | ||
142 | // Drop system folders | ||
143 | lock (m_InventoryCache) | ||
144 | if (m_InventoryCache.ContainsKey(userID)) | ||
145 | m_InventoryCache.Remove(userID); | ||
146 | } | ||
128 | 147 | ||
148 | /// <summary> | ||
149 | /// Get the system folder for a particular asset type | ||
150 | /// </summary> | ||
151 | /// <param name="userID"></param> | ||
152 | /// <param name="type"></param> | ||
153 | /// <returns></returns> | ||
129 | public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) | 154 | public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) |
130 | { | 155 | { |
131 | Dictionary<AssetType, InventoryFolderBase> folders = null; | 156 | Dictionary<AssetType, InventoryFolderBase> folders = null; |
157 | |||
132 | lock (m_InventoryCache) | 158 | lock (m_InventoryCache) |
133 | { | 159 | { |
134 | m_InventoryCache.TryGetValue(userID, out folders); | 160 | m_InventoryCache.TryGetValue(userID, out folders); |
161 | |||
162 | // In some situations (such as non-secured standalones), system folders can be requested without | ||
163 | // the user being logged in. So we need to try caching them here if we don't already have them. | ||
164 | if (null == folders) | ||
165 | CacheSystemFolders(userID); | ||
166 | |||
167 | m_InventoryCache.TryGetValue(userID, out folders); | ||
135 | } | 168 | } |
169 | |||
136 | if ((folders != null) && folders.ContainsKey(type)) | 170 | if ((folders != null) && folders.ContainsKey(type)) |
137 | { | 171 | { |
138 | return folders[type]; | 172 | return folders[type]; |