summaryrefslogtreecommitdiff
path: root/lib/btrfs/btrfsitem/items.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfs/btrfsitem/items.go')
-rw-r--r--lib/btrfs/btrfsitem/items.go55
1 files changed, 46 insertions, 9 deletions
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
}