Skip to content

Commit

Permalink
Merge branch 'main' into importer
Browse files Browse the repository at this point in the history
  • Loading branch information
Scooletz committed Oct 19, 2024
2 parents 60567df + 29c59ad commit 9f7acb7
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 29 deletions.
6 changes: 5 additions & 1 deletion src/Paprika.Tests/Store/AbandonedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,11 @@ public async Task Abandoned_chain_creation_with_overflow()
var accountValue = new byte[2900];
new Random(17).NextBytes(accountValue);

using var db = PagedDb.NativeMemoryDb(165_000 * Page.PageSize, HistoryDepth);
using var db = PagedDb.NativeMemoryDb(350_000 * Page.PageSize, HistoryDepth);

// Ensure that AbandonedList can pack maximum number of abandoned page addresses.
const int estimatedMetadataSize = 32;
AbandonedList.MaxCount.Should().BeGreaterThan(AbandonedList.Size / DbAddress.Size - estimatedMetadataSize);

// Start read only batch to ensure that new pages are allocated instead of reusing
// the abandoned pages.
Expand Down
44 changes: 16 additions & 28 deletions src/Paprika/Store/AbandonedList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,18 @@ namespace Paprika.Store;
public struct AbandonedList
{
/// <summary>
/// The start for spans of <see cref="BatchIds"/> and <see cref="Addresses"/>.
/// The start for <see cref="Addresses"/> span.
/// </summary>
private const int EntriesStart = DbAddress.Size + sizeof(uint);

public const int Size = Page.PageSize - PageHeader.Size - RootPage.Payload.AbandonedStart - EntriesStart;
private const int EntrySize = sizeof(uint) + DbAddress.Size;
private const int EntrySize = DbAddress.Size;
public const int MaxCount = (Size - EntriesStart) / EntrySize;

[FieldOffset(0)] private DbAddress Current;
[FieldOffset(DbAddress.Size)] private uint EntriesCount;

[FieldOffset(EntriesStart)] private uint BatchIdStart;

private Span<uint> BatchIds => MemoryMarshal.CreateSpan(ref BatchIdStart, MaxCount);

[FieldOffset(MaxCount * sizeof(uint) + EntriesStart)]
[FieldOffset(EntriesStart)]
private DbAddress AddressStart;

private Span<DbAddress> Addresses => MemoryMarshal.CreateSpan(ref AddressStart, MaxCount);
Expand All @@ -45,37 +41,33 @@ public bool TryGet(out DbAddress reused, uint minBatchId, IBatchContext batch)
return false;
}

// find first batch matching the range
var id = BatchIds[0];
if (minBatchId > 2 && id < minBatchId)
{
var at = Addresses[0];
// check if the first page matches the specified batch range
var at = Addresses[0];

Debug.Assert(at.IsNull == false);

Debug.Assert(at.IsNull == false);
var page = batch.GetAt(at);
var abandoned = new AbandonedPage(page);

var id = abandoned.BatchId;
if (minBatchId > 2 && id < minBatchId)
{
Current = at;
var page = batch.GetAt(at);
var abandoned = new AbandonedPage(page);
if (abandoned.Next.IsNull)
{
if (EntriesCount == 1)
{
// empty all
Addresses[0] = default;
BatchIds[0] = default;
EntriesCount = 0;
}
else
{
var resized = (int)EntriesCount - 1;

// at least two entries, copy slices to move
// at least two entries, copy slice to move
Addresses.Slice(1, resized).CopyTo(Addresses.Slice(0, resized));
BatchIds.Slice(1, resized).CopyTo(BatchIds.Slice(0, resized));

Addresses[resized] = default;
BatchIds[resized] = default;

EntriesCount--;
}
}
Expand Down Expand Up @@ -166,15 +158,13 @@ private void Register(DbAddress head, IBatchContext batch)
{
if (MaxCount == EntriesCount)
{
// No place, attach it to the youngest batch id from the sorted BatchIds
// No place, attach it to the last page which has the youngest batch id. Addresses
// are always sorted by batch ids, hence the last page.
var maxAt = MaxCount - 1;
Debug.Assert(MaxCount > 2 && BatchIds[MaxCount - 1] > BatchIds[MaxCount - 2]);

// 1. Attach the previously existing abandoned as tail to the current one
new AbandonedPage(batch.GetAt(head)).AttachTail(Addresses[maxAt], batch);
// 2. Update the batch id
BatchIds[maxAt] = batch.BatchId;
// 3. Set properly the address to the head that has been chained up
// 2. Set properly the address to the head that has been chained up
Addresses[maxAt] = head;
}
else
Expand All @@ -184,7 +174,6 @@ private void Register(DbAddress head, IBatchContext batch)

Debug.Assert(Addresses[at] == DbAddress.Null);

BatchIds[at] = batch.BatchId;
Addresses[at] = head;

EntriesCount++;
Expand Down Expand Up @@ -218,7 +207,6 @@ public bool IsFullyEmpty
const int notFound = -1;

return Addresses.IndexOfAnyExcept(DbAddress.Null) == notFound &&
BatchIds.IndexOfAnyExcept(default(uint)) == notFound &&
EntriesCount == 0 &&
Current == DbAddress.Null;
}
Expand Down

0 comments on commit 9f7acb7

Please sign in to comment.