diff --git a/source/LootDumpProcessor/Program.cs b/source/LootDumpProcessor/Program.cs index 4c1e7ce..811b0fa 100644 --- a/source/LootDumpProcessor/Program.cs +++ b/source/LootDumpProcessor/Program.cs @@ -22,9 +22,6 @@ public static class Program await using var serviceProvider = services.BuildServiceProvider(); - // Setup Data storage - DataStorageFactory.GetInstance().Setup(); - // startup the pipeline var pipeline = serviceProvider.GetRequiredService(); await pipeline.Execute(); diff --git a/source/LootDumpProcessor/Storage/AbstractKey.cs b/source/LootDumpProcessor/Storage/AbstractKey.cs index 329868e..0e792ba 100644 --- a/source/LootDumpProcessor/Storage/AbstractKey.cs +++ b/source/LootDumpProcessor/Storage/AbstractKey.cs @@ -2,13 +2,14 @@ namespace LootDumpProcessor.Storage; public abstract class AbstractKey(string[] indexes) : IKey { + private string[] _indexes = indexes; public abstract KeyType GetKeyType(); public string SerializedKey { - get => string.Join("|", indexes); - set => indexes = value.Split("|"); + get => string.Join("|", _indexes); + set => _indexes = value.Split("|"); } - public string[] GetLookupIndex() => indexes; + public string[] GetLookupIndex() => _indexes; } \ No newline at end of file diff --git a/source/LootDumpProcessor/Storage/DataStorageFactory.cs b/source/LootDumpProcessor/Storage/DataStorageFactory.cs index 50a0307..2feec38 100644 --- a/source/LootDumpProcessor/Storage/DataStorageFactory.cs +++ b/source/LootDumpProcessor/Storage/DataStorageFactory.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using LootDumpProcessor.Storage.Implementations.File; using LootDumpProcessor.Storage.Implementations.Memory; @@ -5,9 +6,7 @@ namespace LootDumpProcessor.Storage; public static class DataStorageFactory { - private static readonly Dictionary _dataStorage = new(); - - private static object lockObject = new(); + private static readonly ConcurrentDictionary DataStorage = new(); /** * Requires LootDumpProcessorContext to be initialized before using @@ -15,23 +14,18 @@ public static class DataStorageFactory public static IDataStorage GetInstance() => GetInstance(LootDumpProcessorContext.GetConfig().DataStorageConfig.DataStorageType); - public static IDataStorage GetInstance(DataStorageTypes type) + private static IDataStorage GetInstance(DataStorageTypes type) { - IDataStorage dataStorage; - lock (lockObject) + if (DataStorage.TryGetValue(type, out var dataStorage)) return dataStorage; + + dataStorage = type switch { - if (!_dataStorage.TryGetValue(type, out dataStorage)) - { - dataStorage = type switch - { - DataStorageTypes.File => new FileDataStorage(), - DataStorageTypes.Memory => new MemoryDataStorage(), - _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) - }; + DataStorageTypes.File => new FileDataStorage(), + DataStorageTypes.Memory => new MemoryDataStorage(), + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) + }; - _dataStorage.Add(type, dataStorage); - } - } + DataStorage.TryAdd(type, dataStorage); return dataStorage; } diff --git a/source/LootDumpProcessor/Storage/IDataStorage.cs b/source/LootDumpProcessor/Storage/IDataStorage.cs index 55ddb8f..f29c385 100644 --- a/source/LootDumpProcessor/Storage/IDataStorage.cs +++ b/source/LootDumpProcessor/Storage/IDataStorage.cs @@ -2,9 +2,8 @@ namespace LootDumpProcessor.Storage; public interface IDataStorage { - void Setup(); - void Store(T t) where T : IKeyable; - bool Exists(IKey t); - T GetItem(IKey key) where T : IKeyable; + void Store(TEntity entity) where TEntity : IKeyable; + TEntity? GetItem(IKey key) where TEntity : IKeyable; + bool Exists(IKey key); void Clear(); } \ No newline at end of file diff --git a/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs b/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs index 5c24fe6..0c525f6 100644 --- a/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs +++ b/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs @@ -2,19 +2,14 @@ namespace LootDumpProcessor.Storage.Implementations.File; public class FileDataStorage : IDataStorage { - public void Setup() + public void Store(TEntity entity) where TEntity : IKeyable { + StoreHandlerFactory.GetInstance(entity.GetKey().GetKeyType()).Store(entity); } - public void Store(T t) where T : IKeyable - { - StoreHandlerFactory.GetInstance(t.GetKey().GetKeyType()).Store(t); - } + public bool Exists(IKey key) => StoreHandlerFactory.GetInstance(key.GetKeyType()).Exists(key); - public bool Exists(IKey t) => StoreHandlerFactory.GetInstance(t.GetKeyType()).Exists(t); - - public T GetItem(IKey key) where T : IKeyable => - StoreHandlerFactory.GetInstance(key.GetKeyType()).Retrieve(key); + public T GetItem(IKey key) where T : IKeyable => StoreHandlerFactory.GetInstance(key.GetKeyType()).Retrieve(key); public void Clear() { diff --git a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs index 3bd885d..5793226 100644 --- a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs +++ b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs @@ -5,27 +5,27 @@ namespace LootDumpProcessor.Storage.Implementations.File.Handlers; public abstract class AbstractStoreHandler : IStoreHandler { - public void Store(T obj, bool failIfDuplicate = true) where T : IKeyable + public void Store(TEntity entity, bool failIfDuplicate = true) where TEntity : IKeyable { - var locationWithFile = GetLocation(obj.GetKey()); + var locationWithFile = GetLocation(entity.GetKey()); if (System.IO.File.Exists(locationWithFile) && failIfDuplicate) throw new Exception($"Attempted to save duplicated object into data storage: {locationWithFile}"); - System.IO.File.WriteAllText(locationWithFile, JsonSerializer.Serialize(obj, JsonSerializerSettings.Default)); + System.IO.File.WriteAllText(locationWithFile, JsonSerializer.Serialize(entity, JsonSerializerSettings.Default)); } - public T? Retrieve(IKey obj) where T : IKeyable + public TEntity? Retrieve(IKey key) where TEntity : IKeyable { - var locationWithFile = GetLocation(obj); + var locationWithFile = GetLocation(key); if (!System.IO.File.Exists(locationWithFile)) return default; - return JsonSerializer.Deserialize(System.IO.File.ReadAllText(locationWithFile), + return JsonSerializer.Deserialize(System.IO.File.ReadAllText(locationWithFile), JsonSerializerSettings.Default); } - public bool Exists(IKey obj) + public bool Exists(IKey key) { - var locationWithFile = GetLocation(obj); + var locationWithFile = GetLocation(key); return System.IO.File.Exists(locationWithFile); } diff --git a/source/LootDumpProcessor/Storage/Implementations/File/IStoreHandler.cs b/source/LootDumpProcessor/Storage/Implementations/File/IStoreHandler.cs index b1a8f26..26995a0 100644 --- a/source/LootDumpProcessor/Storage/Implementations/File/IStoreHandler.cs +++ b/source/LootDumpProcessor/Storage/Implementations/File/IStoreHandler.cs @@ -2,7 +2,7 @@ namespace LootDumpProcessor.Storage.Implementations.File; public interface IStoreHandler { - void Store(T obj, bool failIfDuplicate = true) where T : IKeyable; - T? Retrieve(IKey obj) where T : IKeyable; - bool Exists(IKey obj); + void Store(TEntity entity, bool failIfDuplicate = true) where TEntity : IKeyable; + TEntity? Retrieve(IKey key) where TEntity : IKeyable; + bool Exists(IKey key); } \ No newline at end of file diff --git a/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs b/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs index 533a283..f4fa64b 100644 --- a/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs +++ b/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs @@ -1,28 +1,23 @@ +using System.Collections.Concurrent; using LootDumpProcessor.Storage.Implementations.File.Handlers; namespace LootDumpProcessor.Storage.Implementations.File; public class StoreHandlerFactory { - private static Dictionary _handlers = new(); - private static object lockObject = new(); + private static readonly ConcurrentDictionary Handlers = new(); public static IStoreHandler GetInstance(KeyType type) { - IStoreHandler handler; - lock (lockObject) + if (Handlers.TryGetValue(type, out var handler)) return handler; + + handler = type switch { - if (!_handlers.TryGetValue(type, out handler)) - { - handler = type switch - { - KeyType.Unique => new FlatStoreHandler(), - KeyType.Subdivisioned => new SubdivisionedStoreHandler(), - _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) - }; - _handlers.Add(type, handler); - } - } + KeyType.Unique => new FlatStoreHandler(), + KeyType.Subdivisioned => new SubdivisionedStoreHandler(), + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) + }; + Handlers.TryAdd(type, handler); return handler; } diff --git a/source/LootDumpProcessor/Storage/Implementations/Memory/MemoryDataStorage.cs b/source/LootDumpProcessor/Storage/Implementations/Memory/MemoryDataStorage.cs index f7c8256..0c08544 100644 --- a/source/LootDumpProcessor/Storage/Implementations/Memory/MemoryDataStorage.cs +++ b/source/LootDumpProcessor/Storage/Implementations/Memory/MemoryDataStorage.cs @@ -1,47 +1,22 @@ +using System.Collections.Concurrent; + namespace LootDumpProcessor.Storage.Implementations.Memory; public class MemoryDataStorage : IDataStorage { - private static readonly Dictionary CachedObjects = new(); - private static readonly object _cacheObjectLock = new(); + private readonly ConcurrentDictionary _storage = new(); - public void Setup() + public void Store(TEntity entity) where TEntity : IKeyable => + _storage.TryAdd(GetLookupKey(entity.GetKey()), entity); + + public TEntity? GetItem(IKey key) where TEntity : IKeyable { - } - - public void Store(T t) where T : IKeyable - { - lock (_cacheObjectLock) - { - CachedObjects.Add(GetLookupKey(t.GetKey()), t); - } - } - - public bool Exists(IKey t) - { - lock (_cacheObjectLock) - { - return CachedObjects.ContainsKey(GetLookupKey(t)); - } - } - - public T? GetItem(IKey key) where T : IKeyable - { - lock (_cacheObjectLock) - { - if (CachedObjects.TryGetValue(GetLookupKey(key), out var value)) return (T)value; - } - + if (_storage.TryGetValue(GetLookupKey(key), out var value)) return (TEntity)value; return default; } - private string GetLookupKey(IKey key) => string.Join("-", key.GetLookupIndex()); + public bool Exists(IKey key) => _storage.ContainsKey(GetLookupKey(key)); - public void Clear() - { - lock (_cacheObjectLock) - { - CachedObjects.Clear(); - } - } + private string GetLookupKey(IKey key) => string.Join("-", key.GetLookupIndex()); + public void Clear() => _storage.Clear(); } \ No newline at end of file