Skip to content

Commit a32fbf6

Browse files
authored
Merge branch 'main' into fix-typo-occured
2 parents 5555b1d + b1077c2 commit a32fbf6

68 files changed

Lines changed: 4162 additions & 562 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Garnet.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
<Project Path="test/cluster/Garnet.test.cluster/Garnet.test.cluster.csproj" />
8989
<Project Path="test/cluster/Garnet.test.cluster.migrate/Garnet.test.cluster.migrate.csproj" />
9090
<Project Path="test/cluster/Garnet.test.cluster.multilog/Garnet.test.cluster.multilog.csproj" />
91+
<Project Path="test/cluster/Garnet.test.cluster.multilog.diskless/Garnet.test.cluster.multilog.diskless.csproj" />
9192
<Project Path="test/cluster/Garnet.test.cluster.replication/Garnet.test.cluster.replication.csproj" />
9293
<Project Path="test/cluster/Garnet.test.cluster.replication.asyncreplay/Garnet.test.cluster.replication.asyncreplay.csproj" />
9394
<Project Path="test/cluster/Garnet.test.cluster.replication.disklesssync/Garnet.test.cluster.replication.disklesssync.csproj" />

Version.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<!-- VersionPrefix property for builds and packages -->
33
<PropertyGroup>
4-
<VersionPrefix>2.0.0-beta.6</VersionPrefix>
4+
<VersionPrefix>2.0.0-beta.7</VersionPrefix>
55
</PropertyGroup>
66
</Project>

benchmark/Resp.benchmark/OfflineBench/AOFBench/AofGen.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ public AofGen(Options options)
231231
AofMemorySize = options.AofMemorySize,
232232
AofPageSize = options.AofPageSize,
233233
UseAofNullDevice = true,
234-
EnableFastCommit = true,
235234
CommitFrequencyMs = -1,
236235
FastAofTruncate = true,
237236
EnableCluster = true,

libs/cluster/Server/ClusterProvider.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ public void SafeTruncateAOF(in AofAddress truncateUntil)
183183
else
184184
{
185185
storeWrapper.appendOnlyFile?.Log.TruncateUntil(truncateUntil);
186-
if (!serverOptions.EnableFastCommit) storeWrapper.appendOnlyFile?.Log.Commit();
187186
}
188187
}
189188
}

libs/cluster/Server/Replication/ReplicaOps/AOFReplay/ReplicaReplayDriver.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ private unsafe void ConsumeSchedulePage(byte* record, int recordLength, long cur
132132
replicationManager.SetSublogReplicationOffset(physicalSublogIdx, currentAddress);
133133

134134
// Wait for replay to complete.
135-
replayBatchContext.LeaderFollowerBarrier.WaitCompleted(serverOptions.ReplicaSyncTimeout, cts.Token);
135+
if (!replayBatchContext.LeaderFollowerBarrier.WaitCompleted(serverOptions.ReplicaSyncTimeout, cts.Token))
136+
ExceptionUtils.ThrowException(new GarnetException("Timed out waiting for parallel replay tasks to complete", LogLevel.Warning, clientResponse: false));
136137
// Release participants for next cycle
137138
replayBatchContext.LeaderFollowerBarrier.Release();
138139

@@ -159,20 +160,18 @@ private unsafe void ConsumeScheduleChannel(byte* record, int recordLength, long
159160
if (payloadLength > 0)
160161
{
161162
var entryPtr = ptr + entryLength;
163+
var logAddressSequenceNumber = currentAddress + (ptr - record);
162164
var replayTaskIdx = replicationManager.AofProcessor.GetReplayTaskIdx(entryPtr);
163165
replayTasks[replayTaskIdx].AddRecord(new ReplayRecord()
164166
{
165167
entryPtr = entryPtr,
166-
payloadLength = payloadLength
168+
payloadLength = payloadLength,
169+
logAddressSequenceNumber = logAddressSequenceNumber
167170
});
168171
entryLength += TsavoriteLog.UnsafeAlign(payloadLength);
169172
}
170173
else if (payloadLength < 0)
171174
{
172-
if (!serverOptions.EnableFastCommit)
173-
{
174-
throw new GarnetException("Received FastCommit request at replica AOF processor, but FastCommit is not enabled", clientResponse: false);
175-
}
176175
TsavoriteLogRecoveryInfo info = new();
177176
info.Initialize(new ReadOnlySpan<byte>(ptr + entryLength, -payloadLength));
178177
physicalSublog.UnsafeCommitMetadataOnly(info, isProtected);
@@ -229,7 +228,8 @@ private unsafe void ConsumeDirect(byte* record, int recordLength, long currentAd
229228
var payloadLength = physicalSublog.UnsafeGetLength(ptr);
230229
if (payloadLength > 0)
231230
{
232-
replicationManager.AofProcessor.ProcessAofRecordInternal(physicalSublogIdx, ptr + entryLength, payloadLength, true, out var isCheckpointStart);
231+
var logAddressSequenceNumber = currentAddress + (ptr - record);
232+
replicationManager.AofProcessor.ProcessAofRecordInternal(physicalSublogIdx, ptr + entryLength, payloadLength, true, out var isCheckpointStart, logAddressSequenceNumber);
233233
// Encountered checkpoint start marker, log the ReplicationCheckpointStartOffset so we know the correct AOF truncation
234234
// point when we take a checkpoint at the checkpoint end marker
235235
if (isCheckpointStart)
@@ -241,10 +241,6 @@ private unsafe void ConsumeDirect(byte* record, int recordLength, long currentAd
241241
}
242242
else if (payloadLength < 0)
243243
{
244-
if (!serverOptions.EnableFastCommit)
245-
{
246-
throw new GarnetException("Received FastCommit request at replica AOF processor, but FastCommit is not enabled", clientResponse: false);
247-
}
248244
TsavoriteLogRecoveryInfo info = new();
249245
info.Initialize(new ReadOnlySpan<byte>(ptr + entryLength, -payloadLength));
250246
physicalSublog.UnsafeCommitMetadataOnly(info, isProtected);

libs/cluster/Server/Replication/ReplicaOps/AOFReplay/ReplicaReplaySession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public void ProcessPrimaryStream(int physicalSublogIdx, byte* record, int record
100100
physicalSublog ??= clusterProvider.storeWrapper.appendOnlyFile.Log.GetSubLog(physicalSublogIdx);
101101

102102
// Enqueue to AOF
103-
_ = physicalSublog.UnsafeEnqueueRaw(new Span<byte>(record, recordLength), noCommit: clusterProvider.serverOptions.EnableFastCommit);
103+
_ = physicalSublog.UnsafeEnqueueRaw(new Span<byte>(record, recordLength), noCommit: true);
104104

105105
if (clusterProvider.storeWrapper.serverOptions.ReplicationOffsetMaxLag == 0)
106106
{

libs/cluster/Server/Replication/ReplicaOps/AOFReplay/ReplicaReplayTask.cs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ internal unsafe struct ReplayRecord
1818
{
1919
public byte* entryPtr;
2020
public int payloadLength;
21+
public long logAddressSequenceNumber;
2122
}
2223

2324
internal sealed class ReplicaReplayTask(
@@ -62,13 +63,22 @@ internal async Task FullPageBasedBackgroundReplayAsync()
6263
{
6364
await replayBatchContext.LeaderFollowerBarrier.WaitReadyWorkAsync(cancellationToken: cts.Token).ConfigureAwait(false);
6465
}
66+
catch (TaskCanceledException) when (cts.Token.IsCancellationRequested)
67+
{
68+
// Suppress the exception if the task was cancelled because of store wrapper disposal
69+
}
6570
catch (Exception ex)
6671
{
6772
logger?.LogError(ex, "{method} failed at WaitAsync", nameof(FullPageBasedBackgroundReplayAsync));
6873
await cts.CancelAsync().ConfigureAwait(false);
6974
break;
7075
}
7176

77+
// Guard: if cancellation happened during WaitReadyWorkAsync, exit cleanly
78+
// without falling through to the processing block (which would issue a spurious SignalCompleted)
79+
if (cts.Token.IsCancellationRequested)
80+
break;
81+
7282
try
7383
{
7484
unsafe
@@ -80,9 +90,6 @@ internal async Task FullPageBasedBackgroundReplayAsync()
8090
var isProtected = replayBatchContext.IsProtected;
8191
var ptr = record;
8292

83-
var maxSequenceNumber = 0L;
84-
85-
// logger?.LogError("[{sublogIdx},{replayIdx}] = {currentAddress} -> {nextAddress}", sublogIdx, replayIdx, currentAddress, nextAddress);
8693
while (ptr < record + recordLength)
8794
{
8895
cts.Token.ThrowIfCancellationRequested();
@@ -91,25 +98,21 @@ internal async Task FullPageBasedBackgroundReplayAsync()
9198
if (payloadLength > 0)
9299
{
93100
var entryPtr = ptr + entryLength;
94-
if (replicationManager.AofProcessor.CanReplay(entryPtr, replayTaskIdx, out var sequenceNumber))
101+
var logAddressSequenceNumber = currentAddress + (ptr - record);
102+
if (replicationManager.AofProcessor.CanReplay(entryPtr, replayTaskIdx, logAddressSequenceNumber, out _))
95103
{
96-
replicationManager.AofProcessor.ProcessAofRecordInternal(virtualSublogIdx, entryPtr, payloadLength, true, out var isCheckpointStart);
104+
replicationManager.AofProcessor.ProcessAofRecordInternal(virtualSublogIdx, entryPtr, payloadLength, true, out var isCheckpointStart, logAddressSequenceNumber);
97105
// Encountered checkpoint start marker, log the ReplicationCheckpointStartOffset so we know the correct AOF truncation
98106
// point when we take a checkpoint at the checkpoint end marker
99107
if (isCheckpointStart)
100108
{
101-
// logger?.LogError("[{sublogIdx}] CheckpointStart {address}", sublogIdx, clusterProvider.replicationManager.GetSublogReplicationOffset(sublogIdx));
102109
replicationManager.ReplicationCheckpointStartOffset[physicalSublogIdx] = replicationManager.GetSublogReplicationOffset(physicalSublogIdx);
103110
}
104111
}
105-
maxSequenceNumber = Math.Max(sequenceNumber, maxSequenceNumber);
106112
entryLength += TsavoriteLog.UnsafeAlign(payloadLength);
107113
}
108114
else if (payloadLength < 0)
109115
{
110-
if (!clusterProvider.serverOptions.EnableFastCommit)
111-
throw new GarnetException("Received FastCommit request at replica AOF processor, but FastCommit is not enabled", clientResponse: false);
112-
113116
// Only a single thread should commit metadata
114117
if (replayTaskIdx == 0)
115118
{
@@ -122,10 +125,16 @@ internal async Task FullPageBasedBackgroundReplayAsync()
122125
ptr += entryLength;
123126
}
124127

125-
// Update max sequence number for this virtual sublog which is mapped
126-
appendOnlyFile.readConsistencyManager.UpdateVirtualSublogMaxSequenceNumber(virtualSublogIdx, maxSequenceNumber);
128+
// Advance frontier to nextAddress (past all entries in this page).
129+
// This ensures the read consistency protocol (which waits for frontier > sessionSeq)
130+
// can proceed once all writes in the page are complete.
131+
appendOnlyFile.readConsistencyManager.UpdateVirtualSublogMaxSequenceNumber(virtualSublogIdx, nextAddress);
127132
}
128133
}
134+
catch (TaskCanceledException) when (cts.Token.IsCancellationRequested)
135+
{
136+
// Suppress the exception if the task was cancelled because of store wrapper disposal
137+
}
129138
catch (Exception ex)
130139
{
131140
logger?.LogError(ex, "{method} failed at replaying", nameof(FullPageBasedBackgroundReplayAsync));
@@ -156,7 +165,7 @@ internal async Task ChannelBasedBackgroundReplayAsync()
156165
{
157166
unsafe
158167
{
159-
replicationManager.AofProcessor.ProcessAofRecordInternal(virtualSublogIdx, record.entryPtr, record.payloadLength, true, out var isCheckpointStart);
168+
replicationManager.AofProcessor.ProcessAofRecordInternal(virtualSublogIdx, record.entryPtr, record.payloadLength, true, out var isCheckpointStart, record.logAddressSequenceNumber);
160169

161170
// Encountered checkpoint start marker, log the ReplicationCheckpointStartOffset so we know the correct AOF truncation
162171
// point when we take a checkpoint at the checkpoint end marker

libs/cluster/Server/Replication/ReplicaOps/ReplicaDiskbasedSync.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,6 @@ async Task<string> ReplicaSyncAttachTaskAsync(bool downgradeLock, bool forceAsyn
115115
clientName: nameof(TryReplicateDiskbasedSyncAsync));
116116
await gcs.ConnectAsync((int)clusterProvider.serverOptions.ReplicaSyncTimeout.TotalMilliseconds, linkedCts.Token).ConfigureAwait(false);
117117

118-
// Wait for Commit of AOF (data received from old primary) if FastCommit is not enabled
119-
// If FastCommit is enabled, we commit during AOF stream processing
120-
if (!clusterProvider.serverOptions.EnableFastCommit && storeWrapper.appendOnlyFile != null)
121-
{
122-
await storeWrapper.appendOnlyFile.Log.CommitAsync().ConfigureAwait(false);
123-
await storeWrapper.appendOnlyFile.Log.WaitForCommitAsync().ConfigureAwait(false);
124-
}
125-
126118
// Reset background replay iterator if this node was a replica
127119
clusterProvider.replicationManager.ResetReplicaReplayDriverStore();
128120

libs/cluster/Server/Replication/ReplicaOps/ReplicaDisklessSync.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,6 @@ async Task<string> TryBeginReplicaSyncAsync(bool downgradeLock, bool forceAsync)
8282
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ctsRepManager.Token, resetHandler.Token);
8383
try
8484
{
85-
if (!clusterProvider.serverOptions.EnableFastCommit && storeWrapper.appendOnlyFile != null)
86-
{
87-
await storeWrapper.appendOnlyFile.Log.CommitAsync().ConfigureAwait(false);
88-
await storeWrapper.appendOnlyFile.Log.WaitForCommitAsync().ConfigureAwait(false);
89-
}
9085

9186
// Reset background replay tasks if this node was a replica
9287
clusterProvider.replicationManager.ResetReplicaReplayDriverStore();

libs/cluster/Server/Replication/ReplicationHistoryManager.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,6 @@ private void TryUpdateMyPrimaryReplId(string primaryReplicationId)
147147
/// </summary>
148148
public void TryUpdateForFailover()
149149
{
150-
if (!clusterProvider.serverOptions.EnableFastCommit)
151-
{
152-
storeWrapper.appendOnlyFile?.Log.Commit();
153-
storeWrapper.appendOnlyFile?.Log.WaitForCommit();
154-
}
155150
while (true)
156151
{
157152
var replicationOffset2 = storeWrapper.appendOnlyFile.Log.CommittedUntilAddress;

0 commit comments

Comments
 (0)