Compare commits

..

15 commits

Author SHA1 Message Date
17bed735a1 [#20] Update api version
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-17 11:10:12 +03:00
022f818735 [#20] Remove storage groups
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-17 11:10:08 +03:00
d989c8d2a3 [#54] *: Fix linter warnings
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-11 15:21:27 +03:00
0671f42ee1 [#54] .forgejo: Add DCO action
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-11 15:21:27 +03:00
9a7b47d769 [#50] util: Use protowire for util/proto helpers
* Use methods to calculate size

Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-10 16:40:53 +00:00
67b18d3550 [#53] Bump min go version to go1.20
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-09 09:55:51 +03:00
964c3edb3f [#51] *: Do not panic in StableSize()
After #49 it can be called on nil structures.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-02 10:55:10 +03:00
3072090c77 [#51] protogen: Do not panic in StableSize()
Refs TrueCloudLab/frostfs-node#554 .

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-02 10:47:14 +03:00
7a5ee927c8 [#49] util/proto: Do not allocate in StringSize()
It was not catched by the test because most of the time the function is
inlined. However, I've seen it allocating with pprof in one of the
earlier builds.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-26 18:52:59 +03:00
7133a01ccf [#49] message/test: Add test for zero-alloc StableSize()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-26 18:32:17 +03:00
43ad0f114c [#49] session: Make StableSize() zero-alloc
For this to work, it is necessary that `NestedStructureSize` is a generic function.
Otherwise, we would allocate to put it in the interface.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-26 18:31:31 +03:00
6e92d7d5de [#49] util/proto: Make NestedStructure* generic
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-26 18:31:23 +03:00
849de02bc3 [#49] util/proto: Calculate repeated field size without allocations
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-26 18:31:23 +03:00
59c8421597 [#49] util/proto: Use StableSize() to determine if the struct is empty
`reflect` is not necessary here, and checking `StableSize` is what we
_want_ anyway.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-26 18:31:00 +03:00
582d94c81c [#47] types: Fix unique flag conversion
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-07-19 13:03:35 +03:00
47 changed files with 163 additions and 443 deletions

View file

@ -0,0 +1,21 @@
name: DCO action
on: [pull_request]
jobs:
dco:
name: DCO
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: Run commit format checker
uses: https://git.frostfs.info/TrueCloudLab/dco-go@v2
with:
from: 'origin/${{ github.event.pull_request.base.ref }}'

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
acl/grpc/types.pb.go generated

Binary file not shown.

BIN
audit/grpc/types.pb.go generated

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
go.mod
View file

@ -1,6 +1,6 @@
module git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 module git.frostfs.info/TrueCloudLab/frostfs-api-go/v2
go 1.19 go 1.20
require ( require (
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0

View file

@ -1,15 +0,0 @@
package random
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
// Uint32 returns random uint32 value [0, max).
func Uint32(max uint32) uint32 {
return rand.Uint32() % max
}

BIN
lock/grpc/types.pb.go generated

Binary file not shown.

View file

@ -198,6 +198,7 @@ func (p *PlacementPolicy) ToGRPCMessage() grpc.Message {
m.SetSelectors(SelectorsToGRPC(p.selectors)) m.SetSelectors(SelectorsToGRPC(p.selectors))
m.SetReplicas(ReplicasToGRPC(p.replicas)) m.SetReplicas(ReplicasToGRPC(p.replicas))
m.SetContainerBackupFactor(p.backupFactor) m.SetContainerBackupFactor(p.backupFactor)
m.SetUnique(p.unique)
} }
return m return m
@ -228,6 +229,8 @@ func (p *PlacementPolicy) FromGRPCMessage(m grpc.Message) error {
p.backupFactor = v.GetContainerBackupFactor() p.backupFactor = v.GetContainerBackupFactor()
p.unique = v.GetUnique()
return nil return nil
} }

Binary file not shown.

Binary file not shown.

View file

@ -20,6 +20,11 @@ func (m *PlacementPolicy) SetFilters(v []*Filter) {
m.Filters = v m.Filters = v
} }
// SetUnique of placement policy.
func (m *PlacementPolicy) SetUnique(unique bool) {
m.Unique = unique
}
// SetName of placement filter. // SetName of placement filter.
func (m *Filter) SetName(v string) { func (m *Filter) SetName(v string) {
m.Name = v m.Name = v

BIN
netmap/grpc/types.pb.go generated

Binary file not shown.

View file

@ -65,6 +65,10 @@ func (f *Filter) StableMarshal(buf []byte) []byte {
} }
func (f *Filter) StableSize() (size int) { func (f *Filter) StableSize() (size int) {
if f == nil {
return 0
}
size += protoutil.StringSize(nameFilterField, f.name) size += protoutil.StringSize(nameFilterField, f.name)
size += protoutil.StringSize(keyFilterField, f.key) size += protoutil.StringSize(keyFilterField, f.key)
size += protoutil.EnumSize(opFilterField, int32(f.op)) size += protoutil.EnumSize(opFilterField, int32(f.op))
@ -101,6 +105,10 @@ func (s *Selector) StableMarshal(buf []byte) []byte {
} }
func (s *Selector) StableSize() (size int) { func (s *Selector) StableSize() (size int) {
if s == nil {
return 0
}
size += protoutil.StringSize(nameSelectorField, s.name) size += protoutil.StringSize(nameSelectorField, s.name)
size += protoutil.UInt32Size(countSelectorField, s.count) size += protoutil.UInt32Size(countSelectorField, s.count)
size += protoutil.EnumSize(countSelectorField, int32(s.clause)) size += protoutil.EnumSize(countSelectorField, int32(s.clause))
@ -132,6 +140,10 @@ func (r *Replica) StableMarshal(buf []byte) []byte {
} }
func (r *Replica) StableSize() (size int) { func (r *Replica) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.UInt32Size(countReplicaField, r.count) size += protoutil.UInt32Size(countReplicaField, r.count)
size += protoutil.StringSize(selectorReplicaField, r.selector) size += protoutil.StringSize(selectorReplicaField, r.selector)
@ -173,6 +185,10 @@ func (p *PlacementPolicy) StableMarshal(buf []byte) []byte {
} }
func (p *PlacementPolicy) StableSize() (size int) { func (p *PlacementPolicy) StableSize() (size int) {
if p == nil {
return 0
}
for i := range p.replicas { for i := range p.replicas {
size += protoutil.NestedStructureSize(replicasPolicyField, &p.replicas[i]) size += protoutil.NestedStructureSize(replicasPolicyField, &p.replicas[i])
} }

View file

@ -102,6 +102,7 @@ func GeneratePlacementPolicy(empty bool) *netmap.PlacementPolicy {
m.SetFilters(GenerateFilters(false)) m.SetFilters(GenerateFilters(false))
m.SetSelectors(GenerateSelectors(false)) m.SetSelectors(GenerateSelectors(false))
m.SetReplicas(GenerateReplicas(false)) m.SetReplicas(GenerateReplicas(false))
m.SetUnique(true)
} }
return m return m

Binary file not shown.

Binary file not shown.

BIN
object/grpc/types.pb.go generated

Binary file not shown.

View file

@ -1,7 +1,9 @@
package objecttest package objecttest
import ( import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/internal/random" "math/rand"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test" refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test"
@ -186,7 +188,7 @@ func GenerateGetResponseBody(empty bool) *object.GetResponseBody {
m := new(object.GetResponseBody) m := new(object.GetResponseBody)
if !empty { if !empty {
switch random.Uint32(3) { switch randomInt(3) {
case 0: case 0:
m.SetObjectPart(GenerateGetObjectPartInit(false)) m.SetObjectPart(GenerateGetObjectPartInit(false))
case 1: case 1:
@ -240,7 +242,7 @@ func GeneratePutRequestBody(empty bool) *object.PutRequestBody {
m := new(object.PutRequestBody) m := new(object.PutRequestBody)
if !empty { if !empty {
switch random.Uint32(2) { switch randomInt(2) {
case 0: case 0:
m.SetObjectPart(GeneratePutObjectPartInit(false)) m.SetObjectPart(GeneratePutObjectPartInit(false))
case 1: case 1:
@ -362,7 +364,7 @@ func GenerateHeadResponseBody(empty bool) *object.HeadResponseBody {
m := new(object.HeadResponseBody) m := new(object.HeadResponseBody)
if !empty { if !empty {
switch random.Uint32(3) { switch randomInt(3) {
case 0: case 0:
m.SetHeaderPart(GenerateHeaderWithSignature(false)) m.SetHeaderPart(GenerateHeaderWithSignature(false))
case 1: case 1:
@ -524,7 +526,7 @@ func GenerateGetRangeResponseBody(empty bool) *object.GetRangeResponseBody {
m := new(object.GetRangeResponseBody) m := new(object.GetRangeResponseBody)
if !empty { if !empty {
switch random.Uint32(2) { switch randomInt(2) {
case 0: case 0:
m.SetRangePart(GenerateGetRangePartChunk(false)) m.SetRangePart(GenerateGetRangePartChunk(false))
case 1: case 1:
@ -642,3 +644,7 @@ func GeneratePutSingleResponse(empty bool) *object.PutSingleResponse {
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
return m return m
} }
func randomInt(n int) int {
return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n)
}

View file

@ -324,7 +324,7 @@ type PutSingleResponse struct {
const ( const (
TypeRegular Type = iota TypeRegular Type = iota
TypeTombstone TypeTombstone
TypeStorageGroup _
TypeLock TypeLock
) )

BIN
refs/grpc/types.pb.go generated

Binary file not shown.

View file

@ -6,6 +6,7 @@ import (
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc" refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
"google.golang.org/protobuf/encoding/protowire"
) )
const ( const (
@ -116,7 +117,7 @@ func (o *ObjectID) StableSize() int {
// ObjectIDNestedListMarshal writes protobuf repeated ObjectID field // ObjectIDNestedListMarshal writes protobuf repeated ObjectID field
// with fNum number to buf. // with fNum number to buf.
func ObjectIDNestedListMarshal(fNum int64, buf []byte, ids []ObjectID) (off int) { func ObjectIDNestedListMarshal(fNum int64, buf []byte, ids []ObjectID) (off int) {
prefix, _ := proto.NestedStructurePrefix(fNum) prefix := protowire.EncodeTag(protowire.Number(fNum), protowire.BytesType)
for i := range ids { for i := range ids {
off += binary.PutUvarint(buf[off:], prefix) off += binary.PutUvarint(buf[off:], prefix)

View file

@ -17,6 +17,7 @@ type jsonMessage interface {
type binaryMessage interface { type binaryMessage interface {
StableMarshal([]byte) []byte StableMarshal([]byte) []byte
StableSize() int
Unmarshal([]byte) error Unmarshal([]byte) error
} }
@ -53,6 +54,11 @@ func TestRPCMessage(t *testing.T, msgGens ...func(empty bool) message.Message) {
} }
if bm, ok := msg.(binaryMessage); ok { if bm, ok := msg.(binaryMessage); ok {
t.Run(fmt.Sprintf("%T.StableSize() does no allocations", bm), func(t *testing.T) {
require.Zero(t, testing.AllocsPerRun(1000, func() {
_ = bm.StableSize()
}))
})
t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) { t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) {
data := bm.StableMarshal(nil) data := bm.StableMarshal(nil)

Binary file not shown.

Binary file not shown.

BIN
session/grpc/types.pb.go generated

Binary file not shown.

View file

@ -211,7 +211,7 @@ func (c *ObjectSessionContext) StableMarshal(buf []byte) []byte {
} }
offset := proto.EnumMarshal(objectCtxVerbField, buf, int32(c.verb)) offset := proto.EnumMarshal(objectCtxVerbField, buf, int32(c.verb))
proto.NestedStructureMarshal(objectCtxTargetField, buf[offset:], &objectSessionContextTarget{ proto.NestedStructureMarshal(objectCtxTargetField, buf[offset:], objectSessionContextTarget{
cnr: c.cnr, cnr: c.cnr,
objs: c.objs, objs: c.objs,
}) })
@ -225,7 +225,7 @@ func (c *ObjectSessionContext) StableSize() (size int) {
} }
size += proto.EnumSize(objectCtxVerbField, int32(c.verb)) size += proto.EnumSize(objectCtxVerbField, int32(c.verb))
size += proto.NestedStructureSize(objectCtxTargetField, &objectSessionContextTarget{ size += proto.NestedStructureSize(objectCtxTargetField, objectSessionContextTarget{
cnr: c.cnr, cnr: c.cnr,
objs: c.objs, objs: c.objs,
}) })

View file

@ -1,8 +1,10 @@
package sessiontest package sessiontest
import ( import (
"math/rand"
"time"
acltest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/test" acltest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/test"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/internal/random"
refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test" refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
statustest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/test" statustest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/test"
@ -167,7 +169,7 @@ func GenerateSessionTokenBody(empty bool) *session.TokenBody {
m.SetOwnerID(refstest.GenerateOwnerID(false)) m.SetOwnerID(refstest.GenerateOwnerID(false))
m.SetLifetime(GenerateTokenLifetime(false)) m.SetLifetime(GenerateTokenLifetime(false))
switch random.Uint32(2) { switch randomInt(2) {
case 0: case 0:
m.SetContext(GenerateObjectSessionContext(false)) m.SetContext(GenerateObjectSessionContext(false))
case 1: case 1:
@ -236,3 +238,7 @@ func GenerateXHeaders(empty bool) []session.XHeader {
return xs return xs
} }
func randomInt(n int) int {
return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n)
}

View file

@ -50,10 +50,6 @@ func signServiceRequest(key *ecdsa.PrivateKey, v serviceRequest) error {
if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil { if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil {
return err return err
} }
if err := verifyServiceMessagePart(body, result.GetBodySignature); err != nil {
return fmt.Errorf("DEBUG POINT: could not verify body: %w", err)
}
result.SetOrigin(header) result.SetOrigin(header)
v.SetVerificationHeader(result) v.SetVerificationHeader(result)
return nil return nil

BIN
status/grpc/types.pb.go generated

Binary file not shown.

View file

@ -30,6 +30,10 @@ func (x *Detail) StableMarshal(buf []byte) []byte {
} }
func (x *Detail) StableSize() (size int) { func (x *Detail) StableSize() (size int) {
if x == nil {
return 0
}
size += protoutil.UInt32Size(detailIDFNum, x.id) size += protoutil.UInt32Size(detailIDFNum, x.id)
size += protoutil.BytesSize(detailValueFNum, x.val) size += protoutil.BytesSize(detailValueFNum, x.val)
@ -69,6 +73,10 @@ func (x *Status) StableMarshal(buf []byte) []byte {
} }
func (x *Status) StableSize() (size int) { func (x *Status) StableSize() (size int) {
if x == nil {
return 0
}
size += protoutil.UInt32Size(statusCodeFNum, CodeToGRPC(x.code)) size += protoutil.UInt32Size(statusCodeFNum, CodeToGRPC(x.code))
size += protoutil.StringSize(statusMsgFNum, x.msg) size += protoutil.StringSize(statusMsgFNum, x.msg)

View file

@ -1,59 +0,0 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
sg "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/grpc"
)
func (s *StorageGroup) ToGRPCMessage() grpc.Message {
m := new(sg.StorageGroup)
if s != nil {
m = new(sg.StorageGroup)
m.SetMembers(refs.ObjectIDListToGRPCMessage(s.members))
//nolint:staticcheck
m.SetExpirationEpoch(s.exp)
m.SetValidationDataSize(s.size)
m.SetValidationHash(s.hash.ToGRPCMessage().(*refsGRPC.Checksum))
}
return m
}
func (s *StorageGroup) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*sg.StorageGroup)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
hash := v.GetValidationHash()
if hash == nil {
s.hash = nil
} else {
if s.hash == nil {
s.hash = new(refs.Checksum)
}
err = s.hash.FromGRPCMessage(hash)
if err != nil {
return err
}
}
s.members, err = refs.ObjectIDListFromGRPCMessage(v.GetMembers())
if err != nil {
return err
}
//nolint:staticcheck
s.exp = v.GetExpirationEpoch()
s.size = v.GetValidationDataSize()
return nil
}

View file

@ -1,27 +0,0 @@
package storagegroup
import (
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
)
// SetValidationDataSize sets the total size of the payloads of the storage group.
func (m *StorageGroup) SetValidationDataSize(v uint64) {
m.ValidationDataSize = v
}
// SetValidationHash sets total homomorphic hash of the storage group payloads.
func (m *StorageGroup) SetValidationHash(v *refs.Checksum) {
m.ValidationHash = v
}
// SetExpirationEpoch sets number of the last epoch of the storage group lifetime.
//
// Deprecated: do not use, `expiration_epoch` field is deprecated in protocol.
func (m *StorageGroup) SetExpirationEpoch(v uint64) {
m.ExpirationEpoch = v
}
// SetMembers sets list of the identifiers of the storage group members.
func (m *StorageGroup) SetMembers(v []*refs.ObjectID) {
m.Members = v
}

Binary file not shown.

View file

@ -1,14 +0,0 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
storagegroup "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/grpc"
)
func (s *StorageGroup) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(s)
}
func (s *StorageGroup) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(s, data, new(storagegroup.StorageGroup))
}

View file

@ -1,54 +0,0 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
storagegroup "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
)
const (
sizeField = 1
hashField = 2
expirationField = 3
objectIDsField = 4
)
// StableMarshal marshals unified storage group structure in a protobuf
// compatible way without field order shuffle.
func (s *StorageGroup) StableMarshal(buf []byte) []byte {
if s == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, s.StableSize())
}
var offset int
offset += proto.UInt64Marshal(sizeField, buf[offset:], s.size)
offset += proto.NestedStructureMarshal(hashField, buf[offset:], s.hash)
offset += proto.UInt64Marshal(expirationField, buf[offset:], s.exp)
refs.ObjectIDNestedListMarshal(objectIDsField, buf[offset:], s.members)
return buf
}
// StableSize of storage group structure marshalled by StableMarshal function.
func (s *StorageGroup) StableSize() (size int) {
if s == nil {
return 0
}
size += proto.UInt64Size(sizeField, s.size)
size += proto.NestedStructureSize(hashField, s.hash)
size += proto.UInt64Size(expirationField, s.exp)
size += refs.ObjectIDNestedListSize(objectIDsField, s.members)
return size
}
func (s *StorageGroup) Unmarshal(data []byte) error {
return message.Unmarshal(s, data, new(storagegroup.StorageGroup))
}

View file

@ -1,15 +0,0 @@
package storagegroup_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
messagetest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message/test"
storagegrouptest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup/test"
)
func TestMessageConvert(t *testing.T) {
messagetest.TestRPCMessage(t,
func(empty bool) message.Message { return storagegrouptest.GenerateStorageGroup(empty) },
)
}

View file

@ -1,21 +0,0 @@
package storagegrouptest
import (
refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/storagegroup"
)
func GenerateStorageGroup(empty bool) *storagegroup.StorageGroup {
m := new(storagegroup.StorageGroup)
if !empty {
m.SetValidationDataSize(44)
//nolint:staticcheck
m.SetExpirationEpoch(55)
m.SetMembers(refstest.GenerateObjectIDs(false))
}
m.SetValidationHash(refstest.GenerateChecksum(empty))
return m
}

View file

@ -1,79 +0,0 @@
package storagegroup
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
)
// StorageGroup is a unified structure of StorageGroup
// message from proto definition.
type StorageGroup struct {
size uint64
hash *refs.Checksum
exp uint64
members []refs.ObjectID
}
// GetValidationDataSize of unified storage group structure.
func (s *StorageGroup) GetValidationDataSize() uint64 {
if s != nil {
return s.size
}
return 0
}
// SetValidationDataSize into unified storage group structure.
func (s *StorageGroup) SetValidationDataSize(v uint64) {
s.size = v
}
// GetValidationHash of unified storage group structure.
func (s *StorageGroup) GetValidationHash() *refs.Checksum {
if s != nil {
return s.hash
}
return nil
}
// SetValidationHash into unified storage group structure.
func (s *StorageGroup) SetValidationHash(v *refs.Checksum) {
s.hash = v
}
// GetExpirationEpoch of unified storage group structure.
//
// Deprecated: Do not use.
func (s *StorageGroup) GetExpirationEpoch() uint64 {
if s != nil {
return s.exp
}
return 0
}
// SetExpirationEpoch into unified storage group structure.
//
// Deprecated: Do not use.
func (s *StorageGroup) SetExpirationEpoch(v uint64) {
s.exp = v
}
// GetMembers of unified storage group structure. Members are objects of
// storage group.
func (s *StorageGroup) GetMembers() []refs.ObjectID {
if s != nil {
return s.members
}
return nil
}
// SetMembers into unified storage group structure. Members are objects of
// storage group.
func (s *StorageGroup) SetMembers(v []refs.ObjectID) {
s.members = v
}

Binary file not shown.

View file

@ -10,7 +10,8 @@ import (
"encoding/binary" "encoding/binary"
"math" "math"
"math/bits" "math/bits"
"reflect"
"google.golang.org/protobuf/encoding/protowire"
) )
type ( type (
@ -21,14 +22,22 @@ type (
) )
func BytesMarshal(field int, buf, v []byte) int { func BytesMarshal(field int, buf, v []byte) int {
if len(v) == 0 {
return 0
}
return bytesMarshal(field, buf, v) return bytesMarshal(field, buf, v)
} }
func bytesMarshal(field int, buf, v []byte) int { func BytesSize(field int, v []byte) int {
prefix := field<<3 | 0x2 return bytesSize(field, v)
}
func bytesMarshal[T ~[]byte | ~string](field int, buf []byte, v T) int {
if len(v) == 0 {
return 0
}
return bytesMarshalNoCheck(field, buf, v)
}
func bytesMarshalNoCheck[T ~[]byte | ~string](field int, buf []byte, v T) int {
prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType)
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -39,26 +48,23 @@ func bytesMarshal(field int, buf, v []byte) int {
return i return i
} }
func BytesSize(field int, v []byte) int { func bytesSize[T ~[]byte | ~string](field int, v T) int {
ln := len(v) if len(v) == 0 {
if ln == 0 {
return 0 return 0
} }
return bytesSize(field, v) return bytesSizeNoCheck(field, v)
} }
func bytesSize(field int, v []byte) int { func bytesSizeNoCheck[T ~[]byte | ~string](field int, v T) int {
prefix := field<<3 | 0x2 return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(len(v)))
return VarUIntSize(uint64(prefix)) + VarUIntSize(uint64(len(v))) + len(v)
} }
func StringMarshal(field int, buf []byte, v string) int { func StringMarshal(field int, buf []byte, v string) int {
return BytesMarshal(field, buf, []byte(v)) return bytesMarshal(field, buf, v)
} }
func StringSize(field int, v string) int { func StringSize(field int, v string) int {
return BytesSize(field, []byte(v)) return bytesSize(field, v)
} }
func BoolMarshal(field int, buf []byte, v bool) int { func BoolMarshal(field int, buf []byte, v bool) int {
@ -66,12 +72,13 @@ func BoolMarshal(field int, buf []byte, v bool) int {
return 0 return 0
} }
prefix := field << 3 prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType)
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
i := binary.PutUvarint(buf, uint64(prefix)) i := binary.PutUvarint(buf, uint64(prefix))
buf[i] = 0x1 const boolTrueValue = 0x1
buf[i] = boolTrueValue
return i + 1 return i + 1
} }
@ -80,10 +87,8 @@ func BoolSize(field int, v bool) int {
if !v { if !v {
return 0 return 0
} }
const boolLength = 1
prefix := field << 3 return protowire.SizeGroup(protowire.Number(field), boolLength)
return VarUIntSize(uint64(prefix)) + 1 // bool is always 1 byte long
} }
func UInt64Marshal(field int, buf []byte, v uint64) int { func UInt64Marshal(field int, buf []byte, v uint64) int {
@ -91,7 +96,7 @@ func UInt64Marshal(field int, buf []byte, v uint64) int {
return 0 return 0
} }
prefix := field << 3 prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType)
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -105,10 +110,7 @@ func UInt64Size(field int, v uint64) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(field), protowire.SizeVarint(v))
prefix := field << 3
return VarUIntSize(uint64(prefix)) + VarUIntSize(v)
} }
func Int64Marshal(field int, buf []byte, v int64) int { func Int64Marshal(field int, buf []byte, v int64) int {
@ -147,7 +149,7 @@ func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int {
var offset int var offset int
for i := range v { for i := range v {
offset += bytesMarshal(field, buf[offset:], v[i]) offset += bytesMarshalNoCheck(field, buf[offset:], v[i])
} }
return offset return offset
@ -155,7 +157,7 @@ func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int {
func RepeatedBytesSize(field int, v [][]byte) (size int) { func RepeatedBytesSize(field int, v [][]byte) (size int) {
for i := range v { for i := range v {
size += bytesSize(field, v[i]) size += bytesSizeNoCheck(field, v[i])
} }
return size return size
@ -165,7 +167,7 @@ func RepeatedStringMarshal(field int, buf []byte, v []string) int {
var offset int var offset int
for i := range v { for i := range v {
offset += bytesMarshal(field, buf[offset:], []byte(v[i])) offset += bytesMarshalNoCheck(field, buf[offset:], v[i])
} }
return offset return offset
@ -173,123 +175,73 @@ func RepeatedStringMarshal(field int, buf []byte, v []string) int {
func RepeatedStringSize(field int, v []string) (size int) { func RepeatedStringSize(field int, v []string) (size int) {
for i := range v { for i := range v {
size += bytesSize(field, []byte(v[i])) size += bytesSizeNoCheck(field, v[i])
} }
return size return size
} }
func RepeatedUInt64Marshal(field int, buf []byte, v []uint64) int { func repeatedUIntSize[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, v []T) (size, arraySize int) {
if len(v) == 0 {
return 0, 0
}
for i := range v {
arraySize += protowire.SizeVarint(uint64(v[i]))
}
size = protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(arraySize))
return
}
func repeatedUIntMarshal[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, buf []byte, v []T) int {
if len(v) == 0 { if len(v) == 0 {
return 0 return 0
} }
prefix := field<<3 | 0x02 prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType)
offset := binary.PutUvarint(buf, uint64(prefix)) offset := binary.PutUvarint(buf, uint64(prefix))
_, arrSize := RepeatedUInt64Size(field, v) _, arrSize := repeatedUIntSize(field, v)
offset += binary.PutUvarint(buf[offset:], uint64(arrSize)) offset += binary.PutUvarint(buf[offset:], uint64(arrSize))
for i := range v { for i := range v {
offset += binary.PutUvarint(buf[offset:], v[i]) offset += binary.PutUvarint(buf[offset:], uint64(v[i]))
} }
return offset return offset
} }
func RepeatedUInt64Marshal(field int, buf []byte, v []uint64) int {
return repeatedUIntMarshal(field, buf, v)
}
func RepeatedUInt64Size(field int, v []uint64) (size, arraySize int) { func RepeatedUInt64Size(field int, v []uint64) (size, arraySize int) {
if len(v) == 0 { return repeatedUIntSize(field, v)
return 0, 0
}
for i := range v {
size += VarUIntSize(v[i])
}
arraySize = size
size += VarUIntSize(uint64(size))
prefix := field<<3 | 0x2
size += VarUIntSize(uint64(prefix))
return size, arraySize
} }
func RepeatedInt64Marshal(field int, buf []byte, v []int64) int { func RepeatedInt64Marshal(field int, buf []byte, v []int64) int {
if len(v) == 0 { return repeatedUIntMarshal(field, buf, v)
return 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Marshal(field, buf, convert)
} }
func RepeatedInt64Size(field int, v []int64) (size, arraySize int) { func RepeatedInt64Size(field int, v []int64) (size, arraySize int) {
if len(v) == 0 { return repeatedUIntSize(field, v)
return 0, 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Size(field, convert)
} }
func RepeatedUInt32Marshal(field int, buf []byte, v []uint32) int { func RepeatedUInt32Marshal(field int, buf []byte, v []uint32) int {
if len(v) == 0 { return repeatedUIntMarshal(field, buf, v)
return 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Marshal(field, buf, convert)
} }
func RepeatedUInt32Size(field int, v []uint32) (size, arraySize int) { func RepeatedUInt32Size(field int, v []uint32) (size, arraySize int) {
if len(v) == 0 { return repeatedUIntSize(field, v)
return 0, 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Size(field, convert)
} }
func RepeatedInt32Marshal(field int, buf []byte, v []int32) int { func RepeatedInt32Marshal(field int, buf []byte, v []int32) int {
if len(v) == 0 { return repeatedUIntMarshal(field, buf, v)
return 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Marshal(field, buf, convert)
} }
func RepeatedInt32Size(field int, v []int32) (size, arraySize int) { func RepeatedInt32Size(field int, v []int32) (size, arraySize int) {
if len(v) == 0 { return repeatedUIntSize(field, v)
return 0, 0
}
convert := make([]uint64, len(v))
for i := range v {
convert[i] = uint64(v[i])
}
return RepeatedUInt64Size(field, convert)
} }
// VarUIntSize returns length of varint byte sequence for uint64 value 'x'. // VarUIntSize returns length of varint byte sequence for uint64 value 'x'.
@ -297,36 +249,27 @@ func VarUIntSize(x uint64) int {
return (bits.Len64(x|1) + 6) / 7 return (bits.Len64(x|1) + 6) / 7
} }
func NestedStructurePrefix(field int64) (prefix uint64, ln int) { func NestedStructureMarshal[T stableMarshaller](field int64, buf []byte, v T) int {
prefix = uint64(field<<3 | 0x02) n := v.StableSize()
return prefix, VarUIntSize(prefix) if n == 0 {
}
func NestedStructureMarshal(field int64, buf []byte, v stableMarshaller) int {
if v == nil || reflect.ValueOf(v).IsNil() {
return 0 return 0
} }
prefix, _ := NestedStructurePrefix(field) prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType)
offset := binary.PutUvarint(buf, prefix) offset := binary.PutUvarint(buf, prefix)
n := v.StableSize()
offset += binary.PutUvarint(buf[offset:], uint64(n)) offset += binary.PutUvarint(buf[offset:], uint64(n))
v.StableMarshal(buf[offset:]) v.StableMarshal(buf[offset:])
return offset + n return offset + n
} }
func NestedStructureSize(field int64, v stableMarshaller) (size int) { func NestedStructureSize[T stableMarshaller](field int64, v T) (size int) {
if v == nil || reflect.ValueOf(v).IsNil() { n := v.StableSize()
if n == 0 {
return 0 return 0
} }
size = protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(n))
_, ln := NestedStructurePrefix(field) return
n := v.StableSize()
size = ln + VarUIntSize(uint64(n)) + n
return size
} }
func Fixed64Marshal(field int, buf []byte, v uint64) int { func Fixed64Marshal(field int, buf []byte, v uint64) int {
@ -334,7 +277,7 @@ func Fixed64Marshal(field int, buf []byte, v uint64) int {
return 0 return 0
} }
prefix := field<<3 | 1 prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type)
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -348,10 +291,7 @@ func Fixed64Size(fNum int, v uint64) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64())
prefix := fNum<<3 | 1
return VarUIntSize(uint64(prefix)) + 8
} }
func Float64Marshal(field int, buf []byte, v float64) int { func Float64Marshal(field int, buf []byte, v float64) int {
@ -359,7 +299,7 @@ func Float64Marshal(field int, buf []byte, v float64) int {
return 0 return 0
} }
prefix := field<<3 | 1 prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type)
i := binary.PutUvarint(buf, uint64(prefix)) i := binary.PutUvarint(buf, uint64(prefix))
binary.LittleEndian.PutUint64(buf[i:], math.Float64bits(v)) binary.LittleEndian.PutUint64(buf[i:], math.Float64bits(v))
@ -371,10 +311,7 @@ func Float64Size(fNum int, v float64) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64())
prefix := fNum<<3 | 1
return VarUIntSize(uint64(prefix)) + 8
} }
// Fixed32Marshal encodes uint32 value to Protocol Buffers fixed32 field with specified number, // Fixed32Marshal encodes uint32 value to Protocol Buffers fixed32 field with specified number,
@ -386,7 +323,7 @@ func Fixed32Marshal(field int, buf []byte, v uint32) int {
return 0 return 0
} }
prefix := field<<3 | 5 prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed32Type)
// buf length check can prevent panic at PutUvarint, but it will make // buf length check can prevent panic at PutUvarint, but it will make
// marshaller a bit slower. // marshaller a bit slower.
@ -402,8 +339,5 @@ func Fixed32Size(fNum int, v uint32) int {
if v == 0 { if v == 0 {
return 0 return 0
} }
return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed32())
prefix := fNum<<3 | 5
return VarUIntSize(uint64(prefix)) + 4
} }

Binary file not shown.

View file

@ -59,6 +59,7 @@ func emitMessage(g *protogen.GeneratedFile, msg *protogen.Message) {
g.P("//") g.P("//")
g.P("// Structures with the same field values have the same binary size.") g.P("// Structures with the same field values have the same binary size.")
g.P("func (x *", msg.GoIdent.GoName, ") StableSize() (size int) {") g.P("func (x *", msg.GoIdent.GoName, ") StableSize() (size int) {")
g.P("if x == nil { return 0 }")
if len(fs) != 0 { if len(fs) != 0 {
for _, f := range fs { for _, f := range fs {
if f.Desc.IsList() && marshalers[f.Desc.Kind()].RepeatedDouble { if f.Desc.IsList() && marshalers[f.Desc.Kind()].RepeatedDouble {