aboutsummaryrefslogtreecommitdiff
path: root/lib/VNLib.Data.Caching.ObjectCache
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-02-14 14:23:53 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2024-02-14 14:23:53 -0500
commit6b87785026ca57d6f41cff87ddbd066362f3cacc (patch)
tree74cddbca5eebcec7948e706bd7b742b19e55eeb6 /lib/VNLib.Data.Caching.ObjectCache
parentc0e2a71b7b4081117d87c2c34c1b2afb8d511732 (diff)
Squashed commit of the following:
commit 456ead9bc8b0f61357bae93152ad0403c4940101 Author: vnugent <public@vaughnnugent.com> Date: Tue Feb 13 14:46:35 2024 -0500 fix: #1 shared cluster index on linux & latested core updates commit a481d63f964a5d5204cac2e95141f37f9a28d573 Author: vnugent <public@vaughnnugent.com> Date: Tue Jan 23 15:43:50 2024 -0500 cache extension api tweaks
Diffstat (limited to 'lib/VNLib.Data.Caching.ObjectCache')
-rw-r--r--lib/VNLib.Data.Caching.ObjectCache/src/BlobCache.cs76
-rw-r--r--lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs28
-rw-r--r--lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheLIstener.cs41
-rw-r--r--lib/VNLib.Data.Caching.ObjectCache/src/IMemoryCacheEntryFactory.cs43
-rw-r--r--lib/VNLib.Data.Caching.ObjectCache/src/IPersistantCacheStore.cs10
5 files changed, 79 insertions, 119 deletions
diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCache.cs b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCache.cs
index 5a425ec..7b2b3b1 100644
--- a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCache.cs
+++ b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCache.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Data.Caching.ObjectCache
@@ -34,10 +34,10 @@ namespace VNLib.Data.Caching.ObjectCache
/// <summary>
/// A general purpose binary data storage
/// </summary>
- public sealed class BlobCache : LRUCache<string, CacheEntry>, IBlobCache, IMemoryCacheEntryFactory
+ public sealed class BlobCache : LRUCache<string, CacheEntry>, IBlobCache
{
private bool disposedValue;
- private IPersistantCacheStore? _persistance;
+ private readonly IPersistantCacheStore? _persistance;
///<inheritdoc/>
public override bool IsReadOnly { get; }
@@ -62,17 +62,12 @@ namespace VNLib.Data.Caching.ObjectCache
public BlobCache(uint bucketId, int maxCapacity, ICacheEntryMemoryManager manager, IPersistantCacheStore? store)
:base(maxCapacity, StringComparer.Ordinal)
{
- if(maxCapacity < 1)
- {
- throw new ArgumentException("The maxium capacity of the store must be a positive integer larger than 0", nameof(maxCapacity));
- }
+ ArgumentOutOfRangeException.ThrowIfLessThan(maxCapacity, 1);
+ ArgumentNullException.ThrowIfNull(manager);
BucketId = bucketId;
-
_persistance = store;
-
- MemoryManager = manager ?? throw new ArgumentNullException(nameof(manager));
-
+ MemoryManager = manager;
MaxCapacity = maxCapacity;
//Update the lookup table size
@@ -88,11 +83,11 @@ namespace VNLib.Data.Caching.ObjectCache
return false;
}
//Use the persistant cache
- return _persistance.OnCacheMiss(BucketId, key, this, out value);
+ return _persistance.OnCacheMiss(BucketId, key, MemoryManager, out value);
}
///<inheritdoc/>
- protected override void Evicted(ref KeyValuePair<string, CacheEntry> evicted)
+ protected override void Evicted(ref readonly KeyValuePair<string, CacheEntry> evicted)
{
try
{
@@ -109,6 +104,8 @@ namespace VNLib.Data.Caching.ObjectCache
///<inheritdoc/>
public bool TryChangeKey(string objectId, string newId, out CacheEntry entry)
{
+ ObjectDisposedException.ThrowIf(disposedValue, this);
+
//Try to get the node at the current key
if (LookupTable.Remove(objectId, out LinkedListNode<KeyValuePair<string, CacheEntry>> ? node))
{
@@ -137,6 +134,8 @@ namespace VNLib.Data.Caching.ObjectCache
///<inheritdoc/>
public override bool Remove(string key)
{
+ ObjectDisposedException.ThrowIf(disposedValue, this);
+
//Remove from persistant store also
_persistance?.OnEntryDeleted(BucketId, key);
@@ -161,33 +160,23 @@ namespace VNLib.Data.Caching.ObjectCache
/// </summary>
public override void Clear()
{
- //Start from first node
- LinkedListNode<KeyValuePair<string, CacheEntry>>? node = List.First;
+ ObjectDisposedException.ThrowIf(disposedValue, this);
- //Classic ll node itteration
- while(node != null)
- {
- //Dispose the cache entry
- node.ValueRef.Value.Dispose();
-
- //Move to next node
- node = node.Next;
- }
-
- //empty all cache entires in the store
- base.Clear();
+ ClearInternal();
}
///<inheritdoc/>
public bool Remove(string objectId, out CacheEntry entry)
{
+ ObjectDisposedException.ThrowIf(disposedValue, this);
+
//Try to get the stored object
- if(TryGetValue(objectId, out entry))
+ if (TryGetValue(objectId, out entry))
{
//remove the entry and bypass the disposal
bool result = base.Remove(objectId);
- Debug.Assert(result == true, "The cache entry was found in the table, but failed to remove");
+ Debug.Assert(result, "The cache entry was found in the table, but failed to remove");
return true;
}
@@ -196,6 +185,25 @@ namespace VNLib.Data.Caching.ObjectCache
return false;
}
+ private void ClearInternal()
+ {
+ //Start from first node
+ LinkedListNode<KeyValuePair<string, CacheEntry>>? node = List.First;
+
+ //Classic ll node itteration
+ while (node != null)
+ {
+ //Dispose the cache entry
+ node.ValueRef.Value.Dispose();
+
+ //Move to next node
+ node = node.Next;
+ }
+
+ //empty all cache entires in the store
+ base.Clear();
+ }
+
///<inheritdoc/>
void Dispose(bool disposing)
{
@@ -203,7 +211,7 @@ namespace VNLib.Data.Caching.ObjectCache
{
if (disposing)
{
- Clear();
+ ClearInternal();
}
disposedValue = true;
}
@@ -216,13 +224,5 @@ namespace VNLib.Data.Caching.ObjectCache
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
-
-
- ///<inheritdoc/>
- CacheEntry IMemoryCacheEntryFactory.CreateEntry(ReadOnlySpan<byte> entryData)
- {
- //Create entry from the internal heap
- return CacheEntry.Create(entryData, MemoryManager);
- }
}
}
diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs
index ded89d2..1681256 100644
--- a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs
+++ b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheExtensions.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Data.Caching.ObjectCache
@@ -144,14 +144,14 @@ namespace VNLib.Data.Caching.ObjectCache
this IBlobCacheTable table,
string objectId,
string? alternateId,
- ObjectDataReader<T> bodyData,
+ ObjectDataGet<T> bodyData,
T state,
DateTime time,
CancellationToken cancellation = default)
{
-
- _ = table ?? throw new ArgumentNullException(nameof(table));
- _ = bodyData ?? throw new ArgumentNullException(nameof(bodyData));
+ ArgumentNullException.ThrowIfNull(table);
+ ArgumentNullException.ThrowIfNull(bodyData);
+ ArgumentException.ThrowIfNullOrWhiteSpace(objectId);
//See if an id change is required
if (string.IsNullOrWhiteSpace(alternateId))
@@ -252,11 +252,27 @@ namespace VNLib.Data.Caching.ObjectCache
/// <param name="objectId">The id of the object to delete</param>
/// <param name="cancellation">A token to cancel the async lock await</param>
/// <returns>A task that completes when the item has been deleted</returns>
- public static async ValueTask<bool> DeleteObjectAsync(this IBlobCacheTable table, string objectId, CancellationToken cancellation = default)
+ public static ValueTask<bool> DeleteObjectAsync(this IBlobCacheTable table, string objectId, CancellationToken cancellation = default)
{
+ ArgumentNullException.ThrowIfNull(table);
+
//Try to get the bucket that the id should belong to
IBlobCacheBucket bucket = table.GetBucket(objectId);
+ return DeleteObjectAsync(bucket, objectId, cancellation);
+ }
+
+ /// <summary>
+ /// Asynchronously deletes a previously stored item
+ /// </summary>
+ /// <param name="bucket"></param>
+ /// <param name="objectId">The id of the object to delete</param>
+ /// <param name="cancellation">A token to cancel the async lock await</param>
+ /// <returns>A task that completes when the item has been deleted</returns>
+ public static async ValueTask<bool> DeleteObjectAsync(this IBlobCacheBucket bucket, string objectId, CancellationToken cancellation = default)
+ {
+ ArgumentNullException.ThrowIfNull(bucket);
+
//Wait for the bucket
IBlobCache cache = await bucket.ManualWaitAsync(cancellation);
diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheLIstener.cs b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheLIstener.cs
index 5139746..972bf5e 100644
--- a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheLIstener.cs
+++ b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheLIstener.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Data.Caching.ObjectCache
@@ -49,44 +49,36 @@ using static VNLib.Data.Caching.Constants;
namespace VNLib.Data.Caching.ObjectCache
{
-
/// <summary>
/// An <see cref="FBMListener"/> for key-value object data caching servers.
/// </summary>
- public class BlobCacheListener<T> : FBMListenerBase<T>, IDisposable
+ /// <remarks>
+ /// Initialzies a new <see cref="BlobCacheListener{T}"/>
+ /// </remarks>
+ /// <param name="cache">The cache table to work from</param>
+ /// <param name="queue">The event queue to publish changes to</param>
+ /// <param name="log">Writes error and debug logging information</param>
+ /// <param name="memoryManager">The heap to alloc FBM buffers and <see cref="CacheEntry"/> cache buffers from</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public class BlobCacheListener<T>(IBlobCacheTable cache, ICacheListenerEventQueue<T> queue, ILogProvider log, IFBMMemoryManager memoryManager)
+ : FBMListenerBase<T>, IDisposable
{
private bool disposedValue;
///<inheritdoc/>
- protected override ILogProvider Log { get; }
+ protected override ILogProvider Log { get; } = log;
///<inheritdoc/>
- protected override FBMListener Listener { get; }
+ protected override FBMListener Listener { get; } = new(memoryManager);
/// <summary>
/// A queue that stores update and delete events
/// </summary>
- public ICacheListenerEventQueue<T> EventQueue { get; }
+ public ICacheListenerEventQueue<T> EventQueue { get; } = queue ?? throw new ArgumentNullException(nameof(queue));
/// <summary>
/// The Cache store to access data blobs
/// </summary>
- public IBlobCacheTable Cache { get; }
-
- /// <summary>
- /// Initialzies a new <see cref="BlobCacheListener{T}"/>
- /// </summary>
- /// <param name="cache">The cache table to work from</param>
- /// <param name="queue">The event queue to publish changes to</param>
- /// <param name="log">Writes error and debug logging information</param>
- /// <param name="memoryManager">The heap to alloc FBM buffers and <see cref="CacheEntry"/> cache buffers from</param>
- /// <exception cref="ArgumentNullException"></exception>
- public BlobCacheListener(IBlobCacheTable cache, ICacheListenerEventQueue<T> queue, ILogProvider log, IFBMMemoryManager memoryManager)
- {
- Log = log;
- Cache = cache ?? throw new ArgumentNullException(nameof(cache));
- EventQueue = queue ?? throw new ArgumentNullException(nameof(queue));
- Listener = new(memoryManager);
- }
+ public IBlobCacheTable Cache { get; } = cache ?? throw new ArgumentNullException(nameof(cache));
///<inheritdoc/>
protected override async Task ProcessAsync(FBMContext context, T? userState, CancellationToken exitToken)
@@ -254,8 +246,7 @@ namespace VNLib.Data.Caching.ObjectCache
{
if (!disposedValue)
{
- Cache.Dispose();
-
+ Cache.Dispose();
disposedValue = true;
}
}
diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/IMemoryCacheEntryFactory.cs b/lib/VNLib.Data.Caching.ObjectCache/src/IMemoryCacheEntryFactory.cs
deleted file mode 100644
index 1454fc0..0000000
--- a/lib/VNLib.Data.Caching.ObjectCache/src/IMemoryCacheEntryFactory.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-* Copyright (c) 2023 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Data.Caching.ObjectCache
-* File: IMemoryCacheEntryFactory.cs
-*
-* IMemoryCacheEntryFactory.cs is part of VNLib.Data.Caching.ObjectCache which
-* is part of the larger VNLib collection of libraries and utilities.
-*
-* VNLib.Data.Caching.ObjectCache is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* VNLib.Data.Caching.ObjectCache 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 Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see https://www.gnu.org/licenses/.
-*/
-
-using System;
-
-namespace VNLib.Data.Caching.ObjectCache
-{
- /// <summary>
- /// A factory abstraction that builds <see cref="CacheEntry"/> structures
- /// linked to internally configured memory implementations, for cache
- /// promotions.
- /// </summary>
- public interface IMemoryCacheEntryFactory
- {
- /// <summary>
- /// Creates and initalizes a new <see cref="CacheEntry"/> from the desired object data
- /// </summary>
- /// <param name="entryData">The non-owned memory to copy into the the new <see cref="CacheEntry"/></param>
- /// <returns>The newly initalized <see cref="CacheEntry"/></returns>
- CacheEntry CreateEntry(ReadOnlySpan<byte> entryData);
- }
-}
diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/IPersistantCacheStore.cs b/lib/VNLib.Data.Caching.ObjectCache/src/IPersistantCacheStore.cs
index 40f39f2..3824735 100644
--- a/lib/VNLib.Data.Caching.ObjectCache/src/IPersistantCacheStore.cs
+++ b/lib/VNLib.Data.Caching.ObjectCache/src/IPersistantCacheStore.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Data.Caching.ObjectCache
@@ -54,20 +54,16 @@ namespace VNLib.Data.Caching.ObjectCache
/// This method is called while the bucket lock is held. This call is maded
/// during an <see cref="IBlobCache.Add(string, CacheEntry)"/> method call.
/// </para>
- /// <para>
- /// The <see cref="IMemoryCacheEntryFactory"/> should be used to create the
- /// cache entry for the return value. Once this method returns, the caller owns the new <see cref="CacheEntry"/>
- /// </para>
/// </summary>
/// <param name="key">The key identifying the entry to promot</param>
- /// <param name="factory">The cache entry factory</param>
+ /// <param name="memManager">The cache table memory manager</param>
/// <param name="bucketId">The id of the bucket requesting the operation</param>
/// <param name="entry">The newly created entry when data is found</param>
/// <returns>
/// A value inidcating if the entry was successfully recovered from the persistant storage and
/// was successfully promoted.
/// </returns>
- bool OnCacheMiss(uint bucketId, string key, IMemoryCacheEntryFactory factory, out CacheEntry entry);
+ bool OnCacheMiss(uint bucketId, string key, ICacheEntryMemoryManager memManager, out CacheEntry entry);
/// <summary>
/// Removes an entry from the backing store