diff --git a/internal/arenaskl/arena.go b/internal/arenaskl/arena.go index 011c3b0247..587cb15bd9 100644 --- a/internal/arenaskl/arena.go +++ b/internal/arenaskl/arena.go @@ -80,14 +80,14 @@ func (a *Arena) Capacity() uint32 { // If overflow is not 0, it also ensures that many bytes after the buffer are // inside the arena (this is used for structures that are larger than the // requested size but don't use those extra bytes). -func (a *Arena) alloc(size, alignment, overflow uint32) (uint32, uint32, error) { +func (a *Arena) alloc(size, alignment, overflow uint32) (uint32, error) { if invariants.Enabled && (alignment&(alignment-1)) != 0 { panic(errors.AssertionFailedf("invalid alignment %d", alignment)) } // Verify that the arena isn't already full. origSize := a.n.Load() if int(origSize) > len(a.buf) { - return 0, 0, ErrArenaFull + return 0, ErrArenaFull } // Pad the allocation with enough bytes to ensure the requested alignment. @@ -95,12 +95,12 @@ func (a *Arena) alloc(size, alignment, overflow uint32) (uint32, uint32, error) newSize := a.n.Add(padded) if newSize+uint64(overflow) > uint64(len(a.buf)) { - return 0, 0, ErrArenaFull + return 0, ErrArenaFull } // Return the aligned offset. offset := (uint32(newSize) - size) & ^(alignment - 1) - return offset, uint32(padded), nil + return offset, nil } func (a *Arena) getBytes(offset uint32, size uint32) []byte { diff --git a/internal/arenaskl/arena_test.go b/internal/arenaskl/arena_test.go index f264b8de4f..3f6b12291a 100644 --- a/internal/arenaskl/arena_test.go +++ b/internal/arenaskl/arena_test.go @@ -35,19 +35,19 @@ func TestArenaSizeOverflow(t *testing.T) { a := newArena(constants.MaxUint32OrInt) // Allocating under the limit throws no error. - offset, _, err := a.alloc(math.MaxUint16, 1, 0) + offset, err := a.alloc(math.MaxUint16, 1, 0) require.Nil(t, err) require.Equal(t, uint32(1), offset) require.Equal(t, uint32(math.MaxUint16)+1, a.Size()) // Allocating over the limit could cause an accounting // overflow if 32-bit arithmetic was used. It shouldn't. - _, _, err = a.alloc(math.MaxUint32, 1, 0) + _, err = a.alloc(math.MaxUint32, 1, 0) require.Equal(t, ErrArenaFull, err) require.Equal(t, uint32(constants.MaxUint32OrInt), a.Size()) // Continuing to allocate continues to throw an error. - _, _, err = a.alloc(math.MaxUint16, 1, 0) + _, err = a.alloc(math.MaxUint16, 1, 0) require.Equal(t, ErrArenaFull, err) require.Equal(t, uint32(constants.MaxUint32OrInt), a.Size()) } diff --git a/internal/arenaskl/node.go b/internal/arenaskl/node.go index ad66d2fe17..449294f0b9 100644 --- a/internal/arenaskl/node.go +++ b/internal/arenaskl/node.go @@ -49,7 +49,12 @@ type node struct { keySize uint32 keyTrailer base.InternalKeyTrailer valueSize uint32 - allocSize uint32 + + // Padding to align tower on an 8-byte boundary, so that 32-bit and 64-bit + // architectures use the same memory layout for node. Needed for tests which + // expect a certain struct size. The padding can be removed if we add or + // remove a field from the node. + _ [4]byte // Most nodes do not need to use the full height of the tower, since the // probability of each successive level decreases exponentially. Because @@ -95,7 +100,7 @@ func newRawNode(arena *Arena, height uint32, keySize, valueSize uint32) (nd *nod unusedSize := uint32((maxHeight - int(height)) * linksSize) nodeSize := uint32(maxNodeSize) - unusedSize - nodeOffset, allocSize, err := arena.alloc(nodeSize+keySize+valueSize, nodeAlignment, unusedSize) + nodeOffset, err := arena.alloc(nodeSize+keySize+valueSize, nodeAlignment, unusedSize) if err != nil { return } @@ -104,7 +109,6 @@ func newRawNode(arena *Arena, height uint32, keySize, valueSize uint32) (nd *nod nd.keyOffset = nodeOffset + nodeSize nd.keySize = keySize nd.valueSize = valueSize - nd.allocSize = allocSize return }