Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detailed tests for used nodes #25

Merged
merged 3 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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