[#230] pkg: Implement storage group type with basic methods
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
37e2cab93b
commit
6861de042b
2 changed files with 226 additions and 0 deletions
147
pkg/storagegroup/storagegroup.go
Normal file
147
pkg/storagegroup/storagegroup.go
Normal file
|
@ -0,0 +1,147 @@
|
|||
package storagegroup
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/storagegroup"
|
||||
)
|
||||
|
||||
// StorageGroup represents v2-compatible storage group.
|
||||
type StorageGroup storagegroup.StorageGroup
|
||||
|
||||
// NewFromV2 wraps v2 StorageGroup message to StorageGroup.
|
||||
func NewFromV2(aV2 *storagegroup.StorageGroup) *StorageGroup {
|
||||
return (*StorageGroup)(aV2)
|
||||
}
|
||||
|
||||
// New creates and initializes blank StorageGroup.
|
||||
func New() *StorageGroup {
|
||||
return NewFromV2(new(storagegroup.StorageGroup))
|
||||
}
|
||||
|
||||
// ValidationDataSize returns total size of the payloads
|
||||
// of objects in the storage group
|
||||
func (sg *StorageGroup) ValidationDataSize() uint64 {
|
||||
return (*storagegroup.StorageGroup)(sg).
|
||||
GetValidationDataSize()
|
||||
}
|
||||
|
||||
// SetValidationDataSize sets total size of the payloads
|
||||
// of objects in the storage group.
|
||||
func (sg *StorageGroup) SetValidationDataSize(epoch uint64) {
|
||||
(*storagegroup.StorageGroup)(sg).
|
||||
SetValidationDataSize(epoch)
|
||||
}
|
||||
|
||||
// ValidationDataHash returns homomorphic hash from the
|
||||
// concatenation of the payloads of the storage group members.
|
||||
func (sg *StorageGroup) ValidationDataHash() *pkg.Checksum {
|
||||
return pkg.NewChecksumFromV2(
|
||||
(*storagegroup.StorageGroup)(sg).
|
||||
GetValidationHash(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetValidationDataHash sets homomorphic hash from the
|
||||
// concatenation of the payloads of the storage group members.
|
||||
func (sg *StorageGroup) SetValidationDataHash(hash *pkg.Checksum) {
|
||||
(*storagegroup.StorageGroup)(sg).
|
||||
SetValidationHash(hash.ToV2())
|
||||
}
|
||||
|
||||
// ExpirationEpoch returns last NeoFS epoch number
|
||||
// of the storage group lifetime.
|
||||
func (sg *StorageGroup) ExpirationEpoch() uint64 {
|
||||
return (*storagegroup.StorageGroup)(sg).
|
||||
GetExpirationEpoch()
|
||||
}
|
||||
|
||||
// SetExpirationEpoch sets last NeoFS epoch number
|
||||
// of the storage group lifetime.
|
||||
func (sg *StorageGroup) SetExpirationEpoch(epoch uint64) {
|
||||
(*storagegroup.StorageGroup)(sg).
|
||||
SetExpirationEpoch(epoch)
|
||||
}
|
||||
|
||||
// Members returns strictly ordered list of
|
||||
// storage group member objects.
|
||||
func (sg *StorageGroup) Members() []*object.ID {
|
||||
mV2 := (*storagegroup.StorageGroup)(sg).
|
||||
GetMembers()
|
||||
|
||||
if mV2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := make([]*object.ID, len(mV2))
|
||||
|
||||
for i := range mV2 {
|
||||
m[i] = object.NewIDFromV2(mV2[i])
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// SetMembers sets strictly ordered list of
|
||||
// storage group member objects.
|
||||
func (sg *StorageGroup) SetMembers(members []*object.ID) {
|
||||
mV2 := (*storagegroup.StorageGroup)(sg).
|
||||
GetMembers()
|
||||
|
||||
if members == nil {
|
||||
mV2 = nil
|
||||
} else {
|
||||
ln := len(members)
|
||||
|
||||
if cap(mV2) >= ln {
|
||||
mV2 = mV2[:0]
|
||||
} else {
|
||||
mV2 = make([]*refs.ObjectID, 0, ln)
|
||||
}
|
||||
|
||||
for i := 0; i < ln; i++ {
|
||||
mV2 = append(mV2, members[i].ToV2())
|
||||
}
|
||||
}
|
||||
|
||||
(*storagegroup.StorageGroup)(sg).
|
||||
SetMembers(mV2)
|
||||
}
|
||||
|
||||
// ToV2 converts StorageGroup to v2 StorageGroup message.
|
||||
func (sg *StorageGroup) ToV2() *storagegroup.StorageGroup {
|
||||
return (*storagegroup.StorageGroup)(sg)
|
||||
}
|
||||
|
||||
// Marshal marshals StorageGroup into a protobuf binary form.
|
||||
//
|
||||
// Buffer is allocated when the argument is empty.
|
||||
// Otherwise, the first buffer is used.
|
||||
func (sg *StorageGroup) Marshal(b ...[]byte) ([]byte, error) {
|
||||
var buf []byte
|
||||
if len(b) > 0 {
|
||||
buf = b[0]
|
||||
}
|
||||
|
||||
return (*storagegroup.StorageGroup)(sg).
|
||||
StableMarshal(buf)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of StorageGroup.
|
||||
func (sg *StorageGroup) Unmarshal(data []byte) error {
|
||||
return (*storagegroup.StorageGroup)(sg).
|
||||
Unmarshal(data)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes StorageGroup to protobuf JSON format.
|
||||
func (sg *StorageGroup) MarshalJSON() ([]byte, error) {
|
||||
return (*storagegroup.StorageGroup)(sg).
|
||||
MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes StorageGroup from protobuf JSON format.
|
||||
func (sg *StorageGroup) UnmarshalJSON(data []byte) error {
|
||||
return (*storagegroup.StorageGroup)(sg).
|
||||
UnmarshalJSON(data)
|
||||
}
|
79
pkg/storagegroup/storagegroup_test.go
Normal file
79
pkg/storagegroup/storagegroup_test.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package storagegroup_test
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/storagegroup"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testSHA256() (cs [sha256.Size]byte) {
|
||||
_, _ = rand.Read(cs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func testChecksum() *pkg.Checksum {
|
||||
h := pkg.NewChecksum()
|
||||
h.SetSHA256(testSHA256())
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func testOID() *object.ID {
|
||||
id := object.NewID()
|
||||
id.SetSHA256(testSHA256())
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func TestStorageGroup(t *testing.T) {
|
||||
sg := storagegroup.New()
|
||||
|
||||
sz := uint64(13)
|
||||
sg.SetValidationDataSize(sz)
|
||||
require.Equal(t, sz, sg.ValidationDataSize())
|
||||
|
||||
cs := testChecksum()
|
||||
sg.SetValidationDataHash(cs)
|
||||
require.Equal(t, cs, sg.ValidationDataHash())
|
||||
|
||||
exp := uint64(33)
|
||||
sg.SetExpirationEpoch(exp)
|
||||
require.Equal(t, exp, sg.ExpirationEpoch())
|
||||
|
||||
members := []*object.ID{testOID(), testOID()}
|
||||
sg.SetMembers(members)
|
||||
require.Equal(t, members, sg.Members())
|
||||
}
|
||||
|
||||
func TestStorageGroupEncoding(t *testing.T) {
|
||||
sg := storagegroup.New()
|
||||
sg.SetValidationDataSize(13)
|
||||
sg.SetValidationDataHash(testChecksum())
|
||||
sg.SetExpirationEpoch(33)
|
||||
sg.SetMembers([]*object.ID{testOID(), testOID()})
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
data, err := sg.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
sg2 := storagegroup.New()
|
||||
require.NoError(t, sg2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, sg, sg2)
|
||||
})
|
||||
|
||||
t.Run("json", func(t *testing.T) {
|
||||
data, err := sg.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
sg2 := storagegroup.New()
|
||||
require.NoError(t, sg2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, sg, sg2)
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue