From 677755c799c1b6b942349c7d9de836335c7bbf55 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 3 Feb 2023 11:32:52 -0700 Subject: btrfsitem: Have all Item implementations be pointers to structs --- lib/btrfs/btrfsitem/items.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/btrfs/btrfsitem/items.go') diff --git a/lib/btrfs/btrfsitem/items.go b/lib/btrfs/btrfsitem/items.go index 67f96fa..9964e2d 100644 --- a/lib/btrfs/btrfsitem/items.go +++ b/lib/btrfs/btrfsitem/items.go @@ -25,7 +25,7 @@ type Error struct { Err error } -func (Error) isItem() {} +func (*Error) isItem() {} func (o Error) MarshalBinary() ([]byte, error) { return o.Dat, nil @@ -43,7 +43,7 @@ func UnmarshalItem(key btrfsprim.Key, csumType btrfssum.CSumType, dat []byte) It var ok bool gotyp, ok = untypedObjID2gotype[key.ObjectID] if !ok { - return Error{ + return &Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v, ObjectID:%v}, dat): unknown object ID for untyped item", key.ItemType, key.ObjectID), @@ -53,31 +53,31 @@ func UnmarshalItem(key btrfsprim.Key, csumType btrfssum.CSumType, dat []byte) It var ok bool gotyp, ok = keytype2gotype[key.ItemType] if !ok { - return Error{ + return &Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): unknown item type", key.ItemType), } } } - retPtr := reflect.New(gotyp) - if csums, ok := retPtr.Interface().(*ExtentCSum); ok { + ptr := reflect.New(gotyp) + if csums, ok := ptr.Interface().(*ExtentCSum); ok { csums.ChecksumSize = csumType.Size() csums.Addr = btrfsvol.LogicalAddr(key.Offset) } - n, err := binstruct.Unmarshal(dat, retPtr.Interface()) + n, err := binstruct.Unmarshal(dat, ptr.Interface()) if err != nil { - return Error{ + return &Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): %w", key.ItemType, err), } } if n < len(dat) { - return Error{ + return &Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): left over data: got %v bytes but only consumed %v", key.ItemType, len(dat), n), } } //nolint:forcetypeassert // items_gen.go has all types in keytype2gotype implement the Item interface. - return retPtr.Elem().Interface().(Item) + return ptr.Interface().(Item) } -- cgit v1.2.3-2-g168b From 21e92e5dea4d8efc65403eeaee91b32856b86cb6 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 3 Feb 2023 13:04:17 -0700 Subject: btrfsitem: Add `Free` and `CloneItem` methods to Items --- lib/btrfs/btrfsitem/items.go | 55 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 9 deletions(-) (limited to 'lib/btrfs/btrfsitem/items.go') diff --git a/lib/btrfs/btrfsitem/items.go b/lib/btrfs/btrfsitem/items.go index 9964e2d..49d421f 100644 --- a/lib/btrfs/btrfsitem/items.go +++ b/lib/btrfs/btrfsitem/items.go @@ -8,16 +8,21 @@ import ( "fmt" "reflect" + "git.lukeshu.com/go/typedsync" + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" + "git.lukeshu.com/btrfs-progs-ng/lib/containers" ) type Type = btrfsprim.ItemType type Item interface { isItem() + Free() + CloneItem() Item } type Error struct { @@ -25,8 +30,23 @@ type Error struct { Err error } +var errorPool = &typedsync.Pool[*Error]{New: func() *Error { return new(Error) }} + func (*Error) isItem() {} +func (o *Error) Free() { + *o = Error{} + errorPool.Put(o) +} + +func (o Error) Clone() Error { return o } + +func (o *Error) CloneItem() Item { + ret, _ := errorPool.Get() + *ret = *o + return ret +} + func (o Error) MarshalBinary() ([]byte, error) { return o.Dat, nil } @@ -43,41 +63,58 @@ func UnmarshalItem(key btrfsprim.Key, csumType btrfssum.CSumType, dat []byte) It var ok bool gotyp, ok = untypedObjID2gotype[key.ObjectID] if !ok { - return &Error{ + ret, _ := errorPool.Get() + *ret = Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v, ObjectID:%v}, dat): unknown object ID for untyped item", key.ItemType, key.ObjectID), } + return ret } } else { var ok bool gotyp, ok = keytype2gotype[key.ItemType] if !ok { - return &Error{ + ret, _ := errorPool.Get() + *ret = Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): unknown item type", key.ItemType), } + return ret } } - ptr := reflect.New(gotyp) - if csums, ok := ptr.Interface().(*ExtentCSum); ok { + ptr, _ := gotype2pool[gotyp].Get() + if csums, ok := ptr.(*ExtentCSum); ok { csums.ChecksumSize = csumType.Size() csums.Addr = btrfsvol.LogicalAddr(key.Offset) } - n, err := binstruct.Unmarshal(dat, ptr.Interface()) + n, err := binstruct.Unmarshal(dat, ptr) if err != nil { - return &Error{ + ptr.Free() + ret, _ := errorPool.Get() + *ret = Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): %w", key.ItemType, err), } + return ret } if n < len(dat) { - return &Error{ + ptr.Free() + ret, _ := errorPool.Get() + *ret = Error{ Dat: dat, Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): left over data: got %v bytes but only consumed %v", key.ItemType, len(dat), n), } + return ret } - //nolint:forcetypeassert // items_gen.go has all types in keytype2gotype implement the Item interface. - return ptr.Interface().(Item) + return ptr +} + +var bytePool containers.SlicePool[byte] + +func cloneBytes(in []byte) []byte { + out := bytePool.Get(len(in)) + copy(out, in) + return out } -- cgit v1.2.3-2-g168b