forked from TrueCloudLab/frostfs-node
[#488] reputation/eigentrust/calculator: Implement calc wrapper
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
parent
d3c1fc7dda
commit
ea781664cf
14 changed files with 294 additions and 53 deletions
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation/common"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -26,7 +27,7 @@ type Prm struct {
|
|||
|
||||
DaughterTrustSource DaughterTrustIteratorProvider
|
||||
|
||||
IntermediateValueTarget IntermediateWriterProvider
|
||||
IntermediateValueTarget common.WriterProvider
|
||||
|
||||
FinalResultTarget IntermediateWriterProvider
|
||||
|
||||
|
|
|
@ -15,17 +15,16 @@ type CalculatePrm struct {
|
|||
ei eigentrust.EpochIteration
|
||||
}
|
||||
|
||||
func (p *CalculatePrm) SetLast(last bool) {
|
||||
p.last = last
|
||||
}
|
||||
|
||||
func (p *CalculatePrm) SetEpochIteration(ei eigentrust.EpochIteration) {
|
||||
p.ei = ei
|
||||
}
|
||||
|
||||
type iterContext struct {
|
||||
context.Context
|
||||
eigentrust.EpochIteration
|
||||
}
|
||||
|
||||
func (c *Calculator) Calculate(prm CalculatePrm) {
|
||||
ctx := iterContext{
|
||||
ctx := eigentrust.IterContext{
|
||||
Context: context.Background(),
|
||||
EpochIteration: prm.ei,
|
||||
}
|
||||
|
@ -139,7 +138,7 @@ func (c *Calculator) iterateDaughter(p iterDaughterPrm) {
|
|||
var intermediateTrust eigentrust.IterationTrust
|
||||
|
||||
intermediateTrust.SetEpoch(p.ctx.Epoch())
|
||||
intermediateTrust.SetTrustingPeer(p.id)
|
||||
intermediateTrust.SetPeer(p.id)
|
||||
intermediateTrust.SetI(p.ctx.I())
|
||||
|
||||
if p.lastIter {
|
||||
|
@ -163,7 +162,7 @@ func (c *Calculator) iterateDaughter(p iterDaughterPrm) {
|
|||
return
|
||||
}
|
||||
} else {
|
||||
intermediateWriter, err := c.prm.IntermediateValueTarget.InitIntermediateWriter(p.ctx)
|
||||
intermediateWriter, err := c.prm.IntermediateValueTarget.InitWriter(p.ctx)
|
||||
if err != nil {
|
||||
c.opts.log.Debug("init intermediate writer failure",
|
||||
zap.String("error", err.Error()),
|
||||
|
@ -184,10 +183,7 @@ func (c *Calculator) iterateDaughter(p iterDaughterPrm) {
|
|||
|
||||
trust.SetValue(val)
|
||||
|
||||
intermediateTrust.SetPeer(trust.Peer())
|
||||
intermediateTrust.SetValue(val)
|
||||
|
||||
err := intermediateWriter.WriteIntermediateTrust(intermediateTrust)
|
||||
err := intermediateWriter.Write(p.ctx, trust)
|
||||
if err != nil {
|
||||
c.opts.log.Debug("write intermediate value failure",
|
||||
zap.String("error", err.Error()),
|
||||
|
@ -201,6 +197,14 @@ func (c *Calculator) iterateDaughter(p iterDaughterPrm) {
|
|||
zap.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
err = intermediateWriter.Close()
|
||||
if err != nil {
|
||||
c.opts.log.Error(
|
||||
"could not close intermediate writer",
|
||||
zap.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,7 +218,7 @@ func (c *Calculator) sendInitialValues(ctx Context) {
|
|||
return
|
||||
}
|
||||
|
||||
intermediateWriter, err := c.prm.IntermediateValueTarget.InitIntermediateWriter(ctx)
|
||||
intermediateWriter, err := c.prm.IntermediateValueTarget.InitWriter(ctx)
|
||||
if err != nil {
|
||||
c.opts.log.Debug("init intermediate writer failure",
|
||||
zap.String("error", err.Error()),
|
||||
|
@ -223,14 +227,7 @@ func (c *Calculator) sendInitialValues(ctx Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var intermediateTrust eigentrust.IterationTrust
|
||||
|
||||
intermediateTrust.SetEpoch(ctx.Epoch())
|
||||
intermediateTrust.SetI(ctx.I())
|
||||
|
||||
err = daughterIter.Iterate(func(daughter reputation.PeerID, iterator TrustIterator) error {
|
||||
intermediateTrust.SetTrustingPeer(daughter)
|
||||
|
||||
return iterator.Iterate(func(trust reputation.Trust) error {
|
||||
trusted := trust.Peer()
|
||||
|
||||
|
@ -245,12 +242,10 @@ func (c *Calculator) sendInitialValues(ctx Context) {
|
|||
return nil
|
||||
}
|
||||
|
||||
intermediateTrust.SetPeer(trusted)
|
||||
|
||||
initTrust.Mul(trust.Value())
|
||||
intermediateTrust.SetValue(initTrust)
|
||||
trust.SetValue(initTrust)
|
||||
|
||||
err = intermediateWriter.WriteIntermediateTrust(intermediateTrust)
|
||||
err = intermediateWriter.Write(ctx, trust)
|
||||
if err != nil {
|
||||
c.opts.log.Debug("write intermediate value failure",
|
||||
zap.String("error", err.Error()),
|
||||
|
@ -267,4 +262,11 @@ func (c *Calculator) sendInitialValues(ctx Context) {
|
|||
zap.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
err = intermediateWriter.Close()
|
||||
if err != nil {
|
||||
c.opts.log.Debug("could not close intermediate writer",
|
||||
zap.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,27 @@ type TrustIterator interface {
|
|||
|
||||
type PeerTrustsHandler func(reputation.PeerID, TrustIterator) error
|
||||
|
||||
// PeerTrustsIterator must iterate over all nodes(PeerIDs) and provide
|
||||
// TrustIterator for iteration over node's Trusts to others peers.
|
||||
type PeerTrustsIterator interface {
|
||||
Iterate(PeerTrustsHandler) error
|
||||
}
|
||||
|
||||
type DaughterTrustIteratorProvider interface {
|
||||
InitDaughterIterator(Context, reputation.PeerID) (TrustIterator, error)
|
||||
InitAllDaughtersIterator(Context) (PeerTrustsIterator, error)
|
||||
// InitDaughterIterator must init TrustIterator
|
||||
// that iterates over received local trusts from
|
||||
// daughter p for ctx.Epoch() epoch.
|
||||
InitDaughterIterator(ctx Context, p reputation.PeerID) (TrustIterator, error)
|
||||
// InitAllDaughtersIterator must init PeerTrustsIterator
|
||||
// that must iterate over all daughters of the current
|
||||
// node(manager) and all trusts received from them for
|
||||
// ctx.Epoch() epoch.
|
||||
InitAllDaughtersIterator(ctx Context) (PeerTrustsIterator, error)
|
||||
// InitConsumersIterator must init PeerTrustsIterator
|
||||
// that must iterate over all daughters of the current
|
||||
// node(manager) and their consumers' trusts received
|
||||
// from other managers for ctx.Epoch() epoch and
|
||||
// ctx.I() iteration.
|
||||
InitConsumersIterator(Context) (PeerTrustsIterator, error)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// ContinuePrm groups the required parameters of Continue operation.
|
||||
type ContinuePrm struct {
|
||||
epoch uint64
|
||||
Epoch uint64
|
||||
}
|
||||
|
||||
type iterContext struct {
|
||||
|
@ -35,20 +35,24 @@ func (c *Controller) Continue(prm ContinuePrm) {
|
|||
c.mtx.Lock()
|
||||
|
||||
{
|
||||
iterCtx, ok := c.mCtx[prm.epoch]
|
||||
iterCtx, ok := c.mCtx[prm.Epoch]
|
||||
if !ok {
|
||||
iterCtx := new(iterContextCancel)
|
||||
c.mCtx[prm.epoch] = iterCtx
|
||||
iterCtx = new(iterContextCancel)
|
||||
c.mCtx[prm.Epoch] = iterCtx
|
||||
|
||||
iterCtx.Context, iterCtx.cancel = context.WithCancel(context.Background())
|
||||
iterCtx.EpochIteration.SetEpoch(prm.Epoch)
|
||||
} else {
|
||||
iterCtx.cancel()
|
||||
}
|
||||
|
||||
iterCtx.last = iterCtx.I() == c.prm.IterationNumber
|
||||
iterCtx.last = iterCtx.I() == c.iterationNumber-1
|
||||
|
||||
err := c.prm.WorkerPool.Submit(func() {
|
||||
c.prm.DaughtersTrustCalculator.Calculate(iterCtx.iterContext)
|
||||
|
||||
// iteration++
|
||||
iterCtx.Increment()
|
||||
})
|
||||
if err != nil {
|
||||
c.opts.log.Debug("iteration submit failure",
|
||||
|
@ -57,11 +61,21 @@ func (c *Controller) Continue(prm ContinuePrm) {
|
|||
}
|
||||
|
||||
if iterCtx.last {
|
||||
delete(c.mCtx, prm.epoch)
|
||||
// In this case and worker pool failure we can mark epoch
|
||||
// number as already processed, but in any case it grows up
|
||||
// during normal operation of the system. Also, such information
|
||||
// will only live while the application is alive.
|
||||
// during normal operation of the system. Also, such information
|
||||
// number as already processed, but in any case it grows up
|
||||
// In this case and worker pool failure we can mark epoch
|
||||
delete(c.mCtx, prm.Epoch)
|
||||
|
||||
iterations, err := c.prm.IterationsProvider.EigenTrustIterations()
|
||||
if err != nil {
|
||||
c.opts.log.Debug(
|
||||
"could not get iteration numbers",
|
||||
zap.String("error", err.Error()),
|
||||
)
|
||||
} else {
|
||||
c.iterationNumber = uint32(iterations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,15 @@ import (
|
|||
// Passing incorrect parameter values will result in constructor
|
||||
// failure (error or panic depending on the implementation).
|
||||
type Prm struct {
|
||||
// Number of iterations
|
||||
IterationNumber uint32
|
||||
|
||||
// Component of computing iteration of EigenTrust algorithm.
|
||||
//
|
||||
// Must not be nil.
|
||||
DaughtersTrustCalculator DaughtersTrustCalculator
|
||||
|
||||
// IterationsProvider provides information about numbers
|
||||
// of iterations for algorithm.
|
||||
IterationsProvider IterationsProvider
|
||||
|
||||
// Routine execution pool for single epoch iteration.
|
||||
WorkerPool util.WorkerPool
|
||||
}
|
||||
|
@ -45,6 +46,9 @@ type Controller struct {
|
|||
|
||||
opts *options
|
||||
|
||||
// Number of iterations
|
||||
iterationNumber uint32
|
||||
|
||||
mtx sync.Mutex
|
||||
mCtx map[uint64]*iterContextCancel
|
||||
}
|
||||
|
@ -63,14 +67,19 @@ func panicOnPrmValue(n string, v interface{}) {
|
|||
// initialization and is completely ready for work.
|
||||
func New(prm Prm, opts ...Option) *Controller {
|
||||
switch {
|
||||
case prm.IterationNumber == 0:
|
||||
panicOnPrmValue("IterationNumber", prm.IterationNumber)
|
||||
case prm.IterationsProvider == nil:
|
||||
panicOnPrmValue("IterationNumber", prm.IterationsProvider)
|
||||
case prm.WorkerPool == nil:
|
||||
panicOnPrmValue("WorkerPool", prm.WorkerPool)
|
||||
case prm.DaughtersTrustCalculator == nil:
|
||||
panicOnPrmValue("DaughtersTrustCalculator", prm.DaughtersTrustCalculator)
|
||||
}
|
||||
|
||||
iterations, err := prm.IterationsProvider.EigenTrustIterations()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("could not init EigenTrust controller: could not get num of iterations: %w", err))
|
||||
}
|
||||
|
||||
o := defaultOpts()
|
||||
|
||||
for _, opt := range opts {
|
||||
|
@ -78,8 +87,9 @@ func New(prm Prm, opts ...Option) *Controller {
|
|||
}
|
||||
|
||||
return &Controller{
|
||||
prm: prm,
|
||||
opts: o,
|
||||
mCtx: make(map[uint64]*iterContextCancel),
|
||||
iterationNumber: uint32(iterations),
|
||||
prm: prm,
|
||||
opts: o,
|
||||
mCtx: make(map[uint64]*iterContextCancel),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,3 +33,9 @@ type DaughtersTrustCalculator interface {
|
|||
// Execution should be interrupted if ctx.Last().
|
||||
Calculate(ctx IterationContext)
|
||||
}
|
||||
|
||||
// IterationsProvider must provides information about numbers
|
||||
// of iterations for algorithm.
|
||||
type IterationsProvider interface {
|
||||
EigenTrustIterations() (uint64, error)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package eigentrust
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/reputation"
|
||||
)
|
||||
|
||||
|
@ -25,7 +27,30 @@ func (x *EpochIteration) SetI(i uint32) {
|
|||
x.i = i
|
||||
}
|
||||
|
||||
func (x *EpochIteration) Increment() {
|
||||
x.i++
|
||||
}
|
||||
|
||||
type IterationTrust struct {
|
||||
EpochIteration
|
||||
reputation.Trust
|
||||
}
|
||||
|
||||
// IterContext aggregates context and data required for
|
||||
// iterations.
|
||||
type IterContext struct {
|
||||
context.Context
|
||||
EpochIteration
|
||||
}
|
||||
|
||||
func NewIterContext(ctx context.Context, epoch uint64, iter uint32) *IterContext {
|
||||
ei := EpochIteration{}
|
||||
|
||||
ei.SetI(iter)
|
||||
ei.SetEpoch(epoch)
|
||||
|
||||
return &IterContext{
|
||||
Context: ctx,
|
||||
EpochIteration: ei,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue