status-go/vendor/github.com/libp2p/go-libp2p/p2p/host/resource-manager/limit.go

267 lines
6.4 KiB
Go
Raw Normal View History

2022-11-04 13:57:20 +00:00
/*
Package rcmgr is the resource manager for go-libp2p. This allows you to track
resources being used throughout your go-libp2p process. As well as making sure
that the process doesn't use more resources than what you define as your
limits. The resource manager only knows about things it is told about, so it's
the responsibility of the user of this library (either go-libp2p or a go-libp2p
user) to make sure they check with the resource manager before actually
allocating the resource.
*/
2022-04-01 16:16:46 +00:00
package rcmgr
import (
"encoding/json"
"io"
2022-11-04 13:57:20 +00:00
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
2022-04-01 16:16:46 +00:00
)
// Limit is an object that specifies basic resource limits.
type Limit interface {
// GetMemoryLimit returns the (current) memory limit.
GetMemoryLimit() int64
// GetStreamLimit returns the stream limit, for inbound or outbound streams.
GetStreamLimit(network.Direction) int
// GetStreamTotalLimit returns the total stream limit
GetStreamTotalLimit() int
// GetConnLimit returns the connection limit, for inbound or outbound connections.
GetConnLimit(network.Direction) int
// GetConnTotalLimit returns the total connection limit
GetConnTotalLimit() int
// GetFDLimit returns the file descriptor limit.
GetFDLimit() int
}
// Limiter is the interface for providing limits to the resource manager.
type Limiter interface {
GetSystemLimits() Limit
GetTransientLimits() Limit
GetAllowlistedSystemLimits() Limit
GetAllowlistedTransientLimits() Limit
2022-04-01 16:16:46 +00:00
GetServiceLimits(svc string) Limit
GetServicePeerLimits(svc string) Limit
GetProtocolLimits(proto protocol.ID) Limit
GetProtocolPeerLimits(proto protocol.ID) Limit
GetPeerLimits(p peer.ID) Limit
GetStreamLimits(p peer.ID) Limit
GetConnLimits() Limit
}
// NewDefaultLimiterFromJSON creates a new limiter by parsing a json configuration,
// using the default limits for fallback.
func NewDefaultLimiterFromJSON(in io.Reader) (Limiter, error) {
return NewLimiterFromJSON(in, DefaultLimits.AutoScale())
2022-04-01 16:16:46 +00:00
}
// NewLimiterFromJSON creates a new limiter by parsing a json configuration.
func NewLimiterFromJSON(in io.Reader, defaults LimitConfig) (Limiter, error) {
cfg, err := readLimiterConfigFromJSON(in, defaults)
if err != nil {
return nil, err
}
return &fixedLimiter{cfg}, nil
}
func readLimiterConfigFromJSON(in io.Reader, defaults LimitConfig) (LimitConfig, error) {
var cfg LimitConfig
if err := json.NewDecoder(in).Decode(&cfg); err != nil {
return LimitConfig{}, err
}
cfg.Apply(defaults)
return cfg, nil
}
// fixedLimiter is a limiter with fixed limits.
type fixedLimiter struct {
LimitConfig
}
var _ Limiter = (*fixedLimiter)(nil)
func NewFixedLimiter(conf LimitConfig) Limiter {
log.Debugw("initializing new limiter with config", "limits", conf)
return &fixedLimiter{LimitConfig: conf}
}
2022-04-01 16:16:46 +00:00
// BaseLimit is a mixin type for basic resource limits.
type BaseLimit struct {
Streams int
StreamsInbound int
StreamsOutbound int
Conns int
ConnsInbound int
ConnsOutbound int
FD int
Memory int64
2022-04-01 16:16:46 +00:00
}
// Apply overwrites all zero-valued limits with the values of l2
// Must not use a pointer receiver.
func (l *BaseLimit) Apply(l2 BaseLimit) {
if l.Streams == 0 {
l.Streams = l2.Streams
}
if l.StreamsInbound == 0 {
l.StreamsInbound = l2.StreamsInbound
}
if l.StreamsOutbound == 0 {
l.StreamsOutbound = l2.StreamsOutbound
}
if l.Conns == 0 {
l.Conns = l2.Conns
}
if l.ConnsInbound == 0 {
l.ConnsInbound = l2.ConnsInbound
}
if l.ConnsOutbound == 0 {
l.ConnsOutbound = l2.ConnsOutbound
}
if l.Memory == 0 {
l.Memory = l2.Memory
}
if l.FD == 0 {
l.FD = l2.FD
}
}
2022-11-04 13:57:20 +00:00
// BaseLimitIncrease is the increase per GiB of allowed memory.
type BaseLimitIncrease struct {
Streams int
StreamsInbound int
StreamsOutbound int
Conns int
ConnsInbound int
ConnsOutbound int
2022-11-04 13:57:20 +00:00
// Memory is in bytes. Values over 1>>30 (1GiB) don't make sense.
Memory int64
// FDFraction is expected to be >= 0 and <= 1.
FDFraction float64
}
// Apply overwrites all zero-valued limits with the values of l2
// Must not use a pointer receiver.
func (l *BaseLimitIncrease) Apply(l2 BaseLimitIncrease) {
if l.Streams == 0 {
l.Streams = l2.Streams
}
if l.StreamsInbound == 0 {
l.StreamsInbound = l2.StreamsInbound
}
if l.StreamsOutbound == 0 {
l.StreamsOutbound = l2.StreamsOutbound
}
if l.Conns == 0 {
l.Conns = l2.Conns
}
if l.ConnsInbound == 0 {
l.ConnsInbound = l2.ConnsInbound
}
if l.ConnsOutbound == 0 {
l.ConnsOutbound = l2.ConnsOutbound
}
if l.Memory == 0 {
l.Memory = l2.Memory
}
if l.FDFraction == 0 {
l.FDFraction = l2.FDFraction
}
2022-04-01 16:16:46 +00:00
}
func (l *BaseLimit) GetStreamLimit(dir network.Direction) int {
if dir == network.DirInbound {
return l.StreamsInbound
} else {
return l.StreamsOutbound
}
}
func (l *BaseLimit) GetStreamTotalLimit() int {
return l.Streams
}
func (l *BaseLimit) GetConnLimit(dir network.Direction) int {
if dir == network.DirInbound {
return l.ConnsInbound
} else {
return l.ConnsOutbound
}
}
func (l *BaseLimit) GetConnTotalLimit() int {
return l.Conns
}
func (l *BaseLimit) GetFDLimit() int {
return l.FD
}
func (l *BaseLimit) GetMemoryLimit() int64 {
return l.Memory
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetSystemLimits() Limit {
return &l.System
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetTransientLimits() Limit {
return &l.Transient
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetAllowlistedSystemLimits() Limit {
return &l.AllowlistedSystem
}
func (l *fixedLimiter) GetAllowlistedTransientLimits() Limit {
return &l.AllowlistedTransient
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetServiceLimits(svc string) Limit {
sl, ok := l.Service[svc]
2022-04-01 16:16:46 +00:00
if !ok {
return &l.ServiceDefault
2022-04-01 16:16:46 +00:00
}
return &sl
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetServicePeerLimits(svc string) Limit {
pl, ok := l.ServicePeer[svc]
2022-04-01 16:16:46 +00:00
if !ok {
return &l.ServicePeerDefault
2022-04-01 16:16:46 +00:00
}
return &pl
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetProtocolLimits(proto protocol.ID) Limit {
pl, ok := l.Protocol[proto]
2022-04-01 16:16:46 +00:00
if !ok {
return &l.ProtocolDefault
2022-04-01 16:16:46 +00:00
}
return &pl
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetProtocolPeerLimits(proto protocol.ID) Limit {
pl, ok := l.ProtocolPeer[proto]
if !ok {
return &l.ProtocolPeerDefault
}
return &pl
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetPeerLimits(p peer.ID) Limit {
pl, ok := l.Peer[p]
if !ok {
return &l.PeerDefault
}
return &pl
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetStreamLimits(_ peer.ID) Limit {
return &l.Stream
2022-04-01 16:16:46 +00:00
}
func (l *fixedLimiter) GetConnLimits() Limit {
return &l.Conn
2022-04-01 16:16:46 +00:00
}