diff options
author | vnugent <public@vaughnnugent.com> | 2023-09-08 23:20:19 -0400 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2023-09-08 23:20:19 -0400 |
commit | dcf6f9dc0143eb50b702eb7dcd9e5dadd140537c (patch) | |
tree | 41efba0de085e6d49a0228b3f942824b2395383d /lib/Utils | |
parent | c38d794d808b06240b778b5b320f506382215e29 (diff) |
Resource, argon2, accounts. sessions core updates
Diffstat (limited to 'lib/Utils')
-rw-r--r-- | lib/Utils/src/ArgumentList.cs | 101 | ||||
-rw-r--r-- | lib/Utils/src/Async/AsyncUpdatableResource.cs | 41 | ||||
-rw-r--r-- | lib/Utils/src/Async/IAsyncExclusiveResource.cs | 6 | ||||
-rw-r--r-- | lib/Utils/src/Async/IAsyncResourceStateHandler.cs | 53 | ||||
-rw-r--r-- | lib/Utils/src/Extensions/MemoryExtensions.cs | 5 | ||||
-rw-r--r-- | lib/Utils/src/Memory/Caching/LRUCache.cs | 14 | ||||
-rw-r--r-- | lib/Utils/src/Memory/Caching/LRUDataStore.cs | 22 | ||||
-rw-r--r-- | lib/Utils/src/Memory/PrivateBuffersMemoryPool.cs | 19 | ||||
-rw-r--r-- | lib/Utils/src/Resources/BackedResourceBase.cs | 38 | ||||
-rw-r--r-- | lib/Utils/src/Resources/IResourceStateHandler.cs | 47 | ||||
-rw-r--r-- | lib/Utils/src/Resources/UpdatableResource.cs | 46 | ||||
-rw-r--r-- | lib/Utils/src/VnEncoding.cs | 8 | ||||
-rw-r--r-- | lib/Utils/tests/.runsettings | 7 |
13 files changed, 296 insertions, 111 deletions
diff --git a/lib/Utils/src/ArgumentList.cs b/lib/Utils/src/ArgumentList.cs new file mode 100644 index 0000000..ae45e36 --- /dev/null +++ b/lib/Utils/src/ArgumentList.cs @@ -0,0 +1,101 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Utils +* File: ArgumentList.cs +* +* ArgumentList.cs is part of VNLib.Utils which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Utils is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published +* by the Free Software Foundation, either version 2 of the License, +* or (at your option) any later version. +* +* VNLib.Utils is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with VNLib.Utils. If not, see http://www.gnu.org/licenses/. +*/ + +using System; +using System.Linq; +using System.Collections.Generic; + +namespace VNLib.Utils +{ + /// <summary> + /// Provides methods for parsing an argument list + /// </summary> + public class ArgumentList : IIndexable<int, string> + { + private readonly List<string> _args; + + /// <summary> + /// Initalzies a the argument parser by copying the given argument array + /// </summary> + /// <param name="args">The array of arguments to clone</param> + /// <exception cref="ArgumentNullException"></exception> + public ArgumentList(string[] args) + { + _ = args ?? throw new ArgumentNullException(nameof(args)); + _args = args.ToList(); + } + + /// <summary> + /// Initalizes the argument parser by copying the given argument list + /// </summary> + /// <param name="args">The argument list to clone</param> + /// <exception cref="ArgumentNullException"></exception> + public ArgumentList(IReadOnlyList<string> args) + { + _ = args ?? throw new ArgumentNullException(nameof(args)); + _args = args.ToList(); + } + + /// <summary> + /// Gets the number of arguments in the list + /// </summary> + public int Count => _args.Count; + + ///<inheritdoc/> + public string this[int key] + { + get => _args[key]; + set => _args[key] = value; + } + + /// <summary> + /// Determines of the given argument is present in the argument list + /// </summary> + /// <param name="arg"></param> + /// <returns>A value that indicates if the argument is present in the list</returns> + public bool HasArgument(string arg) => _args.Contains(arg); + + /// <summary> + /// Determines if the argument is present in the argument list and + /// has a non-null value following it. + /// </summary> + /// <param name="arg">The argument name to test</param> + /// <returns>A value that indicates if a non-null argument is present in the list</returns> + public bool HasArgumentValue(string arg) => GetArgument(arg) != null; + + /// <summary> + /// Gets the value following the specified argument, or + /// null no value follows the specified argument + /// </summary> + /// <param name="arg">The argument to get following value of</param> + /// <returns>The argument value if found</returns> + public string? GetArgument(string arg) + { + int index = _args.IndexOf(arg); + return index == -1 || index + 1 >= _args.Count ? null : this[index + 1]; + } + + + } +}
\ No newline at end of file diff --git a/lib/Utils/src/Async/AsyncUpdatableResource.cs b/lib/Utils/src/Async/AsyncUpdatableResource.cs index b4ce519..6b8ec62 100644 --- a/lib/Utils/src/Async/AsyncUpdatableResource.cs +++ b/lib/Utils/src/Async/AsyncUpdatableResource.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Utils @@ -23,28 +23,13 @@ */ using System; -using System.IO; -using System.Text.Json; +using System.Threading; using System.Threading.Tasks; -using VNLib.Utils.IO; using VNLib.Utils.Resources; namespace VNLib.Utils.Async { - /// <summary> - /// A callback delegate used for updating a <see cref="AsyncUpdatableResource"/> - /// </summary> - /// <param name="source">The <see cref="AsyncUpdatableResource"/> to be updated</param> - /// <param name="data">The serialized data to be stored/updated</param> - /// <exception cref="ResourceUpdateFailedException"></exception> - public delegate Task AsyncUpdateCallback(object source, Stream data); - /// <summary> - /// A callback delegate invoked when a <see cref="AsyncUpdatableResource"/> delete is requested - /// </summary> - /// <param name="source">The <see cref="AsyncUpdatableResource"/> to be deleted</param> - /// <exception cref="ResourceDeleteFailedException"></exception> - public delegate Task AsyncDeleteCallback(object source); /// <summary> /// Implemented by a resource that is backed by an external data store, that when modified or deleted will @@ -52,8 +37,10 @@ namespace VNLib.Utils.Async /// </summary> public abstract class AsyncUpdatableResource : BackedResourceBase, IAsyncExclusiveResource { - protected abstract AsyncUpdateCallback UpdateCb { get; } - protected abstract AsyncDeleteCallback DeleteCb { get; } + /// <summary> + /// The resource update handler that will be invoked when the resource is modified + /// </summary> + protected abstract IAsyncResourceStateHandler AsyncHandler { get; } /// <summary> /// Releases the resource and flushes pending changes to its backing store. @@ -62,7 +49,7 @@ namespace VNLib.Utils.Async /// <exception cref="InvalidOperationException"></exception> /// <exception cref="ResourceDeleteFailedException"></exception> /// <exception cref="ResourceUpdateFailedException"></exception> - public virtual async ValueTask ReleaseAsync() + public virtual async ValueTask ReleaseAsync(CancellationToken cancellation = default) { //If resource has already been realeased, return if (IsReleased) @@ -72,12 +59,12 @@ namespace VNLib.Utils.Async //If deleted flag is set, invoke the delete callback if (Deleted) { - await DeleteCb(this).ConfigureAwait(true); + await AsyncHandler.DeleteAsync(this, cancellation).ConfigureAwait(true); } //If the state has been modifed, flush changes to the store else if (Modified) { - await FlushPendingChangesAsync().ConfigureAwait(true); + await FlushPendingChangesAsync(cancellation).ConfigureAwait(true); } //Set the released value IsReleased = true; @@ -92,18 +79,12 @@ namespace VNLib.Utils.Async /// Only call this method if your store supports multiple state updates /// </para> /// </summary> - protected virtual async Task FlushPendingChangesAsync() + protected virtual async Task FlushPendingChangesAsync(CancellationToken cancellation = default) { //Get the resource object resource = GetResource(); - //Open a memory stream to store data in - using VnMemoryStream data = new(); - //Serialize and write to stream - VnEncoding.JSONSerializeToBinary(resource, data, resource.GetType(), base.JSO); - //Reset stream to begining - _ = data.Seek(0, SeekOrigin.Begin); //Invoke update callback - await UpdateCb(this, data).ConfigureAwait(true); + await AsyncHandler.UpdateAsync(this, resource, cancellation).ConfigureAwait(true); //Clear modified flag Modified = false; } diff --git a/lib/Utils/src/Async/IAsyncExclusiveResource.cs b/lib/Utils/src/Async/IAsyncExclusiveResource.cs index 93157ce..79657c2 100644 --- a/lib/Utils/src/Async/IAsyncExclusiveResource.cs +++ b/lib/Utils/src/Async/IAsyncExclusiveResource.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Utils @@ -22,7 +22,9 @@ * along with VNLib.Utils. If not, see http://www.gnu.org/licenses/. */ +using System.Threading; using System.Threading.Tasks; + using VNLib.Utils.Resources; namespace VNLib.Utils.Async @@ -35,6 +37,6 @@ namespace VNLib.Utils.Async /// <summary> /// Releases the resource from use. Called when a <see cref="ExclusiveResourceHandle{T}"/> is disposed /// </summary> - ValueTask ReleaseAsync(); + ValueTask ReleaseAsync(CancellationToken cancellation = default); } }
\ No newline at end of file diff --git a/lib/Utils/src/Async/IAsyncResourceStateHandler.cs b/lib/Utils/src/Async/IAsyncResourceStateHandler.cs new file mode 100644 index 0000000..843af96 --- /dev/null +++ b/lib/Utils/src/Async/IAsyncResourceStateHandler.cs @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Utils +* File: IAsyncResourceStateHandler.cs +* +* IAsyncResourceStateHandler.cs is part of VNLib.Utils which is part of +* the larger VNLib collection of libraries and utilities. +* +* VNLib.Utils is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published +* by the Free Software Foundation, either version 2 of the License, +* or (at your option) any later version. +* +* VNLib.Utils is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with VNLib.Utils. If not, see http://www.gnu.org/licenses/. +*/ + +using System.Threading; +using System.Threading.Tasks; + +namespace VNLib.Utils.Async +{ + /// <summary> + /// Represents a resource update handler that processes updates asynchronously + /// when requested by a resource holder + /// </summary> + public interface IAsyncResourceStateHandler + { + /// <summary> + /// Updates the resource in it's backing store + /// </summary> + /// <param name="resource">The instance of the handler that is requesting the update</param> + /// <param name="state">The wrapped resource to update</param> + /// <param name="cancellation">A token to cancel the operation</param> + /// <returns>A task that completes when the resource data has successfully been updated</returns> + Task UpdateAsync(AsyncUpdatableResource resource, object state, CancellationToken cancellation); + + /// <summary> + /// Deletes the resource from it's backing store + /// </summary> + /// <param name="resource">The instance of the source data to delete</param> + /// <param name="cancellation">A token to cancel the operation</param> + /// <returns>A task that completes when the resource has been deleted</returns> + Task DeleteAsync(AsyncUpdatableResource resource, CancellationToken cancellation); + } +} diff --git a/lib/Utils/src/Extensions/MemoryExtensions.cs b/lib/Utils/src/Extensions/MemoryExtensions.cs index 0e898b4..32bb3d4 100644 --- a/lib/Utils/src/Extensions/MemoryExtensions.cs +++ b/lib/Utils/src/Extensions/MemoryExtensions.cs @@ -334,9 +334,9 @@ namespace VNLib.Utils.Extensions /// <typeparam name="T">The unmanged data type to provide allocations from</typeparam> /// <returns>The new <see cref="MemoryPool{T}"/> heap wrapper.</returns> [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static MemoryPool<T> ToPool<T>(this IUnmangedHeap heap) where T : unmanaged + public static MemoryPool<T> ToPool<T>(this IUnmangedHeap heap, int maxBufferSize = int.MaxValue) where T : unmanaged { - return new PrivateBuffersMemoryPool<T>(heap); + return new PrivateBuffersMemoryPool<T>(heap, maxBufferSize); } /// <summary> @@ -388,6 +388,7 @@ namespace VNLib.Utils.Extensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe MemoryHandle<T> Alloc<T>(this IUnmangedHeap heap, nuint elements, bool zero = false) where T : unmanaged { + _ = heap ?? throw new ArgumentNullException(nameof(heap)); //Minimum of one element elements = Math.Max(elements, 1); //Get element size diff --git a/lib/Utils/src/Memory/Caching/LRUCache.cs b/lib/Utils/src/Memory/Caching/LRUCache.cs index 30608af..0c8e169 100644 --- a/lib/Utils/src/Memory/Caching/LRUCache.cs +++ b/lib/Utils/src/Memory/Caching/LRUCache.cs @@ -35,17 +35,20 @@ namespace VNLib.Utils.Memory.Caching public abstract class LRUCache<TKey, TValue> : LRUDataStore<TKey, TValue> where TKey : notnull { ///<inheritdoc/> - protected LRUCache() - {} + protected LRUCache(): base() + { } + ///<inheritdoc/> protected LRUCache(int initialCapacity) : base(initialCapacity) - {} + { } + ///<inheritdoc/> protected LRUCache(IEqualityComparer<TKey> keyComparer) : base(keyComparer) - {} + { } + ///<inheritdoc/> protected LRUCache(int initialCapacity, IEqualityComparer<TKey> keyComparer) : base(initialCapacity, keyComparer) - {} + { } /// <summary> /// The maximum number of items to store in LRU cache @@ -121,6 +124,7 @@ namespace VNLib.Utils.Memory.Caching /// </summary> /// <param name="evicted">The record that is being evicted</param> protected abstract void Evicted(ref KeyValuePair<TKey, TValue> evicted); + /// <summary> /// Invoked when an entry was requested and was not found in cache. /// </summary> diff --git a/lib/Utils/src/Memory/Caching/LRUDataStore.cs b/lib/Utils/src/Memory/Caching/LRUDataStore.cs index 89d7c12..c1eb22b 100644 --- a/lib/Utils/src/Memory/Caching/LRUDataStore.cs +++ b/lib/Utils/src/Memory/Caching/LRUDataStore.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Utils @@ -42,6 +42,7 @@ namespace VNLib.Utils.Memory.Caching /// A lookup table that provides O(1) access times for key-value lookups /// </summary> protected Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> LookupTable { get; } + /// <summary> /// A linked list that tracks the least recently used item. /// New items (or recently accessed items) are moved to the end of the list. @@ -52,11 +53,8 @@ namespace VNLib.Utils.Memory.Caching /// <summary> /// Initializes an empty <see cref="LRUDataStore{TKey, TValue}"/> /// </summary> - protected LRUDataStore() - { - LookupTable = new(); - List = new(); - } + protected LRUDataStore() : this(EqualityComparer<TKey>.Default) + { } /// <summary> /// Initializes an empty <see cref="LRUDataStore{TKey, TValue}"/> and sets @@ -98,6 +96,7 @@ namespace VNLib.Utils.Memory.Caching /// <param name="key">The key identifying the value</param> /// <returns>The value stored at the given key</returns> /// <remarks>Items are promoted in the store when accessed</remarks> + /// <exception cref="KeyNotFoundException"></exception> public virtual TValue this[TKey key] { get @@ -115,7 +114,7 @@ namespace VNLib.Utils.Memory.Caching List.Remove(oldNode); //Reuse the node - oldNode.ValueRef = new KeyValuePair<TKey, TValue>(key, value); + oldNode.Value = new KeyValuePair<TKey, TValue>(key, value); //Move the item to the back of the list List.AddLast(oldNode); @@ -135,8 +134,11 @@ namespace VNLib.Utils.Memory.Caching /// </summary> ///<exception cref="NotImplementedException"></exception> public virtual ICollection<TValue> Values => throw new NotSupportedException("Values are not stored in an independent collection, as they are not directly mutable"); + IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => LookupTable.Keys; + IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => List.Select(static node => node.Value); + IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => List.Select(static node => node.Value).GetEnumerator(); /// <summary> @@ -164,10 +166,13 @@ namespace VNLib.Utils.Memory.Caching public bool Remove(in KeyValuePair<TKey, TValue> item) => Remove(item.Key); ///<inheritdoc/> IEnumerator IEnumerable.GetEnumerator() => List.GetEnumerator(); + ///<inheritdoc/> public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => List.CopyTo(array, arrayIndex); + ///<inheritdoc/> public virtual bool ContainsKey(TKey key) => LookupTable.ContainsKey(key); + ///<inheritdoc/> public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => List.GetEnumerator(); @@ -194,6 +199,7 @@ namespace VNLib.Utils.Memory.Caching LookupTable.Clear(); List.Clear(); } + /// <summary> /// Determines if the <see cref="KeyValuePair{TKey, TValue}"/> exists in the store /// </summary> @@ -207,6 +213,7 @@ namespace VNLib.Utils.Memory.Caching } return false; } + ///<inheritdoc/> public virtual bool Remove(TKey key) { @@ -219,6 +226,7 @@ namespace VNLib.Utils.Memory.Caching } return false; } + /// <summary> /// Tries to get a value from the store with its key. Found items are promoted /// </summary> diff --git a/lib/Utils/src/Memory/PrivateBuffersMemoryPool.cs b/lib/Utils/src/Memory/PrivateBuffersMemoryPool.cs index e73a26f..f2bbd51 100644 --- a/lib/Utils/src/Memory/PrivateBuffersMemoryPool.cs +++ b/lib/Utils/src/Memory/PrivateBuffersMemoryPool.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Utils @@ -28,19 +28,22 @@ using System.Buffers; namespace VNLib.Utils.Memory { /// <summary> - /// Provides a <see cref="MemoryPool{T}"/> wrapper for using unmanged <see cref="Win32PrivateHeap"/>s + /// Provides a <see cref="MemoryPool{T}"/> wrapper for using an <see cref="IUnmangedHeap"/>s /// </summary> /// <typeparam name="T">Unamanged memory type to provide data memory instances from</typeparam> public sealed class PrivateBuffersMemoryPool<T> : MemoryPool<T> where T : unmanaged { private readonly IUnmangedHeap Heap; - internal PrivateBuffersMemoryPool(IUnmangedHeap heap):base() + internal PrivateBuffersMemoryPool(IUnmangedHeap heap, int maxSize) { - this.Heap = heap; + Heap = heap; + MaxBufferSize = maxSize; } + ///<inheritdoc/> - public override int MaxBufferSize => int.MaxValue; + public override int MaxBufferSize { get; } + ///<inheritdoc/> ///<exception cref="OutOfMemoryException"></exception> ///<exception cref="ObjectDisposedException"></exception> @@ -53,10 +56,8 @@ namespace VNLib.Utils.Memory /// <typeparam name="TDifType">The unmanaged data type to allocate for</typeparam> /// <param name="minBufferSize">Minumum size of the buffer</param> /// <returns>The memory owner of a different data type</returns> - public IMemoryOwner<TDifType> Rent<TDifType>(int minBufferSize = 0) where TDifType : unmanaged - { - return new SysBufferMemoryManager<TDifType>(Heap, (uint)minBufferSize, false); - } + public IMemoryOwner<TDifType> Rent<TDifType>(int minBufferSize = 0) where TDifType : unmanaged => new SysBufferMemoryManager<TDifType>(Heap, (uint)minBufferSize, false); + ///<inheritdoc/> protected override void Dispose(bool disposing) { diff --git a/lib/Utils/src/Resources/BackedResourceBase.cs b/lib/Utils/src/Resources/BackedResourceBase.cs index 0a2e1e3..22a965c 100644 --- a/lib/Utils/src/Resources/BackedResourceBase.cs +++ b/lib/Utils/src/Resources/BackedResourceBase.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Utils @@ -23,7 +23,6 @@ */ using System; -using System.Text.Json; using System.Runtime.CompilerServices; namespace VNLib.Utils.Resources @@ -34,23 +33,36 @@ namespace VNLib.Utils.Resources /// </summary> public abstract class BackedResourceBase : IResource { - ///<inheritdoc/> - public bool IsReleased { get; protected set; } + const int IsReleasedFlag = 1 << 0; + const int IsDeletedFlag = 1 << 2; + const int IsModifiedFlag = 1 << 3; - /// <summary> - /// Optional <see cref="JsonSerializerOptions"/> to be used when serializing - /// the resource - /// </summary> - internal protected virtual JsonSerializerOptions? JSO { get; } + private uint _flags; + + ///<inheritdoc/> + public bool IsReleased + { + get => (_flags & IsReleasedFlag) == IsReleasedFlag; + protected set => _flags |= IsReleasedFlag; + } /// <summary> /// A value indicating whether the instance should be deleted when released /// </summary> - protected bool Deleted { get; set; } + protected bool Deleted + { + get => (_flags & IsDeletedFlag) == IsDeletedFlag; + set => _flags |= IsDeletedFlag; + } + /// <summary> /// A value indicating whether the instance should be updated when released /// </summary> - protected bool Modified { get; set; } + protected bool Modified + { + get => (_flags & IsModifiedFlag) == IsModifiedFlag; + set => _flags |= IsModifiedFlag; + } /// <summary> /// Checks if the resouce has been disposed and raises an exception if it is @@ -61,7 +73,7 @@ namespace VNLib.Utils.Resources { if (IsReleased) { - throw new ObjectDisposedException("The resource has been disposed"); + throw new ObjectDisposedException(null, "The resource has been disposed"); } } @@ -74,6 +86,6 @@ namespace VNLib.Utils.Resources /// <summary> /// Marks the resource for deletion from backing store during closing events /// </summary> - public virtual void Delete() => Deleted = true; + public virtual void Delete() => _flags |= IsDeletedFlag; } }
\ No newline at end of file diff --git a/lib/Utils/src/Resources/IResourceStateHandler.cs b/lib/Utils/src/Resources/IResourceStateHandler.cs new file mode 100644 index 0000000..c3d0d56 --- /dev/null +++ b/lib/Utils/src/Resources/IResourceStateHandler.cs @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Utils +* File: IResourceStateHandler.cs +* +* IResourceStateHandler.cs is part of VNLib.Utils which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Utils is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published +* by the Free Software Foundation, either version 2 of the License, +* or (at your option) any later version. +* +* VNLib.Utils is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with VNLib.Utils. If not, see http://www.gnu.org/licenses/. +*/ + +namespace VNLib.Utils.Resources +{ + /// <summary> + /// Implemented by a resource that is backed by an external data store, that when modified or deleted will + /// be reflected to the backing store. + /// </summary> + public interface IResourceStateHandler + { + /// <summary> + /// Called when a resource update has been requested + /// </summary> + /// <param name="resource">The <see cref="UpdatableResource"/> to be updated</param> + /// <param name="data">The wrapped state data to update</param> + void Update(UpdatableResource resource, object data); + + /// <summary> + /// Called when a resource delete has been requested + /// </summary> + /// <param name="resource">The <see cref="UpdatableResource"/> to be deleted</param> + /// <exception cref="ResourceDeleteFailedException"></exception> + void Delete(UpdatableResource resource); + } +}
\ No newline at end of file diff --git a/lib/Utils/src/Resources/UpdatableResource.cs b/lib/Utils/src/Resources/UpdatableResource.cs index 16f26f2..68072f9 100644 --- a/lib/Utils/src/Resources/UpdatableResource.cs +++ b/lib/Utils/src/Resources/UpdatableResource.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Utils @@ -23,25 +23,9 @@ */ using System; -using System.IO; - -using VNLib.Utils.IO; namespace VNLib.Utils.Resources { - /// <summary> - /// A callback delegate used for updating a <see cref="UpdatableResource"/> - /// </summary> - /// <param name="source">The <see cref="UpdatableResource"/> to be updated</param> - /// <param name="data">The serialized data to be stored/updated</param> - /// <exception cref="ResourceUpdateFailedException"></exception> - public delegate void UpdateCallback(object source, Stream data); - /// <summary> - /// A callback delegate invoked when a <see cref="UpdatableResource"/> delete is requested - /// </summary> - /// <param name="source">The <see cref="UpdatableResource"/> to be deleted</param> - /// <exception cref="ResourceDeleteFailedException"></exception> - public delegate void DeleteCallback(object source); /// <summary> /// Implemented by a resource that is backed by an external data store, that when modified or deleted will @@ -50,19 +34,11 @@ namespace VNLib.Utils.Resources public abstract class UpdatableResource : BackedResourceBase, IExclusiveResource { /// <summary> - /// The update callback method to invoke during a release operation - /// when the resource is updated. + /// Gets the <see cref="IResourceStateHandler"/> that will be invoked when the resource is released /// </summary> - protected abstract UpdateCallback UpdateCb { get; } - /// <summary> - /// The callback method to invoke during a realease operation - /// when the resource should be deleted - /// </summary> - protected abstract DeleteCallback DeleteCb { get; } + protected abstract IResourceStateHandler Handler { get; } - /// <summary> /// <inheritdoc/> - /// </summary> /// <exception cref="InvalidOperationException"></exception> /// <exception cref="ResourceDeleteFailedException"></exception> /// <exception cref="ResourceUpdateFailedException"></exception> @@ -76,7 +52,7 @@ namespace VNLib.Utils.Resources //If deleted flag is set, invoke the delete callback if (Deleted) { - DeleteCb(this); + Handler.Delete(this); } //If the state has been modifed, flush changes to the store else if (Modified) @@ -88,24 +64,20 @@ namespace VNLib.Utils.Resources } /// <summary> + /// <para> /// Writes the current state of the the resource to the backing store /// immediatly by invoking the specified callback. - /// <br></br> - /// <br></br> + /// </para> + /// <para> /// Only call this method if your store supports multiple state updates + /// </para> /// </summary> protected virtual void FlushPendingChanges() { //Get the resource object resource = GetResource(); - //Open a memory stream to store data in - using VnMemoryStream data = new(); - //Serialize and write to stream - VnEncoding.JSONSerializeToBinary(resource, data, resource.GetType(), JSO); - //Reset stream to begining - _ = data.Seek(0, SeekOrigin.Begin); //Invoke update callback - UpdateCb(this, data); + Handler.Update(this, resource); //Clear modified flag Modified = false; } diff --git a/lib/Utils/src/VnEncoding.cs b/lib/Utils/src/VnEncoding.cs index 35d52a7..9a50a50 100644 --- a/lib/Utils/src/VnEncoding.cs +++ b/lib/Utils/src/VnEncoding.cs @@ -471,7 +471,8 @@ namespace VNLib.Utils } } return value; - } + } + /// <summary> /// Converts the base32 character buffer to its structure representation /// </summary> @@ -485,7 +486,7 @@ namespace VNLib.Utils //calc size of bin buffer int size = base32.Length; //Rent a bin buffer - using UnsafeMemoryHandle<byte> binBuffer = Memory.MemoryUtil.UnsafeAlloc(size); + using UnsafeMemoryHandle<byte> binBuffer = MemoryUtil.UnsafeAlloc(size); //Try to decode the data ERRNO decoded = TryFromBase32Chars(base32, binBuffer.Span); //Marshal back to a struct @@ -505,7 +506,7 @@ namespace VNLib.Utils return null; } //Buffer size of the base32 string will always be enough buffer space - using UnsafeMemoryHandle<byte> tempBuffer = Memory.MemoryUtil.UnsafeAlloc(base32.Length); + using UnsafeMemoryHandle<byte> tempBuffer = MemoryUtil.UnsafeAlloc(base32.Length); //Try to decode the data ERRNO decoded = TryFromBase32Chars(base32, tempBuffer.Span); @@ -704,6 +705,7 @@ namespace VNLib.Utils { return Convert.TryFromBase64Chars(base64, buffer, out int bytesWritten) ? bytesWritten : ERRNO.E_FAIL; } + /// <summary> /// Tries to convert the 8-bit unsigned integers inside the specified read-only span /// into their equivalent string representation that is encoded with base-64 digits. diff --git a/lib/Utils/tests/.runsettings b/lib/Utils/tests/.runsettings index a4d0377..cf85d64 100644 --- a/lib/Utils/tests/.runsettings +++ b/lib/Utils/tests/.runsettings @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <RunSettings> <RunConfiguration> - <EnvironmentVariables> - <VNLIB_SHARED_HEAP_DIAGNOSTICS>1</VNLIB_SHARED_HEAP_DIAGNOSTICS> - </EnvironmentVariables> + <EnvironmentVariables> + <VNLIB_SHARED_HEAP_FILE_PATH>F:\Programming\VNLib\core\lib\WinRpMalloc\src\x64\Debug\rpmalloc.dll</VNLIB_SHARED_HEAP_FILE_PATH> + <VNLIB_SHARED_HEAP_DIAGNOSTICS>1</VNLIB_SHARED_HEAP_DIAGNOSTICS> + </EnvironmentVariables> </RunConfiguration> </RunSettings>
\ No newline at end of file |