-
Notifications
You must be signed in to change notification settings - Fork 4
/
strategy.go
97 lines (81 loc) · 3.09 KB
/
strategy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package jetalloc
import (
"crypto/sha256"
"encoding/binary"
"hash"
"github.com/insolar/assured-ledger/ledger-core/insolar/node"
"github.com/insolar/assured-ledger/ledger-core/ledger/jet"
"github.com/insolar/assured-ledger/ledger-core/network/consensus/gcpv2/api/census"
"github.com/insolar/assured-ledger/ledger-core/network/consensus/gcpv2/api/member"
"github.com/insolar/assured-ledger/ledger-core/pulse"
"github.com/insolar/assured-ledger/ledger-core/reference"
"github.com/insolar/assured-ledger/ledger-core/vanilla/longbits"
"github.com/insolar/assured-ledger/ledger-core/vanilla/throw"
)
type MaterialAllocationStrategy interface {
CreateCalculator(entropy longbits.FixedReader, population census.OnlinePopulation) MaterialAllocationCalculator
}
type MaterialAllocationCalculator interface {
AllocationOfLine(local reference.Local) jet.Prefix
// AllocationOfJets MUST receive list of all jets, otherwise allocation may be incorrect.
// This requirements for all jets is intended to support balanced distribution algorithms.
AllocationOfJets([]jet.ExactID, pulse.Number) map[jet.ID]node.ShortNodeID
}
type HashFactoryFunc = func() hash.Hash
func NewMaterialAllocationStrategy(usePower bool) MaterialAllocationStrategy {
return defaultMaterialAllocationStrategy{sha256.New, usePower}
}
type defaultMaterialAllocationStrategy struct {
hashFactory HashFactoryFunc
usePower bool
}
func (v defaultMaterialAllocationStrategy) CreateCalculator(entropy longbits.FixedReader, population census.OnlinePopulation) MaterialAllocationCalculator {
mPop := population.GetRolePopulation(member.PrimaryRoleLightMaterial)
switch {
case v.hashFactory == nil:
panic(throw.IllegalState())
case entropy == nil:
panic(throw.IllegalValue())
case mPop == nil || !mPop.IsValid():
panic(throw.IllegalValue())
case v.usePower:
if mPop.GetWorkingPower() == 0 {
panic(throw.IllegalValue())
}
return defaultMaterialAllocationCalc{ v.hashFactory, entropy, mPop.GetAssignmentByPower }
default:
if mPop.GetWorkingCount() <= 0 {
panic(throw.IllegalValue())
}
return defaultMaterialAllocationCalc{ v.hashFactory, entropy, mPop.GetAssignmentByCount }
}
}
type defaultMaterialAllocationCalc struct {
hashFactory HashFactoryFunc
entropy longbits.FixedReader
assignFn census.AssignmentFunc
}
func (v defaultMaterialAllocationCalc) AllocationOfLine(local reference.Local) jet.Prefix {
b := local.AsBytes()
return NewPrefixCalc().FromSlice(jet.IDBitLen, b)
}
func (v defaultMaterialAllocationCalc) metricOfDrop(jt jet.DropID) uint64 {
encoding := binary.LittleEndian
h := v.hashFactory()
var b [8]byte
encoding.PutUint64(b[:], uint64(jt.ID()))
_, _ = h.Write(b[:])
_, _ = v.entropy.WriteTo(h)
return longbits.CutOutUint64(h.Sum(nil))
}
func (v defaultMaterialAllocationCalc) AllocationOfJets(jets []jet.ExactID, pn pulse.Number) map[jet.ID]node.ShortNodeID {
// TODO implement a balanced allocation function
result := map[jet.ID]node.ShortNodeID{}
for _, jt := range jets {
jid := jt.ID()
metric := v.metricOfDrop(jid.AsDrop(pn))
nd, _ := v.assignFn(metric, 0)
result[jid] = nd.GetNodeID()
}
return result
}