forked from TrueCloudLab/frostfs-node
cc88320d6b
Implement a component that connects the value stores of the used space of containers. Implement the Start/Stop operations on it, which will later become the application handlers of the corresponding events from the sidechain. The main task of the controller is to temporarily synchronize the stages of calculating the global estimate of the used space in the container. The details of the score calculation (the way of collecting / transmitting local scores, the final score formula and writing to the contract) are encapsulated in the dependency components, the controller is abstracted from them. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
package loadcontroller
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// Prm groups the required parameters of the Controller's constructor.
|
|
//
|
|
// All values must comply with the requirements imposed on them.
|
|
// Passing incorrect parameter values will result in constructor
|
|
// failure (error or panic depending on the implementation).
|
|
type Prm struct {
|
|
// Iterator over the used space values of the containers
|
|
// collected by the node locally.
|
|
LocalMetrics IteratorProvider
|
|
|
|
// Place of recording the local values of
|
|
// the used space of containers.
|
|
LocalAnnouncementTarget WriterProvider
|
|
|
|
// Iterator over the summarized used space scores
|
|
// from the various network participants.
|
|
AnnouncementAccumulator IteratorProvider
|
|
|
|
// Place of recording the final estimates of
|
|
// the used space of containers.
|
|
ResultReceiver WriterProvider
|
|
}
|
|
|
|
// Controller represents main handler for starting
|
|
// and interrupting container volume estimation.
|
|
//
|
|
// It binds the interfaces of the local value stores
|
|
// to the target storage points. Controller is abstracted
|
|
// from the internal storage device and the network location
|
|
// of the connecting components. At its core, it is a
|
|
// high-level start-stop trigger for calculations.
|
|
//
|
|
// For correct operation, the controller must be created
|
|
// using the constructor (New) based on the required parameters
|
|
// and optional components. After successful creation,
|
|
// the constructor is immediately ready to work through
|
|
// API of external control of calculations and data transfer.
|
|
type Controller struct {
|
|
prm Prm
|
|
|
|
opts *options
|
|
|
|
announceMtx sync.Mutex
|
|
mAnnounceCtx map[uint64]context.CancelFunc
|
|
|
|
reportMtx sync.Mutex
|
|
mReportCtx map[uint64]context.CancelFunc
|
|
}
|
|
|
|
const invalidPrmValFmt = "invalid parameter %s (%T):%v"
|
|
|
|
func panicOnPrmValue(n string, v interface{}) {
|
|
panic(fmt.Sprintf(invalidPrmValFmt, n, v, v))
|
|
}
|
|
|
|
// New creates a new instance of the Controller.
|
|
//
|
|
// Panics if at least one value of the parameters is invalid.
|
|
//
|
|
// The created Controller does not require additional
|
|
// initialization and is completely ready for work
|
|
func New(prm Prm, opts ...Option) *Controller {
|
|
switch {
|
|
case prm.LocalMetrics == nil:
|
|
panicOnPrmValue("LocalMetrics", prm.LocalMetrics)
|
|
case prm.AnnouncementAccumulator == nil:
|
|
panicOnPrmValue("AnnouncementAccumulator", prm.AnnouncementAccumulator)
|
|
case prm.LocalAnnouncementTarget == nil:
|
|
panicOnPrmValue("LocalAnnouncementTarget", prm.LocalAnnouncementTarget)
|
|
case prm.ResultReceiver == nil:
|
|
panicOnPrmValue("ResultReceiver", prm.ResultReceiver)
|
|
}
|
|
|
|
o := defaultOpts()
|
|
|
|
for _, opt := range opts {
|
|
opt(o)
|
|
}
|
|
|
|
return &Controller{
|
|
prm: prm,
|
|
opts: o,
|
|
mAnnounceCtx: make(map[uint64]context.CancelFunc),
|
|
mReportCtx: make(map[uint64]context.CancelFunc),
|
|
}
|
|
}
|