Remove container estimation code #1475

Merged
fyrchik merged 1 commit from fyrchik/frostfs-node:wait-tx into master 2024-11-07 11:19:09 +00:00
13 changed files with 9 additions and 499 deletions

View file

@ -17,8 +17,6 @@ const (
) )
const ( const (
InnerringNonalphabetModeDoNotStopContainerEstimations = "non-alphabet mode, do not stop container estimations"
InnerringCantStopEpochEstimation = "can't stop epoch estimation"
InnerringCantMakeNotaryDepositInMainChain = "can't make notary deposit in main chain" InnerringCantMakeNotaryDepositInMainChain = "can't make notary deposit in main chain"
InnerringCantMakeNotaryDepositInSideChain = "can't make notary deposit in side chain" InnerringCantMakeNotaryDepositInSideChain = "can't make notary deposit in side chain"
InnerringNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" InnerringNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made"
@ -343,7 +341,6 @@ const (
NetmapCantGetTransactionHeight = "can't get transaction height" NetmapCantGetTransactionHeight = "can't get transaction height"
NetmapCantResetEpochTimer = "can't reset epoch timer" NetmapCantResetEpochTimer = "can't reset epoch timer"
NetmapCantGetNetmapSnapshotToPerformCleanup = "can't get netmap snapshot to perform cleanup" NetmapCantGetNetmapSnapshotToPerformCleanup = "can't get netmap snapshot to perform cleanup"
NetmapCantStartContainerSizeEstimation = "can't start container size estimation"
NetmapNonAlphabetModeIgnoreNewEpochTick = "non alphabet mode, ignore new epoch tick" NetmapNonAlphabetModeIgnoreNewEpochTick = "non alphabet mode, ignore new epoch tick"
NetmapNextEpoch = "next epoch" NetmapNextEpoch = "next epoch"
NetmapCantInvokeNetmapNewEpoch = "can't invoke netmap.NewEpoch" NetmapCantInvokeNetmapNewEpoch = "can't invoke netmap.NewEpoch"

View file

@ -3,14 +3,10 @@ package innerring
import ( import (
"context" "context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"go.uber.org/zap"
) )
type ( type (
@ -19,28 +15,12 @@ type (
EpochDuration() uint64 EpochDuration() uint64
} }
alphaState interface {
IsAlphabet() bool
}
newEpochHandler func() newEpochHandler func()
containerEstimationStopper interface {
StopEstimation(p container.StopEstimationPrm) error
}
epochTimerArgs struct { epochTimerArgs struct {
l *logger.Logger
alphabetState alphaState
newEpochHandlers []newEpochHandler newEpochHandlers []newEpochHandler
cnrWrapper containerEstimationStopper // to invoke stop container estimation epoch epochState // to specify which epoch to stop, and epoch duration
epoch epochState // to specify which epoch to stop, and epoch duration
stopEstimationDMul uint32 // X: X/Y of epoch in blocks
stopEstimationDDiv uint32 // Y: X/Y of epoch in blocks
} }
emitTimerArgs struct { emitTimerArgs struct {
@ -74,7 +54,7 @@ func (s *Server) tickTimers(h uint32) {
} }
func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer { func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
epochTimer := timer.NewBlockTimer( return timer.NewBlockTimer(
func() (uint32, error) { func() (uint32, error) {
return uint32(args.epoch.EpochDuration()), nil return uint32(args.epoch.EpochDuration()), nil
}, },
@ -84,35 +64,6 @@ func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
} }
}, },
) )
// sub-timer for epoch timer to tick stop container estimation events at
// some block in epoch
epochTimer.OnDelta(
args.stopEstimationDMul,
args.stopEstimationDDiv,
func() {
if !args.alphabetState.IsAlphabet() {
args.l.Debug(logs.InnerringNonalphabetModeDoNotStopContainerEstimations)
return
}
epochN := args.epoch.EpochCounter()
if epochN == 0 { // estimates are invalid in genesis epoch
return
}
prm := container.StopEstimationPrm{}
prm.SetEpoch(epochN - 1)
err := args.cnrWrapper.StopEstimation(prm)
if err != nil {
args.l.Warn(logs.InnerringCantStopEpochEstimation,
zap.Uint64("epoch", epochN),
zap.String("error", err.Error()))
}
})
return epochTimer
} }
func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer { func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer {

View file

@ -3,29 +3,20 @@ package innerring
import ( import (
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestEpochTimer(t *testing.T) { func TestEpochTimer(t *testing.T) {
t.Parallel() t.Parallel()
alphaState := &testAlphabetState{isAlphabet: true}
neh := &testNewEpochHandler{} neh := &testNewEpochHandler{}
cnrStopper := &testContainerEstStopper{}
epochState := &testEpochState{ epochState := &testEpochState{
counter: 99, counter: 99,
duration: 10, duration: 10,
} }
args := &epochTimerArgs{ args := &epochTimerArgs{
l: test.NewLogger(t), newEpochHandlers: []newEpochHandler{neh.Handle},
alphabetState: alphaState, epoch: epochState,
newEpochHandlers: []newEpochHandler{neh.Handle},
cnrWrapper: cnrStopper,
epoch: epochState,
stopEstimationDMul: 2,
stopEstimationDDiv: 10,
} }
et := newEpochTimer(args) et := newEpochTimer(args)
err := et.Reset() err := et.Reset()
@ -33,63 +24,43 @@ func TestEpochTimer(t *testing.T) {
et.Tick(100) et.Tick(100)
require.Equal(t, 0, neh.called, "invalid new epoch handler calls") require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
require.Equal(t, 0, cnrStopper.called, "invalid container stop handler calls")
et.Tick(101) et.Tick(101)
require.Equal(t, 0, neh.called, "invalid new epoch handler calls") require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
et.Tick(102) et.Tick(102)
require.Equal(t, 0, neh.called, "invalid new epoch handler calls") require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
et.Tick(103) et.Tick(103)
require.Equal(t, 0, neh.called, "invalid new epoch handler calls") require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
var h uint32 var h uint32
for h = 104; h < 109; h++ { for h = 104; h < 109; h++ {
et.Tick(h) et.Tick(h)
require.Equal(t, 0, neh.called, "invalid new epoch handler calls") require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
} }
et.Tick(109) et.Tick(109)
require.Equal(t, 1, neh.called, "invalid new epoch handler calls") require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
et.Tick(110) et.Tick(110)
require.Equal(t, 1, neh.called, "invalid new epoch handler calls") require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
et.Tick(111) et.Tick(111)
require.Equal(t, 1, neh.called, "invalid new epoch handler calls") require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
et.Tick(112) et.Tick(112)
require.Equal(t, 1, neh.called, "invalid new epoch handler calls") require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
et.Tick(113) et.Tick(113)
require.Equal(t, 1, neh.called, "invalid new epoch handler calls") require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
for h = 114; h < 119; h++ { for h = 114; h < 119; h++ {
et.Tick(h) et.Tick(h)
require.Equal(t, 1, neh.called, "invalid new epoch handler calls") require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
} }
et.Tick(120) et.Tick(120)
require.Equal(t, 2, neh.called, "invalid new epoch handler calls") require.Equal(t, 2, neh.called, "invalid new epoch handler calls")
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
}
type testAlphabetState struct {
isAlphabet bool
}
func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet
} }
type testNewEpochHandler struct { type testNewEpochHandler struct {
@ -100,15 +71,6 @@ func (h *testNewEpochHandler) Handle() {
h.called++ h.called++
} }
type testContainerEstStopper struct {
called int
}
func (s *testContainerEstStopper) StopEstimation(_ container.StopEstimationPrm) error {
s.called++
return nil
}
type testEpochState struct { type testEpochState struct {
counter uint64 counter uint64
duration uint64 duration uint64

View file

@ -36,7 +36,6 @@ import (
) )
func (s *Server) initNetmapProcessor(cfg *viper.Viper, func (s *Server) initNetmapProcessor(cfg *viper.Viper,
cnrClient *container.Client,
alphaSync event.Handler, alphaSync event.Handler,
) error { ) error {
locodeValidator, err := s.newLocodeValidator(cfg) locodeValidator, err := s.newLocodeValidator(cfg)
@ -59,7 +58,6 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper,
AlphabetState: s, AlphabetState: s,
CleanupEnabled: cfg.GetBool("netmap_cleaner.enabled"), CleanupEnabled: cfg.GetBool("netmap_cleaner.enabled"),
CleanupThreshold: cfg.GetUint64("netmap_cleaner.threshold"), CleanupThreshold: cfg.GetUint64("netmap_cleaner.threshold"),
ContainerWrapper: cnrClient,
NotaryDepositHandler: s.onlyAlphabetEventHandler( NotaryDepositHandler: s.onlyAlphabetEventHandler(
s.notaryHandler, s.notaryHandler,
), ),
@ -198,15 +196,10 @@ func (s *Server) createIRFetcher() irFetcher {
return irf return irf
} }
func (s *Server) initTimers(cfg *viper.Viper, morphClients *serverMorphClients) { func (s *Server) initTimers(cfg *viper.Viper) {
s.epochTimer = newEpochTimer(&epochTimerArgs{ s.epochTimer = newEpochTimer(&epochTimerArgs{
l: s.log, newEpochHandlers: s.newEpochTickHandlers(),
alphabetState: s, epoch: s,
newEpochHandlers: s.newEpochTickHandlers(),
cnrWrapper: morphClients.CnrClient,
epoch: s,
stopEstimationDMul: cfg.GetUint32("timers.stop_estimation.mul"),
stopEstimationDDiv: cfg.GetUint32("timers.stop_estimation.div"),
}) })
s.addBlockTimer(s.epochTimer) s.addBlockTimer(s.epochTimer)
@ -425,7 +418,7 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien
return err return err
} }
err = s.initNetmapProcessor(cfg, morphClients.CnrClient, alphaSync) err = s.initNetmapProcessor(cfg, alphaSync)
if err != nil { if err != nil {
return err return err
} }

View file

@ -405,7 +405,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan
return nil, err return nil, err
} }
server.initTimers(cfg, morphClients) server.initTimers(cfg)
err = server.initGRPCServer(cfg, log, audit) err = server.initGRPCServer(cfg, log, audit)
if err != nil { if err != nil {

View file

@ -9,7 +9,6 @@ import (
netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance"
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
@ -68,7 +67,6 @@ func TestNewEpoch(t *testing.T) {
duration: 10, duration: 10,
} }
r := &testEpochResetter{} r := &testEpochResetter{}
cc := &testContainerClient{}
nc := &testNetmapClient{ nc := &testNetmapClient{
epochDuration: 20, epochDuration: 20,
txHeights: map[util.Uint256]uint32{ txHeights: map[util.Uint256]uint32{
@ -82,7 +80,6 @@ func TestNewEpoch(t *testing.T) {
p.NotaryDepositHandler = eh.Handle p.NotaryDepositHandler = eh.Handle
p.AlphabetSyncHandler = eh.Handle p.AlphabetSyncHandler = eh.Handle
p.NetmapClient = nc p.NetmapClient = nc
p.ContainerWrapper = cc
p.EpochTimer = r p.EpochTimer = r
p.EpochState = es p.EpochState = es
}) })
@ -103,11 +100,6 @@ func TestNewEpoch(t *testing.T) {
require.Equal(t, ev.Num, es.counter, "invalid epoch counter") require.Equal(t, ev.Num, es.counter, "invalid epoch counter")
require.EqualValues(t, []uint32{nc.txHeights[ev.Hash]}, r.timers, "invalid epoch timer resets") require.EqualValues(t, []uint32{nc.txHeights[ev.Hash]}, r.timers, "invalid epoch timer resets")
var expEstimation cntClient.StartEstimationPrm
expEstimation.SetEpoch(ev.Num - 1)
expEstimation.SetHash(ev.Hash)
require.EqualValues(t, []cntClient.StartEstimationPrm{expEstimation}, cc.estimations, "invalid estimations")
require.EqualValues(t, []event.Event{ require.EqualValues(t, []event.Event{
governance.NewSyncEvent(ev.TxHash()), governance.NewSyncEvent(ev.TxHash()),
ev, ev,
@ -274,7 +266,6 @@ func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) {
as := &testAlphabetState{ as := &testAlphabetState{
isAlphabet: true, isAlphabet: true,
} }
cc := &testContainerClient{}
nc := &testNetmapClient{} nc := &testNetmapClient{}
eh := &testEventHandler{} eh := &testEventHandler{}
@ -288,7 +279,6 @@ func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) {
EpochState: es, EpochState: es,
EpochTimer: r, EpochTimer: r,
AlphabetState: as, AlphabetState: as,
ContainerWrapper: cc,
NetmapClient: nc, NetmapClient: nc,
NotaryDepositHandler: eh.Handle, NotaryDepositHandler: eh.Handle,
AlphabetSyncHandler: eh.Handle, AlphabetSyncHandler: eh.Handle,
@ -354,15 +344,6 @@ func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet return s.isAlphabet
} }
type testContainerClient struct {
estimations []cntClient.StartEstimationPrm
}
func (c *testContainerClient) StartEstimation(p cntClient.StartEstimationPrm) error {
c.estimations = append(c.estimations, p)
return nil
}
type notaryInvoke struct { type notaryInvoke struct {
contract util.Uint160 contract util.Uint160
fee fixedn.Fixed8 fee fixedn.Fixed8

View file

@ -3,7 +3,6 @@ package netmap
import ( import (
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance"
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -44,20 +43,6 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool {
return false return false
} }
prm := cntClient.StartEstimationPrm{}
prm.SetEpoch(epoch - 1)
prm.SetHash(ev.TxHash())
if epoch > 0 && np.alphabetState.IsAlphabet() { // estimates are invalid in genesis epoch
err = np.containerWrp.StartEstimation(prm)
if err != nil {
np.log.Warn(logs.NetmapCantStartContainerSizeEstimation,
zap.Uint64("epoch", epoch),
zap.String("error", err.Error()))
}
}
np.netmapSnapshot.update(*networkMap, epoch) np.netmapSnapshot.update(*networkMap, epoch)
np.handleCleanupTick(netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()}) np.handleCleanupTick(netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()})
np.handleAlphabetSync(governance.NewSyncEvent(ev.TxHash())) np.handleAlphabetSync(governance.NewSyncEvent(ev.TxHash()))

View file

@ -7,7 +7,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state"
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
@ -65,10 +64,6 @@ type (
MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error
} }
ContainerClient interface {
StartEstimation(p cntClient.StartEstimationPrm) error
}
// Processor of events produced by network map contract // Processor of events produced by network map contract
// and new epoch ticker, because it is related to contract. // and new epoch ticker, because it is related to contract.
Processor struct { Processor struct {
@ -80,7 +75,6 @@ type (
alphabetState AlphabetState alphabetState AlphabetState
netmapClient Client netmapClient Client
containerWrp ContainerClient
netmapSnapshot cleanupTable netmapSnapshot cleanupTable
@ -103,7 +97,6 @@ type (
AlphabetState AlphabetState AlphabetState AlphabetState
CleanupEnabled bool CleanupEnabled bool
CleanupThreshold uint64 // in epochs CleanupThreshold uint64 // in epochs
ContainerWrapper ContainerClient
AlphabetSyncHandler event.Handler AlphabetSyncHandler event.Handler
NotaryDepositHandler event.Handler NotaryDepositHandler event.Handler
@ -133,8 +126,6 @@ func New(p *Params) (*Processor, error) {
return nil, errors.New("ir/netmap: alphabet sync handler is not set") return nil, errors.New("ir/netmap: alphabet sync handler is not set")
case p.NotaryDepositHandler == nil: case p.NotaryDepositHandler == nil:
return nil, errors.New("ir/netmap: notary deposit handler is not set") return nil, errors.New("ir/netmap: notary deposit handler is not set")
case p.ContainerWrapper == nil:
return nil, errors.New("ir/netmap: container contract wrapper is not set")
case p.NodeValidator == nil: case p.NodeValidator == nil:
return nil, errors.New("ir/netmap: node validator is not set") return nil, errors.New("ir/netmap: node validator is not set")
case p.NodeStateSettings == nil: case p.NodeStateSettings == nil:
@ -161,7 +152,6 @@ func New(p *Params) (*Processor, error) {
epochState: p.EpochState, epochState: p.EpochState,
alphabetState: p.AlphabetState, alphabetState: p.AlphabetState,
netmapClient: p.NetmapClient, netmapClient: p.NetmapClient,
containerWrp: p.ContainerWrapper,
netmapSnapshot: newCleanupTable(p.CleanupEnabled, p.CleanupThreshold), netmapSnapshot: newCleanupTable(p.CleanupEnabled, p.CleanupThreshold),
handleAlphabetSync: p.AlphabetSyncHandler, handleAlphabetSync: p.AlphabetSyncHandler,

View file

@ -30,12 +30,6 @@ const (
eaclMethod = "eACL" eaclMethod = "eACL"
deletionInfoMethod = "deletionInfo" deletionInfoMethod = "deletionInfo"
startEstimationMethod = "startContainerEstimation"
stopEstimationMethod = "stopContainerEstimation"
listSizesMethod = "listContainerSizes"
getSizeMethod = "getContainerSize"
// putNamedMethod is method name for container put with an alias. It is exported to provide custom fee. // putNamedMethod is method name for container put with an alias. It is exported to provide custom fee.
putNamedMethod = "putNamed" putNamedMethod = "putNamed"
) )

View file

@ -1,54 +0,0 @@
package container
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
)
// StartEstimationPrm groups parameters of StartEstimation operation.
type StartEstimationPrm struct {
commonEstimationPrm
}
// StopEstimationPrm groups parameters of StopEstimation operation.
type StopEstimationPrm struct {
commonEstimationPrm
}
type commonEstimationPrm struct {
epoch uint64
client.InvokePrmOptional
}
// SetEpoch sets epoch.
func (p *commonEstimationPrm) SetEpoch(epoch uint64) {
p.epoch = epoch
}
// StartEstimation votes to produce start estimation notification.
func (c *Client) StartEstimation(p StartEstimationPrm) error {
prm := client.InvokePrm{}
prm.SetMethod(startEstimationMethod)
prm.SetArgs(p.epoch)
prm.InvokePrmOptional = p.InvokePrmOptional
if _, err := c.client.Invoke(prm); err != nil {
return fmt.Errorf("could not invoke method (%s): %w", startEstimationMethod, err)
}
return nil
}
// StopEstimation votes to produce stop estimation notification.
func (c *Client) StopEstimation(p StopEstimationPrm) error {
prm := client.InvokePrm{}
prm.SetMethod(stopEstimationMethod)
prm.SetArgs(p.epoch)
prm.InvokePrmOptional = p.InvokePrmOptional
if _, err := c.client.Invoke(prm); err != nil {
return fmt.Errorf("could not invoke method (%s): %w", stopEstimationMethod, err)
}
return nil
}

View file

@ -1,131 +0,0 @@
package container
import (
"fmt"
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
)
// EstimationID is an identity of container load estimation inside Container contract.
type EstimationID []byte
// ListLoadEstimationsByEpoch returns a list of container load estimations for to the specified epoch.
// The list is composed through Container contract call.
func (c *Client) ListLoadEstimationsByEpoch(epoch uint64) ([]EstimationID, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(listSizesMethod)
invokePrm.SetArgs(epoch)
prms, err := c.client.TestInvoke(invokePrm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", listSizesMethod, err)
} else if ln := len(prms); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", listSizesMethod, ln)
}
prms, err = client.ArrayFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listSizesMethod, err)
}
res := make([]EstimationID, 0, len(prms))
for i := range prms {
id, err := client.BytesFromStackItem(prms[i])
if err != nil {
return nil, fmt.Errorf("could not get ID byte array from stack item (%s): %w", listSizesMethod, err)
}
res = append(res, id)
}
return res, nil
}
// Estimation is a structure of single container load estimation
// reported by storage node.
type Estimation struct {
Size uint64
Reporter []byte
}
// Estimations is a structure of grouped container load estimation inside Container contract.
type Estimations struct {
ContainerID cid.ID
Values []Estimation
}
// GetUsedSpaceEstimations returns a list of container load estimations by ID.
// The list is composed through Container contract call.
func (c *Client) GetUsedSpaceEstimations(id EstimationID) (*Estimations, error) {
prm := client.TestInvokePrm{}
prm.SetMethod(getSizeMethod)
prm.SetArgs([]byte(id))
prms, err := c.client.TestInvoke(prm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getSizeMethod, err)
} else if ln := len(prms); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", getSizeMethod, ln)
}
prms, err = client.ArrayFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get stack items of estimation fields from stack item (%s): %w", getSizeMethod, err)
} else if ln := len(prms); ln != 2 {
return nil, fmt.Errorf("unexpected stack item count of estimations fields (%s)", getSizeMethod)
}
rawCnr, err := client.BytesFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get container ID byte array from stack item (%s): %w", getSizeMethod, err)
}
prms, err = client.ArrayFromStackItem(prms[1])
if err != nil {
return nil, fmt.Errorf("could not get estimation list array from stack item (%s): %w", getSizeMethod, err)
}
var cnr cid.ID
err = cnr.Decode(rawCnr)
if err != nil {
return nil, fmt.Errorf("decode container ID: %w", err)
}
v2 := new(v2refs.ContainerID)
v2.SetValue(rawCnr)
res := &Estimations{
ContainerID: cnr,
Values: make([]Estimation, 0, len(prms)),
}
for i := range prms {
arr, err := client.ArrayFromStackItem(prms[i])
if err != nil {
return nil, fmt.Errorf("could not get estimation struct from stack item (%s): %w", getSizeMethod, err)
} else if ln := len(arr); ln != 2 {
return nil, fmt.Errorf("unexpected stack item count of estimation fields (%s)", getSizeMethod)
}
reporter, err := client.BytesFromStackItem(arr[0])
if err != nil {
return nil, fmt.Errorf("could not get reporter byte array from stack item (%s): %w", getSizeMethod, err)
}
sz, err := client.IntFromStackItem(arr[1])
if err != nil {
return nil, fmt.Errorf("could not get estimation size from stack item (%s): %w", getSizeMethod, err)
}
res.Values = append(res.Values, Estimation{
Reporter: reporter,
Size: uint64(sz),
})
}
return res, nil
}

View file

@ -1,78 +0,0 @@
package container
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
// StartEstimation structure of container.StartEstimation notification from
// morph chain.
type StartEstimation struct {
epoch uint64
}
// StopEstimation structure of container.StopEstimation notification from
// morph chain.
type StopEstimation struct {
epoch uint64
}
// MorphEvent implements Neo:Morph Event interface.
func (StartEstimation) MorphEvent() {}
// MorphEvent implements Neo:Morph Event interface.
func (StopEstimation) MorphEvent() {}
// Epoch returns epoch value for which to start container size estimation.
func (s StartEstimation) Epoch() uint64 { return s.epoch }
// Epoch returns epoch value for which to stop container size estimation.
func (s StopEstimation) Epoch() uint64 { return s.epoch }
// ParseStartEstimation from notification into container event structure.
func ParseStartEstimation(e *state.ContainedNotificationEvent) (event.Event, error) {
params, err := event.ParseStackArray(e)
if err != nil {
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
}
epoch, err := parseEstimation(params)
if err != nil {
return nil, err
}
return StartEstimation{epoch: epoch}, nil
}
// ParseStopEstimation from notification into container event structure.
func ParseStopEstimation(e *state.ContainedNotificationEvent) (event.Event, error) {
params, err := event.ParseStackArray(e)
if err != nil {
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
}
epoch, err := parseEstimation(params)
if err != nil {
return nil, err
}
return StopEstimation{epoch: epoch}, nil
}
func parseEstimation(params []stackitem.Item) (uint64, error) {
if ln := len(params); ln != 1 {
return 0, event.WrongNumberOfParameters(1, ln)
}
// parse container
epoch, err := client.IntFromStackItem(params[0])
if err != nil {
return 0, fmt.Errorf("could not get estimation epoch: %w", err)
}
return uint64(epoch), nil
}

View file

@ -1,80 +0,0 @@
package container
import (
"math/big"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
func TestStartEstimation(t *testing.T) {
var epochNum uint64 = 100
epochItem := stackitem.NewBigInteger(new(big.Int).SetUint64(epochNum))
t.Run("wrong number of parameters", func(t *testing.T) {
prms := []stackitem.Item{
stackitem.NewMap(),
stackitem.NewMap(),
}
_, err := ParseStartEstimation(createNotifyEventFromItems(prms))
require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error())
})
t.Run("wrong estimation parameter", func(t *testing.T) {
_, err := ParseStartEstimation(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("correct behavior", func(t *testing.T) {
ev, err := ParseStartEstimation(createNotifyEventFromItems([]stackitem.Item{
epochItem,
}))
require.NoError(t, err)
require.Equal(t, StartEstimation{
epochNum,
}, ev)
})
}
func TestStopEstimation(t *testing.T) {
var epochNum uint64 = 100
epochItem := stackitem.NewBigInteger(new(big.Int).SetUint64(epochNum))
t.Run("wrong number of parameters", func(t *testing.T) {
prms := []stackitem.Item{
stackitem.NewMap(),
stackitem.NewMap(),
}
_, err := ParseStopEstimation(createNotifyEventFromItems(prms))
require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error())
})
t.Run("wrong estimation parameter", func(t *testing.T) {
_, err := ParseStopEstimation(createNotifyEventFromItems([]stackitem.Item{
stackitem.NewMap(),
}))
require.Error(t, err)
})
t.Run("correct behavior", func(t *testing.T) {
ev, err := ParseStopEstimation(createNotifyEventFromItems([]stackitem.Item{
epochItem,
}))
require.NoError(t, err)
require.Equal(t, StopEstimation{
epochNum,
}, ev)
})
}