From 720806b66183dc55589beb9161bdea071ac9c6fa Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 15 Jun 2013 00:34:45 +0100 Subject: Adjust the locking on InventoryCache. Locking for r/w of the ExpiringCache isn't needed since it's thread safe but r/w of contained dictionaries isn't thread-safe --- .../Inventory/InventoryCache.cs | 37 ++++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs index 1e434b9..dcf33a1 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; - +using System.Threading; using OpenSim.Framework; using OpenMetaverse; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { + /// + /// Cache root and system inventory folders to reduce number of potentially remote inventory calls and associated holdups. + /// public class InventoryCache { private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour @@ -16,8 +19,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public void Cache(UUID userID, InventoryFolderBase root) { - lock (m_RootFolders) - m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS); + m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS); } public InventoryFolderBase GetRootFolder(UUID userID) @@ -31,14 +33,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public void Cache(UUID userID, AssetType type, InventoryFolderBase folder) { - lock (m_FolderTypes) + Dictionary ff = null; + if (!m_FolderTypes.TryGetValue(userID, out ff)) + { + ff = new Dictionary(); + m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS); + } + + // We need to lock here since two threads could potentially retrieve the same dictionary + // and try to add a folder for that type simultaneously. Dictionary<>.Add() is not described as thread-safe in the SDK + // even if the folders are identical. + lock (ff) { - Dictionary ff = null; - if (!m_FolderTypes.TryGetValue(userID, out ff)) - { - ff = new Dictionary(); - m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS); - } if (!ff.ContainsKey(type)) ff.Add(type, folder); } @@ -50,8 +56,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (m_FolderTypes.TryGetValue(userID, out ff)) { InventoryFolderBase f = null; - if (ff.TryGetValue(type, out f)) - return f; + + lock (ff) + { + if (ff.TryGetValue(type, out f)) + return f; + } } return null; @@ -59,8 +69,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public void Cache(UUID userID, InventoryCollection inv) { - lock (m_Inventories) - m_Inventories.AddOrUpdate(userID, inv, 120); + m_Inventories.AddOrUpdate(userID, inv, 120); } public InventoryCollection GetUserInventory(UUID userID) -- cgit v1.1