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
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:
parent
eb8b0a6999
commit
1ec5377241
2 changed files with 143 additions and 10 deletions
|
@ -2,11 +2,10 @@ package meta
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"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"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"github.com/VictoriaMetrics/easyproto"
|
||||
)
|
||||
|
@ -174,18 +173,89 @@ func attributeValueRaw(src []byte, attribute string) (attributeMatchResult, erro
|
|||
}
|
||||
|
||||
func parentFromChild(src []byte) ([]byte, error) {
|
||||
child := objectSDK.New()
|
||||
|
||||
err := child.Unmarshal(src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshal child with parent: %w", err)
|
||||
iter := newProtoIter(src, true)
|
||||
for iter.next(); !iter.finished(); iter.next() {
|
||||
if iter.fc.FieldNum == 3 {
|
||||
return parentFromChildHeader(iter.fc)
|
||||
}
|
||||
}
|
||||
|
||||
par := child.Parent()
|
||||
|
||||
if par == nil { // this should never happen though
|
||||
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)]
|
||||
}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
package meta
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
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()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue