2021-12-23 21:28:14 +08:00
|
|
|
package rcmgr
|
|
|
|
|
|
|
|
import (
|
2021-12-24 00:18:02 +08:00
|
|
|
"context"
|
2021-12-23 21:28:14 +08:00
|
|
|
"fmt"
|
2021-12-23 23:46:08 +08:00
|
|
|
"sync"
|
2021-12-24 00:18:02 +08:00
|
|
|
"time"
|
2021-12-23 21:28:14 +08:00
|
|
|
|
|
|
|
"github.com/libp2p/go-libp2p-core/network"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
"github.com/libp2p/go-libp2p-core/protocol"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ResourceManager struct {
|
2021-12-23 23:46:08 +08:00
|
|
|
limits Limiter
|
|
|
|
|
2021-12-23 21:28:14 +08:00
|
|
|
system *SystemScope
|
|
|
|
transient *TransientScope
|
2021-12-23 23:46:08 +08:00
|
|
|
|
|
|
|
mx sync.Mutex
|
|
|
|
svc map[string]*ServiceScope
|
|
|
|
proto map[protocol.ID]*ProtocolScope
|
|
|
|
peer map[peer.ID]*PeerScope
|
2021-12-24 00:18:02 +08:00
|
|
|
|
|
|
|
cancelCtx context.Context
|
|
|
|
cancel func()
|
|
|
|
wg sync.WaitGroup
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
2021-12-23 23:46:08 +08:00
|
|
|
var _ network.ResourceManager = (*ResourceManager)(nil)
|
|
|
|
|
2021-12-23 21:28:14 +08:00
|
|
|
type SystemScope struct {
|
|
|
|
*ResourceScope
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ network.ResourceScope = (*SystemScope)(nil)
|
|
|
|
|
|
|
|
type TransientScope struct {
|
|
|
|
*ResourceScope
|
|
|
|
|
|
|
|
system *SystemScope
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ network.ResourceScope = (*TransientScope)(nil)
|
|
|
|
|
|
|
|
type ServiceScope struct {
|
|
|
|
*ResourceScope
|
|
|
|
|
|
|
|
name string
|
|
|
|
system *SystemScope
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ network.ServiceScope = (*ServiceScope)(nil)
|
|
|
|
|
|
|
|
type ProtocolScope struct {
|
|
|
|
*ResourceScope
|
|
|
|
|
|
|
|
proto protocol.ID
|
|
|
|
system *SystemScope
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ network.ProtocolScope = (*ProtocolScope)(nil)
|
|
|
|
|
|
|
|
type PeerScope struct {
|
|
|
|
*ResourceScope
|
|
|
|
|
2021-12-26 19:14:59 +08:00
|
|
|
peer peer.ID
|
|
|
|
rcmgr *ResourceManager
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ network.PeerScope = (*PeerScope)(nil)
|
|
|
|
|
|
|
|
type ConnectionScope struct {
|
|
|
|
*ResourceScope
|
|
|
|
|
2021-12-26 19:14:59 +08:00
|
|
|
dir network.Direction
|
|
|
|
usefd bool
|
|
|
|
rcmgr *ResourceManager
|
|
|
|
peer *PeerScope
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ network.ConnectionScope = (*ConnectionScope)(nil)
|
2021-12-24 17:44:01 +08:00
|
|
|
var _ network.UserConnectionScope = (*ConnectionScope)(nil)
|
2021-12-23 21:28:14 +08:00
|
|
|
|
|
|
|
type StreamScope struct {
|
|
|
|
*ResourceScope
|
|
|
|
|
2021-12-26 19:14:59 +08:00
|
|
|
dir network.Direction
|
|
|
|
rcmgr *ResourceManager
|
|
|
|
peer *PeerScope
|
|
|
|
svc *ServiceScope
|
|
|
|
proto *ProtocolScope
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ network.StreamScope = (*StreamScope)(nil)
|
2021-12-24 17:44:01 +08:00
|
|
|
var _ network.UserStreamScope = (*StreamScope)(nil)
|
2021-12-23 21:28:14 +08:00
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
func NewResourceManager(limits Limiter) *ResourceManager {
|
|
|
|
r := &ResourceManager{
|
|
|
|
limits: limits,
|
|
|
|
svc: make(map[string]*ServiceScope),
|
|
|
|
proto: make(map[protocol.ID]*ProtocolScope),
|
|
|
|
peer: make(map[peer.ID]*PeerScope),
|
|
|
|
}
|
|
|
|
|
|
|
|
r.system = NewSystemScope(limits.GetSystemLimits())
|
2021-12-24 18:01:53 +08:00
|
|
|
r.system.IncRef()
|
2021-12-24 00:18:02 +08:00
|
|
|
r.transient = NewTransientScope(limits.GetSystemLimits(), r.system)
|
2021-12-24 18:01:53 +08:00
|
|
|
r.transient.IncRef()
|
2021-12-24 00:18:02 +08:00
|
|
|
|
|
|
|
r.cancelCtx, r.cancel = context.WithCancel(context.Background())
|
|
|
|
|
|
|
|
r.wg.Add(1)
|
|
|
|
go r.background()
|
|
|
|
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
2021-12-24 00:29:41 +08:00
|
|
|
func (r *ResourceManager) ViewSystem(f func(network.ResourceScope) error) error {
|
|
|
|
return f(r.system)
|
2021-12-23 23:46:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 00:29:41 +08:00
|
|
|
func (r *ResourceManager) ViewTransient(f func(network.ResourceScope) error) error {
|
|
|
|
return f(r.transient)
|
2021-12-23 23:46:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 00:29:41 +08:00
|
|
|
func (r *ResourceManager) ViewService(srv string, f func(network.ServiceScope) error) error {
|
2021-12-24 18:01:53 +08:00
|
|
|
s := r.getServiceScope(srv)
|
|
|
|
defer s.DecRef()
|
|
|
|
|
|
|
|
return f(s)
|
2021-12-23 23:46:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 00:29:41 +08:00
|
|
|
func (r *ResourceManager) ViewProtocol(proto protocol.ID, f func(network.ProtocolScope) error) error {
|
2021-12-24 00:39:25 +08:00
|
|
|
s := r.getProtocolScope(proto)
|
2021-12-24 00:29:41 +08:00
|
|
|
defer s.DecRef()
|
|
|
|
|
|
|
|
return f(s)
|
2021-12-23 23:46:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 00:29:41 +08:00
|
|
|
func (r *ResourceManager) ViewPeer(p peer.ID, f func(network.PeerScope) error) error {
|
|
|
|
s := r.getPeerScope(p)
|
|
|
|
defer s.DecRef()
|
|
|
|
|
|
|
|
return f(s)
|
2021-12-23 23:46:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
func (r *ResourceManager) getServiceScope(svc string) *ServiceScope {
|
2021-12-23 23:46:08 +08:00
|
|
|
r.mx.Lock()
|
|
|
|
defer r.mx.Unlock()
|
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
s, ok := r.svc[svc]
|
2021-12-23 23:46:08 +08:00
|
|
|
if !ok {
|
2021-12-24 00:18:02 +08:00
|
|
|
s = NewServiceScope(svc, r.limits.GetServiceLimits(svc), r.system)
|
|
|
|
r.svc[svc] = s
|
2021-12-23 23:46:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 18:01:53 +08:00
|
|
|
s.IncRef()
|
2021-12-23 23:46:08 +08:00
|
|
|
return s
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
func (r *ResourceManager) getProtocolScope(proto protocol.ID) *ProtocolScope {
|
2021-12-23 23:46:08 +08:00
|
|
|
r.mx.Lock()
|
|
|
|
defer r.mx.Unlock()
|
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
s, ok := r.proto[proto]
|
2021-12-23 23:46:08 +08:00
|
|
|
if !ok {
|
2021-12-24 00:18:02 +08:00
|
|
|
s = NewProtocolScope(proto, r.limits.GetProtocolLimits(proto), r.system)
|
|
|
|
r.proto[proto] = s
|
2021-12-23 23:46:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
s.IncRef()
|
2021-12-23 23:46:08 +08:00
|
|
|
return s
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *ResourceManager) getPeerScope(p peer.ID) *PeerScope {
|
2021-12-23 23:46:08 +08:00
|
|
|
r.mx.Lock()
|
|
|
|
defer r.mx.Unlock()
|
2021-12-23 21:28:14 +08:00
|
|
|
|
2021-12-23 23:46:08 +08:00
|
|
|
s, ok := r.peer[p]
|
|
|
|
if !ok {
|
|
|
|
s = NewPeerScope(p, r.limits.GetPeerLimits(p), r)
|
|
|
|
r.peer[p] = s
|
|
|
|
}
|
2021-12-23 21:28:14 +08:00
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
s.IncRef()
|
2021-12-23 23:46:08 +08:00
|
|
|
return s
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *ResourceManager) OpenConnection(dir network.Direction, usefd bool) (network.ConnectionScope, error) {
|
2021-12-23 23:46:08 +08:00
|
|
|
conn := NewConnectionScope(dir, usefd, r.limits.GetConnLimits(), r)
|
2021-12-23 21:28:14 +08:00
|
|
|
|
|
|
|
if err := conn.AddConn(dir); err != nil {
|
2021-12-24 18:01:53 +08:00
|
|
|
conn.Done()
|
2021-12-23 21:28:14 +08:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-12-23 22:13:24 +08:00
|
|
|
if usefd {
|
|
|
|
if err := conn.AddFD(1); err != nil {
|
2021-12-24 18:01:53 +08:00
|
|
|
conn.Done()
|
2021-12-23 22:13:24 +08:00
|
|
|
return nil, err
|
|
|
|
}
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return conn, nil
|
|
|
|
}
|
|
|
|
|
2021-12-24 17:44:01 +08:00
|
|
|
func (r *ResourceManager) OpenStream(p peer.ID, dir network.Direction) (network.StreamScope, error) {
|
|
|
|
peer := r.getPeerScope(p)
|
|
|
|
stream := NewStreamScope(dir, r.limits.GetStreamLimits(p), peer)
|
2021-12-24 18:01:53 +08:00
|
|
|
peer.DecRef() // we have the reference in constraints
|
2021-12-24 17:44:01 +08:00
|
|
|
|
|
|
|
err := stream.AddStream(dir)
|
|
|
|
if err != nil {
|
2021-12-24 18:01:53 +08:00
|
|
|
stream.Done()
|
2021-12-24 17:44:01 +08:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream, nil
|
|
|
|
}
|
|
|
|
|
2021-12-23 23:46:08 +08:00
|
|
|
func (r *ResourceManager) Close() error {
|
2021-12-24 00:18:02 +08:00
|
|
|
r.cancel()
|
|
|
|
r.wg.Wait()
|
|
|
|
|
2021-12-23 23:46:08 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-12-24 00:18:02 +08:00
|
|
|
func (r *ResourceManager) background() {
|
|
|
|
// periodically garbage collects unused peer and protocol scopes
|
|
|
|
ticker := time.NewTicker(time.Minute)
|
|
|
|
defer ticker.Stop()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
|
|
|
r.gc()
|
|
|
|
case <-r.cancelCtx.Done():
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *ResourceManager) gc() {
|
|
|
|
r.mx.Lock()
|
|
|
|
defer r.mx.Unlock()
|
|
|
|
|
|
|
|
for proto, s := range r.proto {
|
|
|
|
if s.IsUnused() {
|
|
|
|
delete(r.proto, proto)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for p, s := range r.peer {
|
|
|
|
if s.IsUnused() {
|
|
|
|
delete(r.peer, p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-23 21:28:14 +08:00
|
|
|
func NewSystemScope(limit Limit) *SystemScope {
|
|
|
|
return &SystemScope{
|
|
|
|
ResourceScope: NewResourceScope(limit, nil),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTransientScope(limit Limit, system *SystemScope) *TransientScope {
|
|
|
|
return &TransientScope{
|
|
|
|
ResourceScope: NewResourceScope(limit, []*ResourceScope{system.ResourceScope}),
|
|
|
|
system: system,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewServiceScope(name string, limit Limit, system *SystemScope) *ServiceScope {
|
|
|
|
return &ServiceScope{
|
|
|
|
ResourceScope: NewResourceScope(limit, []*ResourceScope{system.ResourceScope}),
|
|
|
|
name: name,
|
|
|
|
system: system,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewProtocolScope(proto protocol.ID, limit Limit, system *SystemScope) *ProtocolScope {
|
|
|
|
return &ProtocolScope{
|
|
|
|
ResourceScope: NewResourceScope(limit, []*ResourceScope{system.ResourceScope}),
|
|
|
|
proto: proto,
|
|
|
|
system: system,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPeerScope(p peer.ID, limit Limit, rcmgr *ResourceManager) *PeerScope {
|
|
|
|
return &PeerScope{
|
|
|
|
ResourceScope: NewResourceScope(limit, []*ResourceScope{rcmgr.system.ResourceScope}),
|
|
|
|
peer: p,
|
|
|
|
rcmgr: rcmgr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-23 22:13:24 +08:00
|
|
|
func NewConnectionScope(dir network.Direction, usefd bool, limit Limit, rcmgr *ResourceManager) *ConnectionScope {
|
2021-12-23 21:28:14 +08:00
|
|
|
return &ConnectionScope{
|
|
|
|
ResourceScope: NewResourceScope(limit, []*ResourceScope{rcmgr.transient.ResourceScope, rcmgr.system.ResourceScope}),
|
|
|
|
dir: dir,
|
2021-12-23 22:13:24 +08:00
|
|
|
usefd: usefd,
|
2021-12-23 21:28:14 +08:00
|
|
|
rcmgr: rcmgr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewStreamScope(dir network.Direction, limit Limit, peer *PeerScope) *StreamScope {
|
|
|
|
return &StreamScope{
|
2021-12-26 19:14:59 +08:00
|
|
|
ResourceScope: NewResourceScope(limit, []*ResourceScope{peer.ResourceScope, peer.rcmgr.transient.ResourceScope, peer.rcmgr.system.ResourceScope}),
|
2021-12-23 21:28:14 +08:00
|
|
|
dir: dir,
|
|
|
|
rcmgr: peer.rcmgr,
|
|
|
|
peer: peer,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ServiceScope) Name() string {
|
|
|
|
return s.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ProtocolScope) Protocol() protocol.ID {
|
|
|
|
return s.proto
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *PeerScope) Peer() peer.ID {
|
|
|
|
return s.peer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ConnectionScope) PeerScope() network.PeerScope {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
return s.peer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ConnectionScope) SetPeer(p peer.ID) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
|
|
|
|
if s.peer != nil {
|
|
|
|
return fmt.Errorf("connection scope already attached to a peer")
|
|
|
|
}
|
|
|
|
s.peer = s.rcmgr.getPeerScope(p)
|
|
|
|
|
|
|
|
// juggle resources from transient scope to peer scope
|
|
|
|
mem := s.ResourceScope.rc.memory
|
|
|
|
|
|
|
|
var incount, outcount int
|
|
|
|
if s.dir == network.DirInbound {
|
|
|
|
incount = 1
|
|
|
|
} else {
|
|
|
|
outcount = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.peer.ReserveMemoryForChild(mem); err != nil {
|
2021-12-24 18:01:53 +08:00
|
|
|
s.peer.DecRef()
|
2021-12-26 19:14:59 +08:00
|
|
|
s.peer = nil
|
2021-12-23 21:28:14 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := s.peer.AddConnForChild(incount, outcount); err != nil {
|
|
|
|
s.peer.ReleaseMemoryForChild(mem)
|
2021-12-24 18:01:53 +08:00
|
|
|
s.peer.DecRef()
|
2021-12-26 19:14:59 +08:00
|
|
|
s.peer = nil
|
2021-12-23 21:28:14 +08:00
|
|
|
return err
|
|
|
|
}
|
2021-12-23 22:13:24 +08:00
|
|
|
if s.usefd {
|
|
|
|
if err := s.peer.AddFDForChild(1); err != nil {
|
|
|
|
s.peer.ReleaseMemoryForChild(mem)
|
|
|
|
s.peer.RemoveConnForChild(incount, outcount)
|
2021-12-24 18:01:53 +08:00
|
|
|
s.peer.DecRef()
|
2021-12-26 19:14:59 +08:00
|
|
|
s.peer = nil
|
2021-12-23 22:13:24 +08:00
|
|
|
return err
|
|
|
|
}
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
|
2021-12-26 19:14:59 +08:00
|
|
|
s.rcmgr.transient.ReleaseMemoryForChild(mem)
|
|
|
|
s.rcmgr.transient.RemoveConnForChild(incount, outcount)
|
2021-12-23 22:13:24 +08:00
|
|
|
if s.usefd {
|
2021-12-26 19:14:59 +08:00
|
|
|
s.rcmgr.transient.RemoveFDForChild(1)
|
2021-12-23 22:13:24 +08:00
|
|
|
}
|
2021-12-26 19:14:59 +08:00
|
|
|
s.rcmgr.transient.DecRef() // removed from constraints
|
2021-12-23 21:28:14 +08:00
|
|
|
|
|
|
|
// update constraints
|
|
|
|
constraints := []*ResourceScope{
|
|
|
|
s.peer.ResourceScope,
|
2021-12-26 19:14:59 +08:00
|
|
|
s.rcmgr.system.ResourceScope,
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
s.ResourceScope.constraints = constraints
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StreamScope) ProtocolScope() network.ProtocolScope {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
return s.proto
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StreamScope) SetProtocol(proto protocol.ID) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
|
|
|
|
if s.proto != nil {
|
|
|
|
return fmt.Errorf("stream scope already attached to a protocol")
|
|
|
|
}
|
|
|
|
|
|
|
|
s.proto = s.rcmgr.getProtocolScope(proto)
|
|
|
|
|
|
|
|
// juggle resources from transient scope to protocol scope
|
|
|
|
mem := s.ResourceScope.rc.memory
|
|
|
|
|
|
|
|
var incount, outcount int
|
|
|
|
if s.dir == network.DirInbound {
|
|
|
|
incount = 1
|
|
|
|
} else {
|
|
|
|
outcount = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.proto.ReserveMemoryForChild(mem); err != nil {
|
2021-12-24 18:01:53 +08:00
|
|
|
s.proto.DecRef()
|
|
|
|
s.proto = nil
|
2021-12-23 21:28:14 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := s.proto.AddStreamForChild(incount, outcount); err != nil {
|
|
|
|
s.proto.ReleaseMemoryForChild(mem)
|
2021-12-24 18:01:53 +08:00
|
|
|
s.proto.DecRef()
|
|
|
|
s.proto = nil
|
2021-12-23 21:28:14 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-12-26 19:14:59 +08:00
|
|
|
s.rcmgr.transient.ReleaseMemoryForChild(mem)
|
|
|
|
s.rcmgr.transient.RemoveStreamForChild(incount, outcount)
|
|
|
|
s.rcmgr.transient.DecRef() // removed from constraints
|
2021-12-23 21:28:14 +08:00
|
|
|
|
|
|
|
// update constraints
|
|
|
|
constraints := []*ResourceScope{
|
|
|
|
s.peer.ResourceScope,
|
|
|
|
s.proto.ResourceScope,
|
2021-12-26 19:14:59 +08:00
|
|
|
s.rcmgr.system.ResourceScope,
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
s.ResourceScope.constraints = constraints
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StreamScope) ServiceScope() network.ServiceScope {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
return s.svc
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StreamScope) SetService(svc string) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
|
|
|
|
if s.proto == nil {
|
|
|
|
return fmt.Errorf("stream scope not attached to a protocol")
|
|
|
|
}
|
|
|
|
if s.svc != nil {
|
|
|
|
return fmt.Errorf("stream scope already attached to a service")
|
|
|
|
}
|
|
|
|
|
|
|
|
s.svc = s.rcmgr.getServiceScope(svc)
|
|
|
|
|
|
|
|
// reserve resources in service
|
|
|
|
mem := s.ResourceScope.rc.memory
|
|
|
|
|
|
|
|
var incount, outcount int
|
|
|
|
if s.dir == network.DirInbound {
|
|
|
|
incount = 1
|
|
|
|
} else {
|
|
|
|
outcount = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.svc.ReserveMemoryForChild(mem); err != nil {
|
2021-12-24 18:01:53 +08:00
|
|
|
s.svc.DecRef()
|
|
|
|
s.svc = nil
|
2021-12-23 21:28:14 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := s.svc.AddStreamForChild(incount, outcount); err != nil {
|
|
|
|
s.svc.ReleaseMemoryForChild(mem)
|
2021-12-24 18:01:53 +08:00
|
|
|
s.svc.DecRef()
|
|
|
|
s.svc = nil
|
2021-12-23 21:28:14 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// update constraints
|
|
|
|
constraints := []*ResourceScope{
|
|
|
|
s.peer.ResourceScope,
|
|
|
|
s.proto.ResourceScope,
|
|
|
|
s.svc.ResourceScope,
|
2021-12-26 19:14:59 +08:00
|
|
|
s.rcmgr.system.ResourceScope,
|
2021-12-23 21:28:14 +08:00
|
|
|
}
|
|
|
|
s.ResourceScope.constraints = constraints
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StreamScope) PeerScope() network.PeerScope {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
return s.peer
|
|
|
|
}
|