m
Some checks failed
DCO action / DCO (pull_request) Failing after 32s
Vulncheck / Vulncheck (pull_request) Successful in 1m10s
Pre-commit hooks / Pre-commit (pull_request) Successful in 1m31s
Tests and linters / Lint (pull_request) Failing after 1m59s
Tests and linters / Staticcheck (pull_request) Failing after 1m55s
Tests and linters / Tests (pull_request) Failing after 1m57s
Build / Build Components (pull_request) Successful in 2m13s
Tests and linters / Tests with -race (pull_request) Failing after 3m25s
Tests and linters / gopls check (pull_request) Successful in 3m44s
Tests and linters / Run gofumpt (pull_request) Successful in 4m37s

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2025-03-20 14:57:24 +03:00
parent eb8b0a6999
commit 1ec5377241
Signed by: fyrchik
SSH key fingerprint: SHA256:m/TTwCzjnRkXgnzEx9X92ccxy1CcVeinOgDb3NPWWmg
2 changed files with 143 additions and 10 deletions

View file

@ -2,11 +2,10 @@ package meta
import ( import (
"errors" "errors"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/VictoriaMetrics/easyproto" "github.com/VictoriaMetrics/easyproto"
) )
@ -174,18 +173,89 @@ func attributeValueRaw(src []byte, attribute string) (attributeMatchResult, erro
} }
func parentFromChild(src []byte) ([]byte, error) { func parentFromChild(src []byte) ([]byte, error) {
child := objectSDK.New() iter := newProtoIter(src, true)
for iter.next(); !iter.finished(); iter.next() {
err := child.Unmarshal(src) if iter.fc.FieldNum == 3 {
if err != nil { return parentFromChildHeader(iter.fc)
return nil, fmt.Errorf("unmarshal child with parent: %w", err) }
} }
par := child.Parent()
if par == nil { // this should never happen though
return nil, logicerr.Wrap(new(apistatus.ObjectNotFound)) return nil, logicerr.Wrap(new(apistatus.ObjectNotFound))
} }
return par.Marshal() func parentFromChildHeader(fc easyproto.FieldContext) ([]byte, error) {
iter := newProtoIter(fc.MessageData())
for iter.next(); !iter.finished(); iter.next() {
if iter.fc.FieldNum == 11 {
return parentFromSplitHeader(iter.fc)
}
}
return nil, logicerr.Wrap(new(apistatus.ObjectNotFound))
}
func parentFromSplitHeader(fc easyproto.FieldContext) ([]byte, error) {
iter := newProtoIter(fc.MessageData())
var parentID, parentSig, parentHdr []byte
for iter.next(); !iter.finished(); iter.next() {
var ok bool
switch iter.fc.FieldNum {
case 1: // parent id
parentID, ok = iter.fc.MessageData()
case 3: // parent signature
parentSig, ok = iter.fc.MessageData()
case 4: // parent header
parentHdr, ok = iter.fc.MessageData()
default:
continue
}
if !ok {
return nil, errMalformedObject
}
}
if parentSig == nil || parentHdr == nil {
return nil, logicerr.Wrap(new(apistatus.ObjectNotFound))
}
h := &header{
parentID: parentID,
parentSig: parentSig,
parentHdr: parentHdr,
}
return h.StableMarshal(make([]byte, h.StableSize())), nil
}
type (
header struct {
parentID bs
parentSig bs
parentHdr bs
}
)
func (o *header) StableSize() int {
var size int
size += proto.NestedStructureSize(1, &o.parentID)
size += proto.NestedStructureSize(2, &o.parentSig)
size += proto.NestedStructureSize(3, &o.parentHdr)
return size
}
func (o *header) StableMarshal(buf []byte) []byte {
var offset int
offset += proto.NestedStructureMarshal(1, buf[offset:], &o.parentID)
offset += proto.NestedStructureMarshal(2, buf[offset:], &o.parentSig)
offset += proto.NestedStructureMarshal(3, buf[offset:], &o.parentHdr)
return buf[:offset]
}
type bs []byte
func (b *bs) StableSize() int {
return len(*b)
}
func (b *bs) StableMarshal(dst []byte) []byte {
copy(dst, *b)
return dst[:len(*b)]
} }

View file

@ -1,10 +1,16 @@
package meta package meta
import ( import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
"strconv" "strconv"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
@ -36,3 +42,60 @@ func TestAttributeValueRaw_ZeroAlloc(t *testing.T) {
} }
})) }))
} }
func BenchmarkParentFromChild(b *testing.B) {
cnr := cidtest.ID()
parent := testutil.GenerateObjectWithCIDWithPayload(cnr, nil)
parent.SetPayloadSize(1234)
pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(b, err)
require.NoError(b, objectSDK.CalculateAndSetSignature(*pk, parent))
child := testutil.GenerateObjectWithCID(cnr)
child.SetParent(parent)
data, err := child.Marshal()
require.NoError(b, err)
o1, err := parentFromChildUnoptimized(data)
require.NoError(b, err)
o2, err := parentFromChild(data)
require.NoError(b, err)
require.Equal(b, o1, o2)
b.Run("unoptimized", func(b *testing.B) {
for range b.N {
_, err := parentFromChildUnoptimized(data)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("proto access", func(b *testing.B) {
for range b.N {
_, err := parentFromChild(data)
if err != nil {
b.Fatal(err)
}
}
})
}
func parentFromChildUnoptimized(src []byte) ([]byte, error) {
child := objectSDK.New()
err := child.Unmarshal(src)
if err != nil {
return nil, fmt.Errorf("unmarshal child with parent: %w", err)
}
par := child.Parent()
if par == nil { // this should never happen though
return nil, logicerr.Wrap(new(apistatus.ObjectNotFound))
}
return par.Marshal()
}