From e6181c24124d97f2fbc932b8a68311e625463156 Mon Sep 17 00:00:00 2001 From: uzvkl Date: Tue, 11 Jun 2019 23:05:52 +0200 Subject: Move dsa related stuff to subfolder --- dsa/FireBase/Offline/ConcurrentOfflineDatabase.cs | 233 ++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 dsa/FireBase/Offline/ConcurrentOfflineDatabase.cs (limited to 'dsa/FireBase/Offline/ConcurrentOfflineDatabase.cs') diff --git a/dsa/FireBase/Offline/ConcurrentOfflineDatabase.cs b/dsa/FireBase/Offline/ConcurrentOfflineDatabase.cs new file mode 100644 index 0000000..1a9e607 --- /dev/null +++ b/dsa/FireBase/Offline/ConcurrentOfflineDatabase.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using LiteDB; + +namespace Firebase.Database.Offline +{ + /// + /// The offline database. + /// + public class ConcurrentOfflineDatabase : IDictionary + { + private readonly ConcurrentDictionary ccache; + private readonly LiteRepository db; + + /// + /// Initializes a new instance of the class. + /// + /// The item type which is used to determine the database file name. + /// Custom string which will get appended to the file name. + public ConcurrentOfflineDatabase(Type itemType, string filenameModifier) + { + var fullName = GetFileName(itemType.ToString()); + if (fullName.Length > 100) fullName = fullName.Substring(0, 100); + + var mapper = BsonMapper.Global; + mapper.Entity().Id(o => o.Key); + + var root = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + var filename = fullName + filenameModifier + ".db"; + var path = Path.Combine(root, filename); + db = new LiteRepository(new LiteDatabase(path, mapper)); + + var cache = db.Database + .GetCollection() + .FindAll() + .ToDictionary(o => o.Key, o => o); + + ccache = new ConcurrentDictionary(cache); + } + + /// + /// Gets the number of elements contained in the . + /// + /// The number of elements contained in the . + public int Count => ccache.Count; + + /// + /// Gets a value indicating whether this is a read-only collection. + /// + public bool IsReadOnly => false; + + /// + /// Gets an containing the keys of the + /// . + /// + /// + /// An containing the keys of the object that + /// implements . + /// + public ICollection Keys => ccache.Keys; + + /// + /// Gets an containing the values in the + /// . + /// + /// + /// An containing the values in the object that + /// implements . + /// + public ICollection Values => ccache.Values; + + /// + /// Gets or sets the element with the specified key. + /// + /// The key of the element to get or set. + /// The element with the specified key. + public OfflineEntry this[string key] + { + get => ccache[key]; + + set + { + ccache.AddOrUpdate(key, value, (k, existing) => value); + db.Upsert(value); + } + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator that can be used to iterate through the collection. + public IEnumerator> GetEnumerator() + { + return ccache.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Adds an item to the . + /// + /// The object to add to the . + public void Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } + + /// + /// Removes all items from the . + /// + public void Clear() + { + ccache.Clear(); + db.Delete(LiteDB.Query.All()); + } + + /// + /// Determines whether the contains a specific value. + /// + /// The object to locate in the . + /// + /// True if is found in the ; + /// otherwise, false. + /// + public bool Contains(KeyValuePair item) + { + return ContainsKey(item.Key); + } + + /// + /// Copies the elements of the to an + /// , starting at a particular index. + /// + /// + /// The one-dimensional that is the destination of the elements copied + /// from . The must have + /// zero-based indexing. + /// + /// The zero-based index in at which copying begins. + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + ccache.ToList().CopyTo(array, arrayIndex); + } + + /// + /// Removes the first occurrence of a specific object from the + /// . + /// + /// The object to remove from the . + /// + /// True if was successfully removed from the + /// ; otherwise, false. This method also returns false if + /// is not found in the original . + /// + public bool Remove(KeyValuePair item) + { + return Remove(item.Key); + } + + /// + /// Determines whether the contains an element with the + /// specified key. + /// + /// The key to locate in the . + /// + /// True if the contains an element with the key; + /// otherwise, false. + /// + public bool ContainsKey(string key) + { + return ccache.ContainsKey(key); + } + + /// + /// Adds an element with the provided key and value to the . + /// + /// The object to use as the key of the element to add. + /// The object to use as the value of the element to add. + public void Add(string key, OfflineEntry value) + { + ccache.AddOrUpdate(key, value, (k, existing) => value); + db.Upsert(value); + } + + /// + /// Removes the element with the specified key from the . + /// + /// The key of the element to remove. + /// + /// True if the element is successfully removed; otherwise, false. This method also returns false if + /// was not found in the original . + /// + public bool Remove(string key) + { + ccache.TryRemove(key, out _); + return db.Delete(key); + } + + /// + /// Gets the value associated with the specified key. + /// + /// The key whose value to get. + /// + /// When this method returns, the value associated with the specified key, if the key is found; + /// otherwise, the default value for the type of the parameter. This parameter is passed + /// uninitialized. + /// + /// + /// True if the object that implements contains an + /// element with the specified key; otherwise, false. + /// + public bool TryGetValue(string key, out OfflineEntry value) + { + return ccache.TryGetValue(key, out value); + } + + private string GetFileName(string fileName) + { + var invalidChars = new[] {'`', '[', ',', '='}; + foreach (var c in invalidChars.Concat(Path.GetInvalidFileNameChars()).Distinct()) + fileName = fileName.Replace(c, '_'); + + return fileName; + } + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2