151 lines
4.2 KiB
C#
151 lines
4.2 KiB
C#
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
namespace HermesSocketServer.Store.Internal
|
|
{
|
|
public abstract class GroupSaveStore<K, V> : IStore<K, V> where K : class where V : class
|
|
{
|
|
protected readonly IDictionary<K, V> _store;
|
|
protected readonly IList<K> _added;
|
|
protected readonly IList<K> _modified;
|
|
protected readonly IList<K> _deleted;
|
|
protected readonly object _lock;
|
|
|
|
|
|
public GroupSaveStore()
|
|
{
|
|
_store = new Dictionary<K, V>();
|
|
_added = new List<K>();
|
|
_modified = new List<K>();
|
|
_deleted = new List<K>();
|
|
_lock = new object();
|
|
}
|
|
|
|
public abstract Task Load();
|
|
protected abstract void OnInitialAdd(K key, V value);
|
|
protected abstract void OnInitialModify(K key, V value, V newValue);
|
|
protected abstract void OnPostRemove(K key, V value);
|
|
public abstract Task Save();
|
|
|
|
public V? Get(K key)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
if (_store.TryGetValue(key, out var value))
|
|
return value;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public IDictionary<K, V> Get()
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return _store.ToImmutableDictionary();
|
|
}
|
|
}
|
|
|
|
public bool Modify(K? key, V value)
|
|
{
|
|
if (key == null)
|
|
return false;
|
|
|
|
lock (_lock)
|
|
{
|
|
if (_store.TryGetValue(key, out V? oldValue))
|
|
{
|
|
OnInitialModify(key, oldValue, value);
|
|
_store[key] = value;
|
|
if (!_added.Contains(key) && !_modified.Contains(key))
|
|
{
|
|
_modified.Add(key);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool Modify(K? key, Action<V> modify)
|
|
{
|
|
if (key == null)
|
|
return false;
|
|
|
|
lock (_lock)
|
|
{
|
|
if (_store.TryGetValue(key, out V? value))
|
|
{
|
|
modify(value);
|
|
if (!_added.Contains(key) && !_modified.Contains(key))
|
|
{
|
|
_modified.Add(key);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool Remove(K? key, bool fromCascade = false)
|
|
{
|
|
if (key == null)
|
|
return false;
|
|
|
|
lock (_lock)
|
|
{
|
|
if (_store.TryGetValue(key, out var value))
|
|
{
|
|
if (_store.Remove(key))
|
|
{
|
|
OnPostRemove(key, value);
|
|
if (!_added.Remove(key))
|
|
{
|
|
_modified.Remove(key);
|
|
if (!fromCascade && !_deleted.Contains(key))
|
|
{
|
|
_deleted.Add(key);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool Set(K? key, V value)
|
|
{
|
|
if (key == null)
|
|
return false;
|
|
|
|
lock (_lock)
|
|
{
|
|
if (_store.TryGetValue(key, out V? fetched))
|
|
{
|
|
if (fetched != value)
|
|
{
|
|
OnInitialModify(key, fetched, value);
|
|
_store[key] = value;
|
|
if (!_added.Contains(key) && !_modified.Contains(key))
|
|
{
|
|
_modified.Add(key);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OnInitialAdd(key, value);
|
|
_store.Add(key, value);
|
|
if (!_deleted.Remove(key) && !_added.Contains(key))
|
|
{
|
|
_added.Add(key);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
} |