From 3c353afe4dffa3da9c96ef25b02f0004676afe5f Mon Sep 17 00:00:00 2001 From: vnugent Date: Sat, 14 Oct 2023 15:50:46 -0400 Subject: experimential expansion and performance changes --- .../src/BlobCacheExtensions.cs | 81 ++++++++++++++++++---- 1 file changed, 68 insertions(+), 13 deletions(-) (limited to 'lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs') diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs index 4a8692d..a114236 100644 --- a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs +++ b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs @@ -34,9 +34,42 @@ namespace VNLib.Data.Caching.ObjectCache /// public static class BlobCacheExtensions { + + /// + /// Gets a that holds an exclusive lock + /// for the current bucekt and holds a referrence to the stored + /// + /// + /// + /// A token to cancel the wait operation + /// A that holds the referrence + public static ValueTask WaitAsync(this IBlobCacheBucket bucket, CancellationToken cancellation) + { + _ = bucket ?? throw new ArgumentNullException(nameof(bucket)); + + //Try enter the bucket lock + ValueTask cacheWait = bucket.ManualWaitAsync(cancellation); + + if (cacheWait.IsCompleted) + { + IBlobCache bucketHandle = cacheWait.GetAwaiter().GetResult(); + return new ValueTask(new CacheBucketHandle(bucket, bucketHandle)); + } + else + { + return GetHandleAsync(cacheWait, bucket); + } + + static async ValueTask GetHandleAsync(ValueTask waitTask, IBlobCacheBucket bucket) + { + IBlobCache cache = await waitTask.ConfigureAwait(false); + return new CacheBucketHandle(bucket, cache); + } + } + internal static CacheEntry CreateEntry(this IBlobCache cache, string objectId, ReadOnlySpan initialData, DateTime time) { - CacheEntry entry = CacheEntry.Create(initialData, cache.CacheHeap); + CacheEntry entry = CacheEntry.Create(initialData, cache.MemoryManager); try { //try to add the entry, but if exists, let it throw @@ -115,17 +148,27 @@ namespace VNLib.Data.Caching.ObjectCache DateTime time, CancellationToken cancellation = default) { + + _ = table ?? throw new ArgumentNullException(nameof(table)); + _ = bodyData ?? throw new ArgumentNullException(nameof(bodyData)); + //See if an id change is required if (string.IsNullOrWhiteSpace(alternateId)) { //safe to get the bucket for the primary id IBlobCacheBucket bucket = table.GetBucket(objectId); - //Wait for the bucket - using CacheBucketHandle handle = await bucket.WaitAsync(cancellation); + //Wait for the bucket to be available + IBlobCache cache = await bucket.ManualWaitAsync(cancellation); - //add/update for single entity - _ = handle.Cache.AddOrUpdateEntry(objectId, bodyData(state), time); + try + { + _ = cache.AddOrUpdateEntry(objectId, bodyData(state), time); + } + finally + { + bucket.Release(); + } } else { @@ -136,11 +179,17 @@ namespace VNLib.Data.Caching.ObjectCache //Same bucket if (ReferenceEquals(primary, alternate)) { - //wait for lock on only one bucket otherwise dealock - using CacheBucketHandle handle = await primary.WaitAsync(cancellation); + IBlobCache cache = await primary.ManualWaitAsync(cancellation); - //Update the entry for the single bucket - _ = handle.Cache.TryChangeKey(objectId, alternateId, bodyData(state), time); + try + { + //Update the entry for the single bucket + _ = cache.TryChangeKey(objectId, alternateId, bodyData(state), time); + } + finally + { + primary.Release(); + } } else { @@ -187,11 +236,17 @@ namespace VNLib.Data.Caching.ObjectCache //Try to get the bucket that the id should belong to IBlobCacheBucket bucket = table.GetBucket(objectId); - //Wait for lock on bucket async - using CacheBucketHandle handle = await bucket.WaitAsync(cancellation); + //Wait for the bucket + IBlobCache cache = await bucket.ManualWaitAsync(cancellation); - //Remove the object from the blob store - return handle.Cache.Remove(objectId); + try + { + return cache.Remove(objectId); + } + finally + { + bucket.Release(); + } } } } -- cgit