satellite/metabase/rangedloop: uuid generation
Create helper function to generate ranges of UUIDs, for parallelizing the segment loop. Change-Id: I17dbc1d5effe27fc1a3491aa9ca56c692bd95df0
This commit is contained in:
parent
1da7520a88
commit
c25391e976
44
satellite/metabase/rangedloop/uuid.go
Normal file
44
satellite/metabase/rangedloop/uuid.go
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package rangedloop
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"storj.io/common/uuid"
|
||||
)
|
||||
|
||||
// CreateUUIDBoundaries splits up the entire 128-bit UUID range into equal parts.
|
||||
func CreateUUIDBoundaries(nRanges uint32) ([]uuid.UUID, error) {
|
||||
if nRanges == 0 {
|
||||
// every time this line is executed a mathematician feels a disturbance in the force
|
||||
nRanges = 1
|
||||
}
|
||||
|
||||
increment := uint32(1 << 32 / uint64(nRanges))
|
||||
|
||||
result := []uuid.UUID{}
|
||||
|
||||
for i := uint32(1); i < nRanges; i++ {
|
||||
topBits := i * increment
|
||||
|
||||
newUuid, err := MakeUUIDWithTopBits(topBits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result = append(result, newUuid)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// MakeUUIDWithTopBits creates a zeroed UUID with the top 32 bits set from the input.
|
||||
// Technically the result is not a UUID since it doesn't have the version and variant bits set.
|
||||
func MakeUUIDWithTopBits(topBits uint32) (uuid.UUID, error) {
|
||||
bytes := make([]byte, 16)
|
||||
binary.BigEndian.PutUint32(bytes, topBits)
|
||||
|
||||
return uuid.FromBytes(bytes)
|
||||
}
|
94
satellite/metabase/rangedloop/uuid_test.go
Normal file
94
satellite/metabase/rangedloop/uuid_test.go
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package rangedloop_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"storj.io/common/uuid"
|
||||
"storj.io/storj/satellite/metabase/rangedloop"
|
||||
)
|
||||
|
||||
func TestMakeUuids(t *testing.T) {
|
||||
inouts := []struct {
|
||||
inTopBits uint32
|
||||
outUuid string
|
||||
}{
|
||||
{
|
||||
0,
|
||||
"00000000-0000-0000-0000-000000000000",
|
||||
}, {
|
||||
0xffffffff,
|
||||
"ffffffff-0000-0000-0000-000000000000",
|
||||
}, {
|
||||
0x12345678,
|
||||
"12345678-0000-0000-0000-000000000000",
|
||||
},
|
||||
}
|
||||
|
||||
for _, inout := range inouts {
|
||||
createdUuid, err := rangedloop.MakeUUIDWithTopBits(inout.inTopBits)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, inout.outUuid, createdUuid.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateUuidBoundaries(t *testing.T) {
|
||||
inouts := []struct {
|
||||
inNumRanges uint32
|
||||
outUuids []string
|
||||
}{
|
||||
{
|
||||
0,
|
||||
[]string{},
|
||||
}, {
|
||||
1,
|
||||
[]string{},
|
||||
}, {
|
||||
2,
|
||||
[]string{
|
||||
"80000000-0000-0000-0000-000000000000",
|
||||
},
|
||||
}, {
|
||||
4,
|
||||
[]string{
|
||||
"40000000-0000-0000-0000-000000000000",
|
||||
"80000000-0000-0000-0000-000000000000",
|
||||
"c0000000-0000-0000-0000-000000000000",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, inout := range inouts {
|
||||
expectedUuids := []uuid.UUID{}
|
||||
for _, outUuidString := range inout.outUuids {
|
||||
outUuid, err := uuid.FromString(outUuidString)
|
||||
require.NoError(t, err)
|
||||
expectedUuids = append(expectedUuids, outUuid)
|
||||
}
|
||||
|
||||
createdRange, err := rangedloop.CreateUUIDBoundaries(inout.inNumRanges)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedUuids, createdRange)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateUUIDBoundariesFor8191Ranges(t *testing.T) {
|
||||
// 0x1fff = Mersenne prime 8191
|
||||
boundaries, err := rangedloop.CreateUUIDBoundaries(0x1fff)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, boundaries, 0x1ffe)
|
||||
|
||||
// floor(2 ^ 32 / 0x1fff) = 0x80040
|
||||
secondUuid, err := uuid.FromString("00080040-0000-0000-0000-000000000000")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secondUuid, boundaries[0])
|
||||
|
||||
// floor(2 ^ 32 / 0x1fff) * 0x1ffe = 0xfff7ff80
|
||||
lastUuid, err := uuid.FromString("fff7ff80-0000-0000-0000-000000000000")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, lastUuid, boundaries[0x1ffd])
|
||||
}
|
Loading…
Reference in New Issue
Block a user