From 7ea1d27783fd25841945a8a04866e82e195b6290 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 5 Jan 2022 09:53:18 +0200 Subject: [PATCH] update for memory status indicator --- rcmgr.go | 6 ++--- scope.go | 78 ++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/rcmgr.go b/rcmgr.go index 51467e8..e3f9c47 100644 --- a/rcmgr.go +++ b/rcmgr.go @@ -339,7 +339,7 @@ func (s *connectionScope) SetPeer(p peer.ID) error { // juggle resources from transient scope to peer scope stat := s.resourceScope.rc.stat() - if err := s.peer.ReserveForChild(stat); err != nil { + if _, err := s.peer.ReserveForChild(stat); err != nil { s.peer.DecRef() s.peer = nil return err @@ -376,7 +376,7 @@ func (s *streamScope) SetProtocol(proto protocol.ID) error { // juggle resources from transient scope to protocol scope stat := s.resourceScope.rc.stat() - if err := s.proto.ReserveForChild(stat); err != nil { + if _, err := s.proto.ReserveForChild(stat); err != nil { s.proto.DecRef() s.proto = nil return err @@ -416,7 +416,7 @@ func (s *streamScope) SetService(svc string) error { s.svc = s.rcmgr.getServiceScope(svc) // reserve resources in service - if err := s.svc.ReserveForChild(s.resourceScope.rc.stat()); err != nil { + if _, err := s.svc.ReserveForChild(s.resourceScope.rc.stat()); err != nil { s.svc.DecRef() s.svc = nil return err diff --git a/scope.go b/scope.go index 17f52a1..ca2c2e5 100644 --- a/scope.go +++ b/scope.go @@ -58,28 +58,36 @@ func newTxnResourceScope(owner *resourceScope) *resourceScope { } // Resources implementation -func (rc *resources) checkMemory(rsvp int64) error { +func (rc *resources) checkMemory(rsvp int64) (network.MemoryStatus, error) { // overflow check; this also has the side effect that we cannot reserve negative memory. newmem := rc.memory + rsvp if newmem < rc.memory { - return fmt.Errorf("memory reservation overflow: %w", network.ErrResourceLimitExceeded) + return network.MemoryStatusOK, fmt.Errorf("memory reservation overflow: %w", network.ErrResourceLimitExceeded) } // limit check - if newmem > rc.limit.GetMemoryLimit() { - return fmt.Errorf("cannot reserve memory: %w", network.ErrResourceLimitExceeded) - } + limit := rc.limit.GetMemoryLimit() + switch { + case newmem > limit: + return network.MemoryStatusOK, fmt.Errorf("cannot reserve memory: %w", network.ErrResourceLimitExceeded) + case newmem > int64(0.8*float64(limit)): + return network.MemoryStatusCritical, nil - return nil + case newmem > int64(0.5*float64(limit)): + return network.MemoryStatusCaution, nil + + default: + return network.MemoryStatusOK, nil + } } -func (rc *resources) reserveMemory(size int64) error { - if err := rc.checkMemory(size); err != nil { - return err +func (rc *resources) reserveMemory(size int64) (status network.MemoryStatus, err error) { + if status, err = rc.checkMemory(size); err != nil { + return status, err } rc.memory += size - return nil + return status, nil } func (rc *resources) releaseMemory(size int64) { @@ -196,37 +204,47 @@ func (rc *resources) stat() network.ScopeStat { } // resourceScope implementation -func (s *resourceScope) ReserveMemory(size int) error { +func (s *resourceScope) ReserveMemory(size int) (status network.MemoryStatus, err error) { s.Lock() defer s.Unlock() if s.done { - return network.ErrResourceScopeClosed + return network.MemoryStatusOK, network.ErrResourceScopeClosed } - if err := s.rc.reserveMemory(int64(size)); err != nil { - return err + if status, err = s.rc.reserveMemory(int64(size)); err != nil { + return status, err } - if err := s.reserveMemoryForConstraints(size); err != nil { + var statusCst network.MemoryStatus + if statusCst, err = s.reserveMemoryForConstraints(size); err != nil { s.rc.releaseMemory(int64(size)) - return err + return status, err } - return nil + if statusCst > status { + status = statusCst + } + + return status, nil } -func (s *resourceScope) reserveMemoryForConstraints(size int) error { +func (s *resourceScope) reserveMemoryForConstraints(size int) (status network.MemoryStatus, err error) { if s.owner != nil { return s.owner.ReserveMemory(size) } var reserved int - var err error for _, cst := range s.constraints { - if err = cst.ReserveMemoryForChild(int64(size)); err != nil { + var statusCst network.MemoryStatus + if statusCst, err = cst.ReserveMemoryForChild(int64(size)); err != nil { break } + + if statusCst > status { + status = statusCst + } + reserved++ } @@ -237,7 +255,7 @@ func (s *resourceScope) reserveMemoryForConstraints(size int) error { } } - return err + return status, err } func (s *resourceScope) releaseMemoryForConstraints(size int) { @@ -251,12 +269,12 @@ func (s *resourceScope) releaseMemoryForConstraints(size int) { } } -func (s *resourceScope) ReserveMemoryForChild(size int64) error { +func (s *resourceScope) ReserveMemoryForChild(size int64) (network.MemoryStatus, error) { s.Lock() defer s.Unlock() if s.done { - return network.ErrResourceScopeClosed + return network.MemoryStatusOK, network.ErrResourceScopeClosed } return s.rc.reserveMemory(size) @@ -460,30 +478,30 @@ func (s *resourceScope) RemoveConnForChild(dir network.Direction, usefd bool) { s.rc.removeConn(dir, usefd) } -func (s *resourceScope) ReserveForChild(st network.ScopeStat) error { +func (s *resourceScope) ReserveForChild(st network.ScopeStat) (status network.MemoryStatus, err error) { s.Lock() defer s.Unlock() if s.done { - return network.ErrResourceScopeClosed + return network.MemoryStatusOK, network.ErrResourceScopeClosed } - if err := s.rc.reserveMemory(st.Memory); err != nil { - return err + if status, err = s.rc.reserveMemory(st.Memory); err != nil { + return status, err } if err := s.rc.addStreams(st.NumStreamsInbound, st.NumStreamsOutbound); err != nil { s.rc.releaseMemory(st.Memory) - return err + return status, err } if err := s.rc.addConns(st.NumConnsInbound, st.NumConnsOutbound, st.NumFD); err != nil { s.rc.releaseMemory(st.Memory) s.rc.removeStreams(st.NumStreamsInbound, st.NumStreamsOutbound) - return err + return status, err } - return nil + return status, nil } func (s *resourceScope) ReleaseForChild(st network.ScopeStat) {