diff --git a/cs/src/core/ClientSession/BasicContext.cs b/cs/src/core/ClientSession/BasicContext.cs
new file mode 100644
index 000000000..7e496af18
--- /dev/null
+++ b/cs/src/core/ClientSession/BasicContext.cs
@@ -0,0 +1,228 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FASTER.core
+{
+ ///
+ /// Basic Faster Context implementation.
+ ///
+ public readonly struct BasicContext : IFasterContext
+ where Functions : IFunctions
+ {
+ readonly ClientSession clientSession;
+
+ internal BasicContext(ClientSession clientSession)
+ {
+ this.clientSession = clientSession;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void UnsafeResumeThread()
+ => clientSession.UnsafeResumeThread();
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void UnsafeResumeThread(out int resumeEpoch)
+ => clientSession.UnsafeResumeThread(out resumeEpoch);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void UnsafeSuspendThread()
+ => clientSession.UnsafeSuspendThread();
+
+ #region IFasterContext
+
+ ///
+ public bool CompletePending(bool wait = false, bool spinWaitForCommit = false)
+ => clientSession.CompletePending(wait, spinWaitForCommit);
+
+ ///
+ public bool CompletePendingWithOutputs(out CompletedOutputIterator completedOutputs, bool wait = false, bool spinWaitForCommit = false)
+ => clientSession.CompletePendingWithOutputs(out completedOutputs, wait, spinWaitForCommit);
+
+ ///
+ public ValueTask CompletePendingAsync(bool waitForCommit = false, CancellationToken token = default)
+ => clientSession.CompletePendingAsync(waitForCommit, token);
+
+ ///
+ public ValueTask> CompletePendingWithOutputsAsync(bool waitForCommit = false, CancellationToken token = default)
+ => clientSession.CompletePendingWithOutputsAsync(waitForCommit, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Read(ref Key key, ref Input input, ref Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.Read(ref key, ref input, ref output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Read(Key key, Input input, out Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.Read(key, input, out output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Read(ref Key key, ref Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.Read(ref key, ref output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Read(Key key, out Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.Read(key, out output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public (Status status, Output output) Read(Key key, Context userContext = default, long serialNo = 0)
+ => clientSession.Read(key, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Read(ref Key key, ref Input input, ref Output output, ref ReadOptions readOptions, out RecordMetadata recordMetadata, Context userContext = default, long serialNo = 0)
+ => clientSession.Read(ref key, ref input, ref output, ref readOptions, out recordMetadata, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status ReadAtAddress(ref Input input, ref Output output, ref ReadOptions readOptions, Context userContext = default, long serialNo = 0)
+ => clientSession.ReadAtAddress(ref input, ref output, ref readOptions, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.ReadAsyncResult> ReadAsync(ref Key key, ref Input input, Context userContext = default, long serialNo = 0, CancellationToken cancellationToken = default)
+ => clientSession.ReadAsync(ref key, ref input, userContext, serialNo, cancellationToken);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.ReadAsyncResult> ReadAsync(Key key, Input input, Context context = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.ReadAsync(key, input, context, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.ReadAsyncResult> ReadAsync(ref Key key, Context userContext = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.ReadAsync(ref key, userContext, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.ReadAsyncResult> ReadAsync(Key key, Context context = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.ReadAsync(key, context, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.ReadAsyncResult> ReadAsync(ref Key key, ref Input input, ref ReadOptions readOptions, Context userContext = default, long serialNo = 0, CancellationToken cancellationToken = default)
+ => clientSession.ReadAsync(ref key, ref input, ref readOptions, userContext, serialNo, cancellationToken);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.ReadAsyncResult> ReadAtAddressAsync(ref Input input, ref ReadOptions readOptions, Context userContext = default, long serialNo = 0, CancellationToken cancellationToken = default)
+ => clientSession.ReadAtAddressAsync(ref input, ref readOptions, userContext, serialNo, cancellationToken);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Upsert(ref Key key, ref Value desiredValue, Context userContext = default, long serialNo = 0)
+ => clientSession.Upsert(ref key, ref desiredValue, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Upsert(ref Key key, ref Input input, ref Value desiredValue, ref Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.Upsert(ref key, ref input, ref desiredValue, ref output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Upsert(ref Key key, ref Input input, ref Value desiredValue, ref Output output, out RecordMetadata recordMetadata, Context userContext = default, long serialNo = 0)
+ => clientSession.Upsert(ref key, ref input, ref desiredValue, ref output, out recordMetadata, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Upsert(Key key, Value desiredValue, Context userContext = default, long serialNo = 0)
+ => clientSession.Upsert(key, desiredValue, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Upsert(Key key, Input input, Value desiredValue, ref Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.Upsert(key, input, desiredValue, ref output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.UpsertAsyncResult> UpsertAsync(ref Key key, ref Value desiredValue, Context userContext = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.UpsertAsync(ref key, ref desiredValue, userContext, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.UpsertAsyncResult> UpsertAsync(ref Key key, ref Input input, ref Value desiredValue, Context userContext = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.UpsertAsync(ref key, ref input, ref desiredValue, userContext, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.UpsertAsyncResult> UpsertAsync(Key key, Value desiredValue, Context userContext = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.UpsertAsync(key, desiredValue, userContext, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.UpsertAsyncResult> UpsertAsync(Key key, Input input, Value desiredValue, Context userContext = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.UpsertAsync(key, input, desiredValue, userContext, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status RMW(ref Key key, ref Input input, ref Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.RMW(ref key, ref input, ref output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status RMW(ref Key key, ref Input input, ref Output output, out RecordMetadata recordMetadata, Context userContext = default, long serialNo = 0)
+ => clientSession.RMW(ref key, ref input, ref output, out recordMetadata, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status RMW(Key key, Input input, out Output output, Context userContext = default, long serialNo = 0)
+ => clientSession.RMW(key, input, out output, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status RMW(ref Key key, ref Input input, Context userContext = default, long serialNo = 0)
+ => clientSession.RMW(ref key, ref input, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status RMW(Key key, Input input, Context userContext = default, long serialNo = 0)
+ => clientSession.RMW(key, input, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.RmwAsyncResult> RMWAsync(ref Key key, ref Input input, Context context = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.RMWAsync(ref key, ref input, context, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.RmwAsyncResult> RMWAsync(Key key, Input input, Context context = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.RMWAsync(key, input, context, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Delete(ref Key key, Context userContext = default, long serialNo = 0)
+ => clientSession.Delete(ref key, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Status Delete(Key key, Context userContext = default, long serialNo = 0)
+ => clientSession.Delete(key, userContext, serialNo);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.DeleteAsyncResult> DeleteAsync(ref Key key, Context userContext = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.DeleteAsync(ref key, userContext, serialNo, token);
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueTask.DeleteAsyncResult> DeleteAsync(Key key, Context userContext = default, long serialNo = 0, CancellationToken token = default)
+ => clientSession.DeleteAsync(key, userContext, serialNo, token);
+
+ ///
+ public void Refresh()
+ => clientSession.Refresh();
+
+ #endregion IFasterContext
+ }
+}
diff --git a/cs/src/core/ClientSession/ClientSession.cs b/cs/src/core/ClientSession/ClientSession.cs
index 4b79664e6..b117954c7 100644
--- a/cs/src/core/ClientSession/ClientSession.cs
+++ b/cs/src/core/ClientSession/ClientSession.cs
@@ -37,13 +37,51 @@ public sealed class ClientSession
UnsafeContext uContext;
LockableUnsafeContext luContext;
- LockableContext lContext;
+ readonly LockableContext lContext;
+ readonly BasicContext bContext;
internal const string NotAsyncSessionErr = "Session does not support async operations";
readonly ILoggerFactory loggerFactory;
readonly ILogger logger;
+ internal ulong TotalLockCount => sharedLockCount + exclusiveLockCount;
+ internal ulong sharedLockCount;
+ internal ulong exclusiveLockCount;
+
+ bool isAcquired;
+
+ internal void Acquire()
+ {
+ CheckNotAcquired();
+ fht.IncrementNumLockingSessions();
+ isAcquired = true;
+ }
+
+ internal void Release()
+ {
+ CheckAcquired();
+ isAcquired = false;
+ fht.DecrementNumLockingSessions();
+ }
+
+ internal void CheckAcquired()
+ {
+ if (!isAcquired)
+ throw new FasterException("Method call on not-acquired Context");
+ }
+
+ void CheckNotAcquired()
+ {
+ if (isAcquired)
+ throw new FasterException("Method call on acquired Context");
+ }
+
+ ///
+ /// Local current epoch
+ ///
+ public int LocalCurrentEpoch => fht.epoch.LocalCurrentEpoch;
+
internal ClientSession(
FasterKV fht,
FasterKV.FasterExecutionContext ctx,
@@ -51,8 +89,11 @@ internal ClientSession(
SessionVariableLengthStructSettings sessionVariableLengthStructSettings,
ILoggerFactory loggerFactory = null)
{
+ this.lContext = new(this);
+ this.bContext = new(this);
+
this.loggerFactory = loggerFactory;
- this.logger = loggerFactory?.CreateLogger($"ClientSession-{GetHashCode().ToString("X8")}");
+ this.logger = loggerFactory?.CreateLogger($"ClientSession-{GetHashCode():X8}");
this.fht = fht;
this.ctx = ctx;
this.functions = functions;
@@ -72,7 +113,7 @@ internal ClientSession(
}
else
{
- if (!(fht.hlog is VariableLengthBlittableAllocator))
+ if (fht.hlog is not VariableLengthBlittableAllocator)
logger?.LogWarning("Warning: Session param of variableLengthStruct provided for non-varlen allocator");
}
@@ -101,7 +142,7 @@ internal ClientSession(
private void UpdateVarlen(ref IVariableLengthStruct variableLengthStruct)
{
- if (!(fht.hlog is VariableLengthBlittableAllocator))
+ if (fht.hlog is not VariableLengthBlittableAllocator)
return;
if (typeof(Value) == typeof(SpanByte) && typeof(Input) == typeof(SpanByte))
@@ -181,14 +222,14 @@ public LockableUnsafeContext GetL
}
///
- /// Return a new interface to Faster operations that supports manual locking.
+ /// Return a session wrapper that supports manual locking.
///
- public LockableContext GetLockableContext()
- {
- this.lContext ??= new(this);
- this.lContext.Acquire();
- return this.lContext;
- }
+ public LockableContext LockableContext => lContext;
+
+ ///
+ /// Return a session wrapper struct that passes through to client session
+ ///
+ public BasicContext BasicContext => bContext;
#region IFasterContext
///
diff --git a/cs/src/core/ClientSession/LockableContext.cs b/cs/src/core/ClientSession/LockableContext.cs
index d40a1a47c..6eeda711b 100644
--- a/cs/src/core/ClientSession/LockableContext.cs
+++ b/cs/src/core/ClientSession/LockableContext.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
-using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;
@@ -12,23 +11,11 @@ namespace FASTER.core
///
/// Faster Context implementation that allows manual control of record locking and epoch management. For advanced use only.
///
- public sealed class LockableContext : IFasterContext, ILockableContext, IDisposable
+ public readonly struct LockableContext : IFasterContext, ILockableContext
where Functions : IFunctions
{
readonly ClientSession clientSession;
-
- internal readonly InternalFasterSession FasterSession;
- bool isAcquired;
-
- ulong TotalLockCount => sharedLockCount + exclusiveLockCount;
- internal ulong sharedLockCount;
- internal ulong exclusiveLockCount;
-
- void CheckAcquired()
- {
- if (!isAcquired)
- throw new FasterException("Method call on unacquired LockableContext");
- }
+ readonly InternalFasterSession FasterSession;
internal LockableContext(ClientSession clientSession)
{
@@ -40,7 +27,7 @@ internal LockableContext(ClientSession clientSession.fht.epoch.LocalCurrentEpoch;
#region Acquire and Dispose
- internal void Acquire()
+
+ ///
+ /// Acquire a lockable context
+ ///
+ public void Acquire()
{
- this.clientSession.fht.IncrementNumLockingSessions();
- if (this.isAcquired)
- throw new FasterException("Trying to acquire an already-acquired LockableContext");
- this.isAcquired = true;
+ clientSession.Acquire();
}
///
- /// Does not actually dispose of anything; asserts the epoch has been suspended
+ /// Release a lockable context; does not actually dispose of anything
///
- public void Dispose()
+ public void Release()
{
- CheckAcquired();
if (clientSession.fht.epoch.ThisInstanceProtected())
- throw new FasterException("Disposing LockableContext with a protected epoch; must call UnsafeSuspendThread");
- if (TotalLockCount > 0)
- throw new FasterException($"Disposing LockableContext with locks held: {sharedLockCount} shared locks, {exclusiveLockCount} exclusive locks");
- this.isAcquired = false;
- this.clientSession.fht.DecrementNumLockingSessions();
+ throw new FasterException("Releasing LockableContext with a protected epoch; must call UnsafeSuspendThread");
+ if (clientSession.TotalLockCount > 0)
+ throw new FasterException($"Releasing LockableContext with locks held: {clientSession.sharedLockCount} shared locks, {clientSession.exclusiveLockCount} exclusive locks");
+ clientSession.Release();
}
#endregion Acquire and Dispose
@@ -95,7 +81,7 @@ public void Dispose()
///
public unsafe void Lock(ref Key key, LockType lockType)
{
- CheckAcquired();
+ clientSession.CheckAcquired();
Debug.Assert(!clientSession.fht.epoch.ThisInstanceProtected());
clientSession.UnsafeResumeThread();
try
@@ -110,9 +96,9 @@ public unsafe void Lock(ref Key key, LockType lockType)
Debug.Assert(status == OperationStatus.SUCCESS);
if (lockType == LockType.Exclusive)
- ++this.exclusiveLockCount;
+ ++clientSession.exclusiveLockCount;
else
- ++this.sharedLockCount;
+ ++clientSession.sharedLockCount;
}
finally
{
@@ -126,7 +112,7 @@ public unsafe void Lock(ref Key key, LockType lockType)
///
public void Unlock(ref Key key, LockType lockType)
{
- CheckAcquired();
+ clientSession.CheckAcquired();
Debug.Assert(!clientSession.fht.epoch.ThisInstanceProtected());
clientSession.UnsafeResumeThread();
try
@@ -141,9 +127,9 @@ public void Unlock(ref Key key, LockType lockType)
Debug.Assert(status == OperationStatus.SUCCESS);
if (lockType == LockType.Exclusive)
- --this.exclusiveLockCount;
+ --clientSession.exclusiveLockCount;
else
- --this.sharedLockCount;
+ --clientSession.sharedLockCount;
}
finally
{
@@ -157,7 +143,7 @@ public void Unlock(ref Key key, LockType lockType)
///
public (bool exclusive, byte shared) IsLocked(ref Key key)
{
- CheckAcquired();
+ clientSession.CheckAcquired();
Debug.Assert(!clientSession.fht.epoch.ThisInstanceProtected());
clientSession.UnsafeResumeThread();
try
@@ -185,7 +171,7 @@ public void Unlock(ref Key key, LockType lockType)
///
/// The session id of FasterSession
///
- public int sessionID { get { return clientSession.ctx.sessionID; } }
+ public int SessionID { get { return clientSession.ctx.sessionID; } }
#endregion Key Locking
diff --git a/cs/src/core/ClientSession/LockableUnsafeContext.cs b/cs/src/core/ClientSession/LockableUnsafeContext.cs
index 17d0d7fda..054f04dc6 100644
--- a/cs/src/core/ClientSession/LockableUnsafeContext.cs
+++ b/cs/src/core/ClientSession/LockableUnsafeContext.cs
@@ -16,19 +16,7 @@ public sealed class LockableUnsafeContext
{
readonly ClientSession clientSession;
-
internal readonly InternalFasterSession FasterSession;
- bool isAcquired;
-
- ulong TotalLockCount => sharedLockCount + exclusiveLockCount;
- internal ulong sharedLockCount;
- internal ulong exclusiveLockCount;
-
- void CheckAcquired()
- {
- if (!isAcquired)
- throw new FasterException("Method call on not-acquired LockableUnsafeContext");
- }
internal LockableUnsafeContext(ClientSession clientSession)
{
@@ -40,7 +28,7 @@ internal LockableUnsafeContext(ClientSession
@@ -79,10 +65,9 @@ public void Dispose()
{
if (clientSession.fht.epoch.ThisInstanceProtected())
throw new FasterException("Disposing LockableUnsafeContext with a protected epoch; must call UnsafeSuspendThread");
- if (TotalLockCount > 0)
- throw new FasterException($"Disposing LockableUnsafeContext with locks held: {sharedLockCount} shared locks, {exclusiveLockCount} exclusive locks");
- this.isAcquired = false;
- this.clientSession.fht.DecrementNumLockingSessions();
+ if (clientSession.TotalLockCount > 0)
+ throw new FasterException($"Disposing LockableUnsafeContext with locks held: {clientSession.sharedLockCount} shared locks, {clientSession.exclusiveLockCount} exclusive locks");
+ clientSession.Release();
}
#endregion Acquire and Dispose
@@ -91,7 +76,7 @@ public void Dispose()
///
public unsafe void Lock(ref Key key, LockType lockType)
{
- CheckAcquired();
+ clientSession.CheckAcquired();
Debug.Assert(clientSession.fht.epoch.ThisInstanceProtected(), "Epoch protection required for Lock()");
LockOperation lockOp = new(LockOperationType.Lock, lockType);
@@ -104,9 +89,9 @@ public unsafe void Lock(ref Key key, LockType lockType)
Debug.Assert(status == OperationStatus.SUCCESS);
if (lockType == LockType.Exclusive)
- ++this.exclusiveLockCount;
+ ++clientSession.exclusiveLockCount;
else
- ++this.sharedLockCount;
+ ++clientSession.sharedLockCount;
}
///
@@ -115,7 +100,7 @@ public unsafe void Lock(ref Key key, LockType lockType)
///
public void Unlock(ref Key key, LockType lockType)
{
- CheckAcquired();
+ clientSession.CheckAcquired();
Debug.Assert(clientSession.fht.epoch.ThisInstanceProtected(), "Epoch protection required for Unlock()");
LockOperation lockOp = new(LockOperationType.Unlock, lockType);
@@ -128,9 +113,9 @@ public void Unlock(ref Key key, LockType lockType)
Debug.Assert(status == OperationStatus.SUCCESS);
if (lockType == LockType.Exclusive)
- --this.exclusiveLockCount;
+ --clientSession.exclusiveLockCount;
else
- --this.sharedLockCount;
+ --clientSession.sharedLockCount;
}
///
@@ -139,7 +124,7 @@ public void Unlock(ref Key key, LockType lockType)
///
public (bool exclusive, byte shared) IsLocked(ref Key key)
{
- CheckAcquired();
+ clientSession.CheckAcquired();
Debug.Assert(clientSession.fht.epoch.ThisInstanceProtected(), "Epoch protection required for IsLocked()");
LockOperation lockOp = new(LockOperationType.IsLocked, LockType.None);
@@ -160,7 +145,7 @@ public void Unlock(ref Key key, LockType lockType)
///
/// The session id of FasterSession
///
- public int sessionID { get { return clientSession.ctx.sessionID; } }
+ public int SessionID { get { return clientSession.ctx.sessionID; } }
#endregion Key Locking
diff --git a/cs/src/core/FasterLog/FasterLogIterator.cs b/cs/src/core/FasterLog/FasterLogIterator.cs
index 115a2a5f0..4721f3104 100644
--- a/cs/src/core/FasterLog/FasterLogIterator.cs
+++ b/cs/src/core/FasterLog/FasterLogIterator.cs
@@ -551,10 +551,11 @@ public override void Dispose()
if (name != null)
fasterLog.PersistedIterators.TryRemove(name, out _);
+ if (Interlocked.Decrement(ref fasterLog.logRefCount) == 0)
+ fasterLog.TrueDispose();
+
disposed = true;
}
- if (Interlocked.Decrement(ref fasterLog.logRefCount) == 0)
- fasterLog.TrueDispose();
}
internal override void AsyncReadPagesFromDeviceToFrame(long readPageStart, int numPages, long untilAddress, TContext context, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null, IDevice objectLogDevice = null, CancellationTokenSource cts = null)
diff --git a/cs/test/LockableUnsafeContextTests.cs b/cs/test/LockableUnsafeContextTests.cs
index 56637506c..16b5c9ebe 100644
--- a/cs/test/LockableUnsafeContextTests.cs
+++ b/cs/test/LockableUnsafeContextTests.cs
@@ -145,21 +145,21 @@ void PrepareRecordLocation(FlushMode recordLocation)
this.fht.Log.FlushAndEvict(wait: true);
}
- static void ClearCountsOnError(LockableUnsafeContext luContext)
+ static void ClearCountsOnError(ClientSession luContext)
{
// If we already have an exception, clear these counts so "Run" will not report them spuriously.
luContext.sharedLockCount = 0;
luContext.exclusiveLockCount = 0;
}
- static void ClearCountsOnError(LockableUnsafeContext> luContext)
+ static void ClearCountsOnError(ClientSession> luContext)
{
// If we already have an exception, clear these counts so "Run" will not report them spuriously.
luContext.sharedLockCount = 0;
luContext.exclusiveLockCount = 0;
}
- static void ClearCountsOnError(LockableUnsafeContext> luContext)
+ static void ClearCountsOnError(ClientSession> luContext)
{
// If we already have an exception, clear these counts so "Run" will not report them spuriously.
luContext.sharedLockCount = 0;
@@ -409,7 +409,7 @@ public void InMemorySimpleLockTxnTest([Values] ResultLockTarget resultLockTarget
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -496,7 +496,7 @@ public void InMemoryLongLockTest([Values] ResultLockTarget resultLockTarget, [Va
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -554,7 +554,7 @@ public void InMemoryDeleteTest([Values] ResultLockTarget resultLockTarget, [Valu
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -705,7 +705,7 @@ public void TransferFromLockTableToCTTTest()
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -757,7 +757,7 @@ public void TransferFromLockTableToUpsertTest([Values] ChainTests.RecordRegion r
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -799,7 +799,7 @@ public void TransferFromLockTableToRMWTest([Values] ChainTests.RecordRegion reco
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -846,7 +846,7 @@ public void TransferFromLockTableToDeleteTest([Values] ChainTests.RecordRegion r
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -894,7 +894,7 @@ public void LockAndUnlockInLockTableOnlyTest()
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -947,7 +947,7 @@ public void TransferFromReadOnlyToUpdateRecordTest([Values] UpdateOp updateOp)
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -1036,7 +1036,7 @@ void unlockKey(int key)
}
catch (Exception)
{
- ClearCountsOnError(lockLuContext);
+ ClearCountsOnError(lockSession);
throw;
}
finally
@@ -1056,7 +1056,7 @@ void locker(int key)
}
catch (Exception)
{
- ClearCountsOnError(lockLuContext);
+ ClearCountsOnError(lockSession);
throw;
}
finally
@@ -1086,7 +1086,7 @@ void updater(int key)
}
catch (Exception)
{
- ClearCountsOnError(updateLuContext);
+ ClearCountsOnError(updateSession);
throw;
}
finally
@@ -1131,7 +1131,7 @@ public void MultiSharedLockTest()
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -1202,7 +1202,7 @@ public void EvictFromMainLogToLockTableTest()
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -1243,7 +1243,7 @@ public async ValueTask CheckpointRecoverTest([Values] CheckpointType checkpointT
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -1270,7 +1270,7 @@ public async ValueTask CheckpointRecoverTest([Values] CheckpointType checkpointT
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -1302,7 +1302,7 @@ public async ValueTask CheckpointRecoverTest([Values] CheckpointType checkpointT
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -1382,7 +1382,7 @@ async static Task PrimaryWriter(FasterKV primaryStore, SyncMode sync
}
catch (Exception)
{
- ClearCountsOnError(luc1);
+ ClearCountsOnError(s1);
throw;
}
finally
@@ -1406,7 +1406,7 @@ async static Task PrimaryWriter(FasterKV primaryStore, SyncMode sync
}
catch (Exception)
{
- ClearCountsOnError(luc1);
+ ClearCountsOnError(s1);
throw;
}
finally
@@ -1462,7 +1462,7 @@ async static Task SecondaryReader(FasterKV secondaryStore, SyncMode
}
catch (Exception)
{
- ClearCountsOnError(luc1);
+ ClearCountsOnError(s1);
throw;
}
finally
diff --git a/cs/test/ReadCacheChainTests.cs b/cs/test/ReadCacheChainTests.cs
index 840898941..a33699e50 100644
--- a/cs/test/ReadCacheChainTests.cs
+++ b/cs/test/ReadCacheChainTests.cs
@@ -227,7 +227,7 @@ void VerifySplicedInKey(int expectedKey)
Assert.AreEqual(expectedKey, storedKey);
}
- static void ClearCountsOnError(LockableUnsafeContext> luContext)
+ static void ClearCountsOnError(ClientSession> luContext)
{
// If we already have an exception, clear these counts so "Run" will not report them spuriously.
luContext.sharedLockCount = 0;
@@ -531,7 +531,7 @@ public void EvictFromReadCacheToLockTableTest()
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -607,7 +607,7 @@ public void TransferFromLockTableToReadCacheTest()
}
catch (Exception)
{
- ClearCountsOnError(luContext);
+ ClearCountsOnError(session);
throw;
}
finally
@@ -718,7 +718,7 @@ unsafe void PopulateAndEvict()
fht.Log.FlushAndEvict(true);
}
- static void ClearCountsOnError(LockableUnsafeContext> luContext)
+ static void ClearCountsOnError(ClientSession> luContext)
{
// If we already have an exception, clear these counts so "Run" will not report them spuriously.
luContext.sharedLockCount = 0;
@@ -903,7 +903,7 @@ unsafe void PopulateAndEvict()
fht.Log.FlushAndEvict(true);
}
- static void ClearCountsOnError(LockableUnsafeContext> luContext)
+ static void ClearCountsOnError(ClientSession> luContext)
{
// If we already have an exception, clear these counts so "Run" will not report them spuriously.
luContext.sharedLockCount = 0;