forked from TrueCloudLab/frostfs-api-go
[#233] Implement data audit result type with basic methods
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>support/v2.15
parent
3039aa20c7
commit
9986a4ecd1
|
@ -0,0 +1,258 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/audit"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
)
|
||||
|
||||
// Result represents v2-compatible data audit result.
|
||||
type Result audit.DataAuditResult
|
||||
|
||||
// NewFromV2 wraps v2 DataAuditResult message to Result.
|
||||
func NewResultFromV2(aV2 *audit.DataAuditResult) *Result {
|
||||
return (*Result)(aV2)
|
||||
}
|
||||
|
||||
// New creates and initializes blank Result.
|
||||
func NewResult() *Result {
|
||||
return NewResultFromV2(new(audit.DataAuditResult))
|
||||
}
|
||||
|
||||
// ToV2 converts Result to v2 DataAuditResult message.
|
||||
func (r *Result) ToV2() *audit.DataAuditResult {
|
||||
return (*audit.DataAuditResult)(r)
|
||||
}
|
||||
|
||||
// Marshal marshals Result into a protobuf binary form.
|
||||
//
|
||||
// Buffer is allocated when the argument is empty.
|
||||
// Otherwise, the first buffer is used.
|
||||
func (r *Result) Marshal(b ...[]byte) ([]byte, error) {
|
||||
var buf []byte
|
||||
if len(b) > 0 {
|
||||
buf = b[0]
|
||||
}
|
||||
|
||||
return (*audit.DataAuditResult)(r).
|
||||
StableMarshal(buf)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of Result.
|
||||
func (r *Result) Unmarshal(data []byte) error {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
Unmarshal(data)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Result to protobuf JSON format.
|
||||
func (r *Result) MarshalJSON() ([]byte, error) {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Result from protobuf JSON format.
|
||||
func (r *Result) UnmarshalJSON(data []byte) error {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
UnmarshalJSON(data)
|
||||
}
|
||||
|
||||
// AuditEpoch returns epoch number when the Data Audit was conducted.
|
||||
func (r *Result) AuditEpoch() uint64 {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
GetAuditEpoch()
|
||||
}
|
||||
|
||||
// SetAuditEpoch sets epoch number when the Data Audit was conducted.
|
||||
func (r *Result) SetAuditEpoch(epoch uint64) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetAuditEpoch(epoch)
|
||||
}
|
||||
|
||||
// ContainerID returns container under audit.
|
||||
func (r *Result) ContainerID() *container.ID {
|
||||
return container.NewIDFromV2(
|
||||
(*audit.DataAuditResult)(r).
|
||||
GetContainerID(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetContainerID sets container under audit.
|
||||
func (r *Result) SetContainerID(id *container.ID) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetContainerID(id.ToV2())
|
||||
}
|
||||
|
||||
// PublicKey returns public key of the auditing InnerRing node in a binary format.
|
||||
func (r *Result) PublicKey() []byte {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
GetPublicKey()
|
||||
}
|
||||
|
||||
// SetPublicKey sets public key of the auditing InnerRing node in a binary format.
|
||||
func (r *Result) SetPublicKey(key []byte) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetPublicKey(key)
|
||||
}
|
||||
|
||||
// PassSG returns list of Storage Groups that passed audit PoR stage.
|
||||
func (r *Result) PassSG() []*object.ID {
|
||||
mV2 := (*audit.DataAuditResult)(r).
|
||||
GetPassSG()
|
||||
|
||||
if mV2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := make([]*object.ID, len(mV2))
|
||||
|
||||
for i := range mV2 {
|
||||
m[i] = object.NewIDFromV2(mV2[i])
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// SetPassSG sets list of Storage Groups that passed audit PoR stage.
|
||||
func (r *Result) SetPassSG(list []*object.ID) {
|
||||
mV2 := (*audit.DataAuditResult)(r).
|
||||
GetPassSG()
|
||||
|
||||
if list == nil {
|
||||
mV2 = nil
|
||||
} else {
|
||||
ln := len(list)
|
||||
|
||||
if cap(mV2) >= ln {
|
||||
mV2 = mV2[:0]
|
||||
} else {
|
||||
mV2 = make([]*refs.ObjectID, 0, ln)
|
||||
}
|
||||
|
||||
for i := 0; i < ln; i++ {
|
||||
mV2 = append(mV2, list[i].ToV2())
|
||||
}
|
||||
}
|
||||
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetPassSG(mV2)
|
||||
}
|
||||
|
||||
// FailSG returns list of Storage Groups that failed audit PoR stage.
|
||||
func (r *Result) FailSG() []*object.ID {
|
||||
mV2 := (*audit.DataAuditResult)(r).
|
||||
GetFailSG()
|
||||
|
||||
if mV2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := make([]*object.ID, len(mV2))
|
||||
|
||||
for i := range mV2 {
|
||||
m[i] = object.NewIDFromV2(mV2[i])
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// SetFailSG sets list of Storage Groups that failed audit PoR stage.
|
||||
func (r *Result) SetFailSG(list []*object.ID) {
|
||||
mV2 := (*audit.DataAuditResult)(r).
|
||||
GetFailSG()
|
||||
|
||||
if list == nil {
|
||||
mV2 = nil
|
||||
} else {
|
||||
ln := len(list)
|
||||
|
||||
if cap(mV2) >= ln {
|
||||
mV2 = mV2[:0]
|
||||
} else {
|
||||
mV2 = make([]*refs.ObjectID, 0, ln)
|
||||
}
|
||||
|
||||
for i := 0; i < ln; i++ {
|
||||
mV2 = append(mV2, list[i].ToV2())
|
||||
}
|
||||
}
|
||||
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetFailSG(mV2)
|
||||
}
|
||||
|
||||
// Hit returns number of sampled objects under audit placed
|
||||
// in an optimal way according to the containers placement policy
|
||||
// when checking PoP.
|
||||
func (r *Result) Hit() uint32 {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
GetHit()
|
||||
}
|
||||
|
||||
// SetHit sets number of sampled objects under audit placed
|
||||
// in an optimal way according to the containers placement policy
|
||||
// when checking PoP.
|
||||
func (r *Result) SetHit(hit uint32) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetHit(hit)
|
||||
}
|
||||
|
||||
// Miss returns number of sampled objects under audit placed
|
||||
// in suboptimal way according to the containers placement policy,
|
||||
// but still at a satisfactory level when checking PoP.
|
||||
func (r *Result) Miss() uint32 {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
GetMiss()
|
||||
}
|
||||
|
||||
// SetMiss sets number of sampled objects under audit placed
|
||||
// in suboptimal way according to the containers placement policy,
|
||||
// but still at a satisfactory level when checking PoP.
|
||||
func (r *Result) SetMiss(miss uint32) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetMiss(miss)
|
||||
}
|
||||
|
||||
// Fail returns number of sampled objects under audit stored
|
||||
// in a way not confirming placement policy or not found at all
|
||||
// when checking PoP.
|
||||
func (r *Result) Fail() uint32 {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
GetFail()
|
||||
}
|
||||
|
||||
// SetFail sets number of sampled objects under audit stored
|
||||
// in a way not confirming placement policy or not found at all
|
||||
// when checking PoP.
|
||||
func (r *Result) SetFail(fail uint32) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetFail(fail)
|
||||
}
|
||||
|
||||
// PassNodes returns list of storage node public keys that
|
||||
// passed at least one PDP.
|
||||
func (r *Result) PassNodes() [][]byte {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
GetPassNodes()
|
||||
}
|
||||
|
||||
// SetPassNodes sets list of storage node public keys that
|
||||
// passed at least one PDP.
|
||||
func (r *Result) SetPassNodes(list [][]byte) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetPassNodes(list)
|
||||
}
|
||||
|
||||
// FailNodes returns list of storage node public keys that
|
||||
// failed at least one PDP.
|
||||
func (r *Result) FailNodes() [][]byte {
|
||||
return (*audit.DataAuditResult)(r).
|
||||
GetFailNodes()
|
||||
}
|
||||
|
||||
// SetFailNodes sets list of storage node public keys that
|
||||
// failed at least one PDP.
|
||||
func (r *Result) SetFailNodes(list [][]byte) {
|
||||
(*audit.DataAuditResult)(r).
|
||||
SetFailNodes(list)
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package audit_test
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/audit"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testSHA256() (cs [sha256.Size]byte) {
|
||||
_, _ = rand.Read(cs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func testCID() *container.ID {
|
||||
cid := container.NewID()
|
||||
cid.SetSHA256(testSHA256())
|
||||
|
||||
return cid
|
||||
}
|
||||
|
||||
func testOID() *object.ID {
|
||||
id := object.NewID()
|
||||
id.SetSHA256(testSHA256())
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func TestResult(t *testing.T) {
|
||||
r := audit.NewResult()
|
||||
|
||||
epoch := uint64(13)
|
||||
r.SetAuditEpoch(epoch)
|
||||
require.Equal(t, epoch, r.AuditEpoch())
|
||||
|
||||
cid := testCID()
|
||||
r.SetContainerID(cid)
|
||||
require.Equal(t, cid, r.ContainerID())
|
||||
|
||||
key := []byte{1, 2, 3}
|
||||
r.SetPublicKey(key)
|
||||
require.Equal(t, key, r.PublicKey())
|
||||
|
||||
passSG := []*object.ID{testOID(), testOID()}
|
||||
r.SetPassSG(passSG)
|
||||
require.Equal(t, passSG, r.PassSG())
|
||||
|
||||
failSG := []*object.ID{testOID(), testOID()}
|
||||
r.SetFailSG(failSG)
|
||||
require.Equal(t, failSG, r.FailSG())
|
||||
|
||||
hit := uint32(1)
|
||||
r.SetHit(hit)
|
||||
require.Equal(t, hit, r.Hit())
|
||||
|
||||
miss := uint32(2)
|
||||
r.SetMiss(miss)
|
||||
require.Equal(t, miss, r.Miss())
|
||||
|
||||
fail := uint32(3)
|
||||
r.SetFail(fail)
|
||||
require.Equal(t, fail, r.Fail())
|
||||
|
||||
passNodes := [][]byte{{1}, {2}}
|
||||
r.SetPassNodes(passNodes)
|
||||
require.Equal(t, passNodes, r.PassNodes())
|
||||
|
||||
failNodes := [][]byte{{3}, {4}}
|
||||
r.SetFailNodes(failNodes)
|
||||
require.Equal(t, failNodes, r.FailNodes())
|
||||
}
|
||||
|
||||
func TestStorageGroupEncoding(t *testing.T) {
|
||||
r := audit.NewResult()
|
||||
r.SetAuditEpoch(13)
|
||||
r.SetContainerID(testCID())
|
||||
r.SetPublicKey([]byte{1, 2, 3})
|
||||
r.SetPassSG([]*object.ID{testOID(), testOID()})
|
||||
r.SetFailSG([]*object.ID{testOID(), testOID()})
|
||||
r.SetHit(1)
|
||||
r.SetMiss(2)
|
||||
r.SetFail(3)
|
||||
r.SetPassNodes([][]byte{{1}, {2}})
|
||||
r.SetFailNodes([][]byte{{3}, {4}})
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
data, err := r.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
r2 := audit.NewResult()
|
||||
require.NoError(t, r2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, r, r2)
|
||||
})
|
||||
|
||||
t.Run("json", func(t *testing.T) {
|
||||
data, err := r.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
r2 := audit.NewResult()
|
||||
require.NoError(t, r2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, r, r2)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
audit "github.com/nspcc-dev/neofs-api-go/v2/audit/grpc"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
)
|
||||
|
||||
// DataAuditResultToGRPCMessage converts unified DataAuditResult structure
|
||||
// into gRPC DataAuditResult message.
|
||||
func DataAuditResultToGRPCMessage(a *DataAuditResult) *audit.DataAuditResult {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := new(audit.DataAuditResult)
|
||||
|
||||
m.SetAuditEpoch(a.GetAuditEpoch())
|
||||
|
||||
m.SetContainerId(
|
||||
refs.ContainerIDToGRPCMessage(a.GetContainerID()),
|
||||
)
|
||||
|
||||
m.SetPublicKey(a.GetPublicKey())
|
||||
|
||||
m.SetPassSg(
|
||||
refs.ObjectIDListToGRPCMessage(a.GetPassSG()),
|
||||
)
|
||||
|
||||
m.SetFailSg(
|
||||
refs.ObjectIDListToGRPCMessage(a.GetFailSG()),
|
||||
)
|
||||
|
||||
m.SetHit(a.GetHit())
|
||||
m.SetMiss(a.GetMiss())
|
||||
m.SetFail(a.GetFail())
|
||||
|
||||
m.SetPassNodes(a.GetPassNodes())
|
||||
m.SetFailNodes(a.GetFailNodes())
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// DataAuditResultFromGRPCMessage converts gRPC message DataAuditResult
|
||||
// into unified DataAuditResult structure.
|
||||
func DataAuditResultFromGRPCMessage(m *audit.DataAuditResult) *DataAuditResult {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := new(DataAuditResult)
|
||||
|
||||
a.SetAuditEpoch(m.GetAuditEpoch())
|
||||
|
||||
a.SetContainerID(
|
||||
refs.ContainerIDFromGRPCMessage(m.GetContainerId()),
|
||||
)
|
||||
|
||||
a.SetPublicKey(m.GetPublicKey())
|
||||
|
||||
a.SetPassSG(
|
||||
refs.ObjectIDListFromGRPCMessage(m.GetPassSg()),
|
||||
)
|
||||
|
||||
a.SetFailSG(
|
||||
refs.ObjectIDListFromGRPCMessage(m.GetFailSg()),
|
||||
)
|
||||
|
||||
a.SetHit(m.GetHit())
|
||||
a.SetMiss(m.GetMiss())
|
||||
a.SetFail(m.GetFail())
|
||||
|
||||
a.SetPassNodes(m.GetPassNodes())
|
||||
a.SetFailNodes(m.GetFailNodes())
|
||||
|
||||
return a
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
refs "github.com/nspcc-dev/neofs-api-go/v2/refs/grpc"
|
||||
)
|
||||
|
||||
// SetAuditEpoch is an AuditEpoch field setter.
|
||||
func (x *DataAuditResult) SetAuditEpoch(v uint64) {
|
||||
if x != nil {
|
||||
x.AuditEpoch = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetContainerId is a ContainerId field setter.
|
||||
func (x *DataAuditResult) SetContainerId(v *refs.ContainerID) {
|
||||
if x != nil {
|
||||
x.ContainerId = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetPublicKey is a PublicKey field setter.
|
||||
func (x *DataAuditResult) SetPublicKey(v []byte) {
|
||||
if x != nil {
|
||||
x.PublicKey = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetPassSg is a PassSg field setter.
|
||||
func (x *DataAuditResult) SetPassSg(v []*refs.ObjectID) {
|
||||
if x != nil {
|
||||
x.PassSg = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetFailSg is a FailSg field setter.
|
||||
func (x *DataAuditResult) SetFailSg(v []*refs.ObjectID) {
|
||||
if x != nil {
|
||||
x.FailSg = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetHit is a Hit field setter.
|
||||
func (x *DataAuditResult) SetHit(v uint32) {
|
||||
if x != nil {
|
||||
x.Hit = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetMiss is a Miss field setter.
|
||||
func (x *DataAuditResult) SetMiss(v uint32) {
|
||||
if x != nil {
|
||||
x.Miss = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetFail is a Fail field setter.
|
||||
func (x *DataAuditResult) SetFail(v uint32) {
|
||||
if x != nil {
|
||||
x.Fail = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetPassNodes is a PassNodes field setter.
|
||||
func (x *DataAuditResult) SetPassNodes(v [][]byte) {
|
||||
if x != nil {
|
||||
x.PassNodes = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetFailNodes is a FailNodes field setter.
|
||||
func (x *DataAuditResult) SetFailNodes(v [][]byte) {
|
||||
if x != nil {
|
||||
x.FailNodes = v
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
audit "github.com/nspcc-dev/neofs-api-go/v2/audit/grpc"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
func (a *DataAuditResult) MarshalJSON() ([]byte, error) {
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
DataAuditResultToGRPCMessage(a),
|
||||
)
|
||||
}
|
||||
|
||||
func (a *DataAuditResult) UnmarshalJSON(data []byte) error {
|
||||
msg := new(audit.DataAuditResult)
|
||||
|
||||
if err := protojson.Unmarshal(data, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*a = *DataAuditResultFromGRPCMessage(msg)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package audit_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/audit"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDataAuditResultJSON(t *testing.T) {
|
||||
a := generateDataAuditResult()
|
||||
|
||||
data, err := a.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
a2 := new(audit.DataAuditResult)
|
||||
require.NoError(t, a2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, a, a2)
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/util/proto"
|
||||
audit "github.com/nspcc-dev/neofs-api-go/v2/audit/grpc"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
goproto "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
auditEpochFNum
|
||||
cidFNum
|
||||
pubKeyFNum
|
||||
passSGFNum
|
||||
failSGFNum
|
||||
hitFNum
|
||||
missFNum
|
||||
failFNum
|
||||
passNodesFNum
|
||||
failNodesFNum
|
||||
)
|
||||
|
||||
// StableMarshal marshals unified DataAuditResult structure into a protobuf
|
||||
// binary format without field order shuffle.
|
||||
func (a *DataAuditResult) StableMarshal(buf []byte) ([]byte, error) {
|
||||
if a == nil {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
if buf == nil {
|
||||
buf = make([]byte, a.StableSize())
|
||||
}
|
||||
|
||||
var (
|
||||
offset, n int
|
||||
err error
|
||||
)
|
||||
|
||||
n, err = proto.Fixed64Marshal(auditEpochFNum, buf[offset:], a.auditEpoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = proto.NestedStructureMarshal(cidFNum, buf[offset:], a.cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = proto.BytesMarshal(pubKeyFNum, buf[offset:], a.pubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = refs.ObjectIDNestedListMarshal(passSGFNum, buf[offset:], a.passSG)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = refs.ObjectIDNestedListMarshal(failSGFNum, buf[offset:], a.failSG)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = proto.UInt32Marshal(hitFNum, buf[offset:], a.hit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = proto.UInt32Marshal(missFNum, buf[offset:], a.miss)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = proto.UInt32Marshal(failFNum, buf[offset:], a.fail)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = proto.RepeatedBytesMarshal(passNodesFNum, buf[offset:], a.passNodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
n, err = proto.RepeatedBytesMarshal(failNodesFNum, buf[offset:], a.failNodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// StableSize returns byte length of DataAuditResult structure
|
||||
// marshaled by StableMarshal function.
|
||||
func (a *DataAuditResult) StableSize() (size int) {
|
||||
if a == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
size += proto.Fixed64Size(auditEpochFNum, a.auditEpoch)
|
||||
size += proto.NestedStructureSize(cidFNum, a.cid)
|
||||
size += proto.BytesSize(pubKeyFNum, a.pubKey)
|
||||
size += refs.ObjectIDNestedListSize(passSGFNum, a.passSG)
|
||||
size += refs.ObjectIDNestedListSize(failSGFNum, a.failSG)
|
||||
size += proto.UInt32Size(hitFNum, a.hit)
|
||||
size += proto.UInt32Size(missFNum, a.miss)
|
||||
size += proto.UInt32Size(failFNum, a.fail)
|
||||
size += proto.RepeatedBytesSize(passNodesFNum, a.passNodes)
|
||||
size += proto.RepeatedBytesSize(failNodesFNum, a.failNodes)
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals DataAuditResult structure from its protobuf
|
||||
// binary representation.
|
||||
func (a *DataAuditResult) Unmarshal(data []byte) error {
|
||||
m := new(audit.DataAuditResult)
|
||||
if err := goproto.Unmarshal(data, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*a = *DataAuditResultFromGRPCMessage(m)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package audit_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/audit"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDataAuditResult_StableMarshal(t *testing.T) {
|
||||
from := generateDataAuditResult()
|
||||
|
||||
t.Run("non empty", func(t *testing.T) {
|
||||
wire, err := from.StableMarshal(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
to := new(audit.DataAuditResult)
|
||||
require.NoError(t, to.Unmarshal(wire))
|
||||
|
||||
require.Equal(t, from, to)
|
||||
})
|
||||
}
|
||||
|
||||
func generateDataAuditResult() *audit.DataAuditResult {
|
||||
a := new(audit.DataAuditResult)
|
||||
|
||||
oid1 := new(refs.ObjectID)
|
||||
oid1.SetValue([]byte("Object ID 1"))
|
||||
|
||||
oid2 := new(refs.ObjectID)
|
||||
oid2.SetValue([]byte("Object ID 2"))
|
||||
|
||||
cid := new(refs.ContainerID)
|
||||
cid.SetValue([]byte("Container ID"))
|
||||
|
||||
a.SetAuditEpoch(13)
|
||||
a.SetContainerID(cid)
|
||||
a.SetPublicKey([]byte("Public key"))
|
||||
a.SetPassSG([]*refs.ObjectID{oid1, oid2})
|
||||
a.SetFailSG([]*refs.ObjectID{oid2, oid1})
|
||||
a.SetHit(1)
|
||||
a.SetMiss(2)
|
||||
a.SetFail(3)
|
||||
a.SetPassNodes([][]byte{
|
||||
{1, 2},
|
||||
{3, 4},
|
||||
})
|
||||
a.SetFailNodes([][]byte{
|
||||
{5, 6},
|
||||
{7, 8},
|
||||
})
|
||||
|
||||
return a
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
)
|
||||
|
||||
// DataAuditResult is a unified structure of
|
||||
// DataAuditResult message from proto definition.
|
||||
type DataAuditResult struct {
|
||||
auditEpoch uint64
|
||||
|
||||
hit, miss, fail uint32
|
||||
|
||||
cid *refs.ContainerID
|
||||
|
||||
pubKey []byte
|
||||
|
||||
passSG, failSG []*refs.ObjectID
|
||||
|
||||
failNodes, passNodes [][]byte
|
||||
}
|
||||
|
||||
// GetAuditEpoch returns epoch number when the Data Audit was conducted.
|
||||
func (a *DataAuditResult) GetAuditEpoch() uint64 {
|
||||
if a != nil {
|
||||
return a.auditEpoch
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// SetAuditEpoch sets epoch number when the Data Audit was conducted.
|
||||
func (a *DataAuditResult) SetAuditEpoch(v uint64) {
|
||||
if a != nil {
|
||||
a.auditEpoch = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetContainerID returns container under audit.
|
||||
func (a *DataAuditResult) GetContainerID() *refs.ContainerID {
|
||||
if a != nil {
|
||||
return a.cid
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetContainerID sets container under audit.
|
||||
func (a *DataAuditResult) SetContainerID(v *refs.ContainerID) {
|
||||
if a != nil {
|
||||
a.cid = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetPublicKey returns public key of the auditing InnerRing node in a binary format.
|
||||
func (a *DataAuditResult) GetPublicKey() []byte {
|
||||
if a != nil {
|
||||
return a.pubKey
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPublicKey sets public key of the auditing InnerRing node in a binary format.
|
||||
func (a *DataAuditResult) SetPublicKey(v []byte) {
|
||||
if a != nil {
|
||||
a.pubKey = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetPassSG returns list of Storage Groups that passed audit PoR stage.
|
||||
func (a *DataAuditResult) GetPassSG() []*refs.ObjectID {
|
||||
if a != nil {
|
||||
return a.passSG
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPassSG sets list of Storage Groups that passed audit PoR stage.
|
||||
func (a *DataAuditResult) SetPassSG(v []*refs.ObjectID) {
|
||||
if a != nil {
|
||||
a.passSG = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetFailSG returns list of Storage Groups that failed audit PoR stage.
|
||||
func (a *DataAuditResult) GetFailSG() []*refs.ObjectID {
|
||||
if a != nil {
|
||||
return a.failSG
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFailSG sets list of Storage Groups that failed audit PoR stage.
|
||||
func (a *DataAuditResult) SetFailSG(v []*refs.ObjectID) {
|
||||
if a != nil {
|
||||
a.failSG = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetHit returns number of sampled objects under audit placed
|
||||
// in an optimal way according to the containers placement policy
|
||||
// when checking PoP.
|
||||
func (a *DataAuditResult) GetHit() uint32 {
|
||||
if a != nil {
|
||||
return a.hit
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// SetHit sets number of sampled objects under audit placed
|
||||
// in an optimal way according to the containers placement policy
|
||||
// when checking PoP.
|
||||
func (a *DataAuditResult) SetHit(v uint32) {
|
||||
if a != nil {
|
||||
a.hit = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetMiss returns number of sampled objects under audit placed
|
||||
// in suboptimal way according to the containers placement policy,
|
||||
// but still at a satisfactory level when checking PoP.
|
||||
func (a *DataAuditResult) GetMiss() uint32 {
|
||||
if a != nil {
|
||||
return a.miss
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// SetMiss sets number of sampled objects under audit placed
|
||||
// in suboptimal way according to the containers placement policy,
|
||||
// but still at a satisfactory level when checking PoP.
|
||||
func (a *DataAuditResult) SetMiss(v uint32) {
|
||||
if a != nil {
|
||||
a.miss = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetFail returns number of sampled objects under audit stored
|
||||
// in a way not confirming placement policy or not found at all
|
||||
// when checking PoP.
|
||||
func (a *DataAuditResult) GetFail() uint32 {
|
||||
if a != nil {
|
||||
return a.fail
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// SetFail sets number of sampled objects under audit stored
|
||||
// in a way not confirming placement policy or not found at all
|
||||
// when checking PoP.
|
||||
func (a *DataAuditResult) SetFail(v uint32) {
|
||||
if a != nil {
|
||||
a.fail = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetPassNodes returns list of storage node public keys that
|
||||
// passed at least one PDP.
|
||||
func (a *DataAuditResult) GetPassNodes() [][]byte {
|
||||
if a != nil {
|
||||
return a.passNodes
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPassNodes sets list of storage node public keys that
|
||||
// passed at least one PDP.
|
||||
func (a *DataAuditResult) SetPassNodes(v [][]byte) {
|
||||
if a != nil {
|
||||
a.passNodes = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetFailNodes returns list of storage node public keys that
|
||||
// failed at least one PDP.
|
||||
func (a *DataAuditResult) GetFailNodes() [][]byte {
|
||||
if a != nil {
|
||||
return a.failNodes
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFailNodes sets list of storage node public keys that
|
||||
// failed at least one PDP.
|
||||
func (a *DataAuditResult) SetFailNodes(v [][]byte) {
|
||||
if a != nil {
|
||||
a.failNodes = v
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue