Skip to content

Commit e25782f

Browse files
authored
Fix flush with generic allocator so that we do not write invalid data to disk in rare cases (record was invalid when making initial image, but (#916)
1 parent e9e56ed commit e25782f

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

cs/src/core/Allocator/GenericAllocator.cs

+24-8
Original file line numberDiff line numberDiff line change
@@ -452,29 +452,46 @@ private void WriteAsync<TContext>(long flushPage, ulong alignedDestinationAddres
452452
}
453453

454454
long endPosition = 0;
455-
for (int i=start/recordSize; i<end/recordSize; i++)
455+
for (int i = start / recordSize; i < end / recordSize; i++)
456456
{
457-
if (!src[i].info.Invalid)
457+
byte* recordPtr = buffer.aligned_pointer + i * recordSize;
458+
459+
// Retrieve reference to record struct
460+
ref var record = ref Unsafe.AsRef<Record<Key, Value>>(recordPtr);
461+
AddressInfo* key_address = null, value_address = null;
462+
463+
// Zero out object reference addresses (AddressInfo) in the planned disk image
464+
if (KeyHasObjects())
465+
{
466+
key_address = GetKeyAddressInfo((long)recordPtr);
467+
*key_address = default;
468+
}
469+
if (ValueHasObjects())
470+
{
471+
value_address = GetValueAddressInfo((long)recordPtr);
472+
*value_address = default;
473+
}
474+
475+
// Now fill in AddressInfo data for the valid records
476+
if (!record.info.Invalid)
458477
{
459478
var address = (flushPage << LogPageSizeBits) + i * recordSize;
460-
if (address < fuzzyStartLogicalAddress || !src[i].info.IsInNewVersion)
479+
if (address < fuzzyStartLogicalAddress || !record.info.IsInNewVersion)
461480
{
462481
if (KeyHasObjects())
463482
{
464483
long pos = ms.Position;
465484
keySerializer.Serialize(ref src[i].key);
466-
var key_address = GetKeyAddressInfo((long)(buffer.aligned_pointer + i * recordSize));
467485
key_address->Address = pos;
468486
key_address->Size = (int)(ms.Position - pos);
469487
addr.Add((long)key_address);
470488
endPosition = pos + key_address->Size;
471489
}
472490

473-
if (ValueHasObjects() && !src[i].info.Tombstone)
491+
if (ValueHasObjects() && !record.info.Tombstone)
474492
{
475493
long pos = ms.Position;
476494
valueSerializer.Serialize(ref src[i].value);
477-
var value_address = GetValueAddressInfo((long)(buffer.aligned_pointer + i * recordSize));
478495
value_address->Address = pos;
479496
value_address->Size = (int)(ms.Position - pos);
480497
addr.Add((long)value_address);
@@ -484,7 +501,6 @@ private void WriteAsync<TContext>(long flushPage, ulong alignedDestinationAddres
484501
else
485502
{
486503
// Mark v+1 records as invalid to avoid deserializing them on recovery
487-
ref var record = ref Unsafe.AsRef<Record<Key, Value>>(buffer.aligned_pointer + i * recordSize);
488504
record.info.SetInvalid();
489505
}
490506
}
@@ -846,7 +862,7 @@ public void Deserialize(byte *raw, long ptr, long untilptr, Record<Key, Value>[]
846862
stream.Seek(streamStartPos + key_addr->Address - start_addr, SeekOrigin.Begin);
847863
}
848864

849-
keySerializer.Deserialize(out src[ptr/recordSize].key);
865+
keySerializer.Deserialize(out src[ptr / recordSize].key);
850866
}
851867
else
852868
{

0 commit comments

Comments
 (0)