Skip to content

Commit

Permalink
Detailed tests for used nodes (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
outofforest authored Oct 5, 2024
1 parent 881266b commit 45c9d60
Show file tree
Hide file tree
Showing 8 changed files with 420 additions and 101 deletions.
6 changes: 1 addition & 5 deletions alloc/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
func NewTestAllocator(parentAllocator types.Allocator) *TestAllocator {
return &TestAllocator{
parentAllocator: parentAllocator,
nodesAccessed: map[types.NodeAddress]struct{}{},
nodesAllocated: map[types.NodeAddress]struct{}{},
nodesDeallocated: map[types.NodeAddress]struct{}{},
}
Expand All @@ -20,14 +19,12 @@ func NewTestAllocator(parentAllocator types.Allocator) *TestAllocator {
type TestAllocator struct {
parentAllocator types.Allocator

nodesAccessed map[types.NodeAddress]struct{}
nodesAllocated map[types.NodeAddress]struct{}
nodesDeallocated map[types.NodeAddress]struct{}
}

// Node returns node bytes.
func (a *TestAllocator) Node(nodeAddress types.NodeAddress) []byte {
a.nodesAccessed[nodeAddress] = struct{}{}
return a.parentAllocator.Node(nodeAddress)
}

Expand All @@ -54,11 +51,10 @@ func (a *TestAllocator) NodeSize() uint64 {

// Nodes returns touched nodes.
func (a *TestAllocator) Nodes() (
accessed []types.NodeAddress,
allocated []types.NodeAddress,
deallocated []types.NodeAddress,
) {
return mapToSlice(a.nodesAccessed), mapToSlice(a.nodesAllocated), mapToSlice(a.nodesDeallocated)
return mapToSlice(a.nodesAllocated), mapToSlice(a.nodesDeallocated)
}

func mapToSlice(m map[types.NodeAddress]struct{}) []types.NodeAddress {
Expand Down
14 changes: 4 additions & 10 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,23 +155,17 @@ func (db *DB) DeleteSnapshot(snapshotID types.SnapshotID) error {
}
}

// FIXME (wojciech): Iterate over space instead
for sID := db.nextSnapshot.SingularityNode.FirstSnapshotID; sID < snapshotID; sID++ {
listNodeAddress, exists := deallocationLists.Get(sID)
if !exists {
continue
}

nextListNodeAddress, _ := nextDeallocationLists.Get(sID)
for snapshotItem := range deallocationLists.Iterator() {
nextListNodeAddress, _ := nextDeallocationLists.Get(snapshotItem.Key)
newNextListNodeAddress := nextListNodeAddress
nextList := list.New(list.Config{
Item: &newNextListNodeAddress,
})
if err := nextList.Attach(listNodeAddress); err != nil {
if err := nextList.Attach(snapshotItem.Value); err != nil {
return err
}
if newNextListNodeAddress != nextListNodeAddress {
if err := nextDeallocationLists.Set(sID, newNextListNodeAddress); err != nil {
if err := nextDeallocationLists.Set(snapshotItem.Key, newNextListNodeAddress); err != nil {
return err
}
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/samber/lo v1.47.0
github.com/stretchr/testify v1.9.0
golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 h1:1wqE9dj9NpSm04INVsJhhEUzhuDVjbcyKH91sVyPATw=
golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
Expand Down
61 changes: 60 additions & 1 deletion list/list.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package list

import "github.com/outofforest/quantum/types"
import (
"sort"

"github.com/outofforest/quantum/types"
)

// Config stores list configuration.
type Config struct {
Expand Down Expand Up @@ -134,3 +138,58 @@ func (l *List) Deallocate(allocator types.Allocator) {
allocator.Deallocate(n)
}
}

// Iterator iterates over items in the list.
func (l *List) Iterator() func(func(types.NodeAddress) bool) {
return func(yield func(types.NodeAddress) bool) {
if *l.config.Item == 0 {
return
}

stack := []types.NodeAddress{*l.config.Item}
for {
if len(stack) == 0 {
return
}

n := stack[len(stack)-1]
stack = stack[:len(stack)-1]

_, listNode := l.config.NodeAllocator.Get(n)
for i := range listNode.Header.NumOfItems {
if !yield(listNode.Items[i]) {
return
}
}

stack = append(stack, listNode.Items[uint64(len(listNode.Items))-listNode.Header.NumOfSideLists:]...)
}
}
}

// Nodes returns list of nodes used by the list.
func (l *List) Nodes() []types.NodeAddress {
if *l.config.Item == 0 {
return nil
}

nodes := []types.NodeAddress{}
stack := []types.NodeAddress{*l.config.Item}

for {
if len(stack) == 0 {
sort.Slice(nodes, func(i, j int) bool {
return nodes[i] < nodes[j]
})

return nodes
}

n := stack[len(stack)-1]
stack = stack[:len(stack)-1]
nodes = append(nodes, n)

_, listNode := l.config.NodeAllocator.Get(n)
stack = append(stack, listNode.Items[uint64(len(listNode.Items))-listNode.Header.NumOfSideLists:]...)
}
}
58 changes: 58 additions & 0 deletions list/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package list_test

import (
"github.com/samber/lo"
"github.com/stretchr/testify/require"

"github.com/outofforest/quantum/alloc"
"github.com/outofforest/quantum/list"
"github.com/outofforest/quantum/space"
"github.com/outofforest/quantum/types"
)

//nolint:unused
func newEnv(requireT *require.Assertions) *env {
allocator := alloc.NewTestAllocator(alloc.NewAllocator(alloc.Config{
TotalSize: 1024 * 1024,
NodeSize: 512,
}))

nodeAllocator, err := list.NewNodeAllocator(allocator)
requireT.NoError(err)

return &env{
Allocator: allocator,
Item: lo.ToPtr[types.NodeAddress](0),
nodeAllocator: nodeAllocator,
}
}

//nolint:unused
type env struct {
Allocator *alloc.TestAllocator
Item *types.NodeAddress

snapshotID types.SnapshotID
nodeAllocator list.NodeAllocator
}

//nolint:unused
func (e *env) NextSnapshot() *list.List {
snapshotID := e.snapshotID
e.snapshotID++

itemCopy := *e.Item
e.Item = &itemCopy

return list.New(list.Config{
SnapshotID: snapshotID,
Item: e.Item,
NodeAllocator: e.nodeAllocator,
Allocator: alloc.NewSnapshotAllocator(
snapshotID,
e.Allocator,
&space.Space[types.SnapshotID, types.NodeAddress]{},
e.nodeAllocator,
),
})
}
41 changes: 41 additions & 0 deletions space/space.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package space

import (
"sort"

"github.com/cespare/xxhash"

"github.com/outofforest/photon"
Expand Down Expand Up @@ -191,6 +193,45 @@ func (s *Space[K, V]) Iterator() func(func(types.DataItem[K, V]) bool) {
}
}

// Nodes returns list of nodes used by the space.
func (s *Space[K, V]) Nodes() []types.NodeAddress {
switch *s.config.SpaceRoot.State {
case types.StateFree:
return nil
case types.StateData:
return []types.NodeAddress{*s.config.SpaceRoot.Item}
case types.StatePointer:
}

nodes := []types.NodeAddress{}
stack := []types.NodeAddress{*s.config.SpaceRoot.Item}

for {
if len(stack) == 0 {
sort.Slice(nodes, func(i, j int) bool {
return nodes[i] < nodes[j]
})

return nodes
}

n := stack[len(stack)-1]
stack = stack[:len(stack)-1]
nodes = append(nodes, n)

_, pointerNode := s.config.PointerNodeAllocator.Get(n)
for i, state := range pointerNode.States {
switch state {
case types.StateFree:
case types.StateData:
nodes = append(nodes, pointerNode.Items[i])
case types.StatePointer:
stack = append(stack, pointerNode.Items[i])
}
}
}
}

func (s *Space[K, V]) set(pInfo types.ParentInfo, item types.DataItem[K, V]) error {
for {
switch *pInfo.State {
Expand Down
Loading

0 comments on commit 45c9d60

Please sign in to comment.