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