/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using MessagePack; public class DatabaseCache { public event Action OnDataInsertLocal; public event Action OnDataUpdateLocal; public event Action OnDataDeleteLocal; public event Action OnDataInsertRemote; public event Action OnDataUpdateRemote; public event Action OnDataDeleteRemote; private readonly object addLock = new object(); public Action Logger = Console.WriteLine; private readonly Dictionary _entries = new Dictionary(); private readonly Dictionary> _types = new Dictionary>(); public IEnumerable AllEntries => _entries.Values; public void Add(DatabaseEntry entry, bool remote = false) { lock(addLock) { if (entry != null) { var exists = _entries.ContainsKey(entry.ID); _entries[entry.ID] = entry; var type = entry.GetType(); var types = type.GetParentTypes(); foreach (var t in types) { if (!_types.ContainsKey(t)) _types[t] = new Dictionary(); _types[t][entry.ID] = entry; } if (remote) { if (exists) OnDataUpdateRemote?.Invoke(entry); else OnDataInsertRemote?.Invoke(entry); } else { if (exists) OnDataUpdateLocal?.Invoke(entry); else OnDataInsertLocal?.Invoke(entry); } } } } public void AddAll(IEnumerable entries, bool remote = false) { foreach (var entry in entries) { Add(entry, remote); } } public DatabaseEntry Get(Guid guid) { DatabaseEntry entry; _entries.TryGetValue(guid, out entry); return entry; } public T Get(Guid guid) where T : DatabaseEntry { if (!_types.ContainsKey(typeof(T))) return null; DatabaseEntry entry; _types[typeof(T)].TryGetValue(guid, out entry); return (T) entry; } public IEnumerable GetAll() { return !_types.ContainsKey(typeof(T)) ? Enumerable.Empty() : _types[typeof(T)].Values.Cast(); } public void Delete(DatabaseEntry entry, bool remote = false) { _entries.Remove(entry.ID); foreach (var type in _types.Values) { type.Remove(entry.ID); } if (remote) OnDataDeleteRemote?.Invoke(entry); else OnDataDeleteLocal?.Invoke(entry); } public void Load(string path) { RegisterResolver.Register(); var bytes = File.ReadAllBytes(Path.Combine(path, "AetherDB.msgpack")); var entries = MessagePackSerializer.Deserialize(bytes); AddAll(entries); } public void Save(string path) { RegisterResolver.Register(); var entries = AllEntries.ToArray(); File.WriteAllBytes(Path.Combine(path, "AetherDB.msgpack"), MessagePackSerializer.Serialize(entries)); } }