Skip to content

Commit

Permalink
NLog - ConfigurationItemFactory - Handle concurrent registration of c…
Browse files Browse the repository at this point in the history
…onfiguration items
  • Loading branch information
snakefoot committed Dec 5, 2022
1 parent 373bbf4 commit 1297d08
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 43 deletions.
88 changes: 60 additions & 28 deletions src/NLog/Config/Factory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,22 @@ public void RegisterType(Type type, string assemblyName, string itemNamePrefix)
public void RegisterNamedType(string itemName, string typeName)
{
itemName = NormalizeName(itemName);
_items[itemName] = () => Type.GetType(typeName, false);

lock (_items)
{
_items[itemName] = () => Type.GetType(typeName, false);
}
}

/// <summary>
/// Clears the contents of the factory.
/// </summary>
public void Clear()
public virtual void Clear()
{
_items.Clear();
lock (_items)
{
_items.Clear();
}
}

/// <inheritdoc/>
Expand All @@ -160,22 +167,26 @@ private void RegisterDefinition(string itemName, Type itemDefinition, string ass
{
GetTypeDelegate typeLookup = () => itemDefinition;
itemName = NormalizeName(itemName);
_items[itemNamePrefix + itemName] = typeLookup;
if (!string.IsNullOrEmpty(assemblyName))

lock (_items)
{
_items[itemName + ", " + assemblyName] = typeLookup;
_items[itemDefinition.Name + ", " + assemblyName] = typeLookup;
_items[itemDefinition.ToString() + ", " + assemblyName] = typeLookup;
_items[itemNamePrefix + itemName] = typeLookup;

if (!string.IsNullOrEmpty(assemblyName))
{
_items[itemName + ", " + assemblyName] = typeLookup;
_items[itemDefinition.Name + ", " + assemblyName] = typeLookup;
_items[itemDefinition.ToString() + ", " + assemblyName] = typeLookup;
}
}
}

/// <inheritdoc/>
public bool TryGetDefinition(string itemName, out Type result)
{
GetTypeDelegate getTypeDelegate;

itemName = NormalizeName(itemName);
if (!_items.TryGetValue(itemName, out getTypeDelegate))

if (!TryGetTypeDelegate(itemName, out var getTypeDelegate))
{
if (_globalDefaultFactory != null && _globalDefaultFactory.TryGetDefinition(itemName, out result))
{
Expand Down Expand Up @@ -204,6 +215,14 @@ public bool TryGetDefinition(string itemName, out Type result)
}
}

private bool TryGetTypeDelegate(string itemName, out GetTypeDelegate getTypeDelegate)
{
lock (_items)
{
return _items.TryGetValue(itemName, out getTypeDelegate);
}
}

/// <inheritdoc/>
public virtual bool TryCreateInstance(string itemName, out TBaseType result)
{
Expand Down Expand Up @@ -292,7 +311,7 @@ protected static string NormalizeName(string itemName)
/// </summary>
internal sealed class LayoutRendererFactory : Factory<LayoutRenderer, LayoutRendererAttribute>
{
private Dictionary<string, FuncLayoutRenderer> _funcRenderers;
private readonly Dictionary<string, FuncLayoutRenderer> _funcRenderers = new Dictionary<string, FuncLayoutRenderer>(StringComparer.OrdinalIgnoreCase);
private readonly LayoutRendererFactory _globalDefaultFactory;

public LayoutRendererFactory(ConfigurationItemFactory parentFactory, LayoutRendererFactory globalDefaultFactory)
Expand All @@ -301,12 +320,15 @@ public LayoutRendererFactory(ConfigurationItemFactory parentFactory, LayoutRende
_globalDefaultFactory = globalDefaultFactory;
}

/// <summary>
/// Clear all func layouts
/// </summary>
public void ClearFuncLayouts()
/// <inheritdoc/>
public override void Clear()
{
_funcRenderers?.Clear();
lock (_funcRenderers)
{
_funcRenderers.Clear();
}

base.Clear();
}

/// <summary>
Expand All @@ -317,10 +339,11 @@ public void ClearFuncLayouts()
public void RegisterFuncLayout(string itemName, FuncLayoutRenderer renderer)
{
itemName = NormalizeName(itemName);
_funcRenderers = _funcRenderers ?? new Dictionary<string, FuncLayoutRenderer>(StringComparer.OrdinalIgnoreCase);

//overwrite current if there is one
_funcRenderers[itemName] = renderer;
lock (_funcRenderers)
{
_funcRenderers[itemName] = renderer;
}
}

/// <summary>
Expand All @@ -334,20 +357,29 @@ public override bool TryCreateInstance(string itemName, out LayoutRenderer resul
//first try func renderers, as they should have the possibility to overwrite a current one.
FuncLayoutRenderer funcResult;
itemName = NormalizeName(itemName);
if (_funcRenderers != null)

if (_funcRenderers.Count > 0)
{
var successAsFunc = _funcRenderers.TryGetValue(itemName, out funcResult);
if (successAsFunc)
lock (_funcRenderers)
{
result = funcResult;
return true;
if (_funcRenderers.TryGetValue(itemName, out funcResult))
{
result = funcResult;
return true;
}
}
}

if (_globalDefaultFactory?._funcRenderers != null && _globalDefaultFactory._funcRenderers.TryGetValue(itemName, out funcResult))
if (_globalDefaultFactory?._funcRenderers?.Count > 0)
{
result = funcResult;
return true;
lock (_globalDefaultFactory._funcRenderers)
{
if (_globalDefaultFactory._funcRenderers.TryGetValue(itemName, out funcResult))
{
result = funcResult;
return true;
}
}
}

return base.TryCreateInstance(itemName, out result);
Expand Down
41 changes: 26 additions & 15 deletions src/NLog/Config/MethodFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,11 @@ public static IList<KeyValuePair<string, MethodInfo>> ExtractClassMethods<TClass
/// </summary>
public void Clear()
{
_nameToMethodInfo.Clear();
lock (_nameToLateBoundMethod)
lock (_nameToMethodInfo)
{
_nameToMethodInfo.Clear();
_nameToLateBoundMethod.Clear();
}
}

/// <summary>
Expand All @@ -173,18 +175,18 @@ public void RegisterDefinition(string itemName, MethodInfo itemDefinition)
/// <param name="itemNamePrefix">The item name prefix.</param>
public void RegisterDefinition(string itemName, MethodInfo itemDefinition, string assemblyName, string itemNamePrefix)
{
_nameToMethodInfo[itemName + itemNamePrefix] = itemDefinition;
if (!string.IsNullOrEmpty(assemblyName))
lock (_nameToMethodInfo)
{
_nameToMethodInfo[itemName + ", " + assemblyName] = itemDefinition;
}
_nameToMethodInfo[itemName + itemNamePrefix] = itemDefinition;
if (!string.IsNullOrEmpty(assemblyName))
{
_nameToMethodInfo[itemName + ", " + assemblyName] = itemDefinition;
}

lock (_nameToLateBoundMethod)
{
_nameToLateBoundMethod.Remove(itemName + itemNamePrefix);
if (!string.IsNullOrEmpty(assemblyName))
{
_nameToMethodInfo.Remove(itemName + ", " + assemblyName);
_nameToLateBoundMethod.Remove(itemName + ", " + assemblyName);
}
}
}
Expand All @@ -197,9 +199,11 @@ public void RegisterDefinition(string itemName, MethodInfo itemDefinition, strin
/// <param name="lateBoundMethod">The precompiled method delegate.</param>
internal void RegisterDefinition(string itemName, MethodInfo itemDefinition, ReflectionHelpers.LateBoundMethod lateBoundMethod)
{
_nameToMethodInfo[itemName] = itemDefinition;
lock (_nameToLateBoundMethod)
{
_nameToMethodInfo[itemName] = itemDefinition;
_nameToLateBoundMethod[itemName] = lateBoundMethod;
}
}

/// <summary>
Expand All @@ -221,18 +225,22 @@ public bool TryCreateInstance(string itemName, out MethodInfo result)
/// <returns>A value of <c>true</c> if the method was found, <c>false</c> otherwise.</returns>
public bool TryCreateInstance(string itemName, out ReflectionHelpers.LateBoundMethod result)
{
lock (_nameToLateBoundMethod)
MethodInfo methodInfo = null;

lock (_nameToMethodInfo)
{
if (_nameToLateBoundMethod.TryGetValue(itemName, out result))
{
return true;
}

_nameToMethodInfo.TryGetValue(itemName, out methodInfo);
}

if (_nameToMethodInfo.TryGetValue(itemName, out var methodInfo))
if (methodInfo != null)
{
result = ReflectionHelpers.CreateLateBoundMethod(methodInfo);
lock (_nameToLateBoundMethod)
lock (_nameToMethodInfo)
_nameToLateBoundMethod[itemName] = result;
return true;
}
Expand Down Expand Up @@ -278,9 +286,12 @@ public ReflectionHelpers.LateBoundMethod CreateInstance(string itemName)
/// <returns>A value of <c>true</c> if the method was found, <c>false</c> otherwise.</returns>
public bool TryGetDefinition(string itemName, out MethodInfo result)
{
if (_nameToMethodInfo.TryGetValue(itemName, out result))
lock (_nameToMethodInfo)
{
return true;
if (_nameToMethodInfo.TryGetValue(itemName, out result))
{
return true;
}
}

return _globalDefaultFactory?.TryGetDefinition(itemName, out result) ?? false;
Expand Down

0 comments on commit 1297d08

Please sign in to comment.