From cfce3f5cda679505930bb16c73072b4c5996cb3f Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 16 Dec 2021 14:42:41 +0200 Subject: [PATCH 01/55] add resource manager interfaces --- network/rcmgr.go | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 network/rcmgr.go diff --git a/network/rcmgr.go b/network/rcmgr.go new file mode 100644 index 0000000..2e89c4d --- /dev/null +++ b/network/rcmgr.go @@ -0,0 +1,109 @@ +package network + +import ( + "errors" + + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/protocol" +) + +var ( + ErrResourceLimitExceeded = errors.New("resource limit exceeded") + ErrResourceScopeClosed = errors.New("resource scope closed") +) + +// ResourceManager is the interface to the network resource management subsystem +type ResourceManager interface { + // GetProtocolScope retrieves the resource management scope for a specific protocol. + // If there is no configured limits for a particular protocol, then the default scope is + // returned. + GetProtocolScope(protocol.ID) ProtocolScope + // GetPeerScope retrieces the resource management scope for a specific peer. + GetPeerScope(peer.ID) PeerScope + + // OpenConnection creates a connect scope not yet associated with any peer + OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) + + // Close closes the resource manager + Close() error +} + +// ResourceScope is the interface for all scopes. +type ResourceScope interface { + // ReserveMemory reserves memory/buffer space in the scope. + ReserveMemory(size int) error + // ReleaseMemory explicitly releases memory previously reserved with ReserveMemory + ReleaseMemory(size int) + + // GetBuffer reserves memory and allocates a buffer through the buffer pool. + GetBuffer(size int) ([]byte, error) + // GrowBuffer grows a previous allocated buffer, reserving the appropriate memory space. + GrowBuffer(buf []byte, newsize, copy int) ([]byte, error) + // ReleaseBuffer releases a previous allocated buffer. + ReleaseBuffer(buf []byte) + + // Stat retrieves current resource usage for the scope. + Stat() ScopeStat +} + +// TransactionalScope is a mixin interface for transactional scopes. +type TransactionalScope interface { + // Done ends the transaction scope and releases associated resources. + Done() +} + +// ProtocolScope is the interface for protocol resource scopes. +type ProtocolScope interface { + ResourceScope + + // Protocols returns the list of protocol IDs constrained by this scope. + Protocols() []protocol.ID + // IsDefault returns true if this is the default (global) scope. + IsDefault() bool +} + +// PeerScope is the interface for peer resource scopes. +type PeerScope interface { + ResourceScope + + // Peer returns the peer ID for this scope + Peer() peer.ID + + // OpenSconnect creates a new connection scope for this peer. + OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) + // AddConnection adds a previously associated connect to this peer scope. + AddConnection(ConnectionScope) error +} + +// ConnectionScope is the interface for connection resource scopes. +type ConnectionScope interface { + ResourceScope + TransactionalScope + + // PeerScope returns the peer scope associated with this connection. + // It reeturns nil if the connection is not yet asociated with any peer. + PeerScope() PeerScope + + // OpenStream creates a new stream scope, with the specified protocols. + OpenStream(dir Direction, proto ...protocol.ID) (StreamScope, error) +} + +// StreamScope is the interface for stream resource scopes +type StreamScope interface { + ResourceScope + TransactionalScope + + // PeerScope returns the peer resource scope associated with this stream. + PeerScope() PeerScope + // ProtocolScope returns the protocol resource scope associated with this stream. + ProtocolScope() ProtocolScope +} + +// ScopeStat is a struct containing resource accounting information. +type ScopeStat struct { + NumPeers int + NumConns int + NumStreams int + + Memory int +} From 044fbea3462329ff819890a5a812dba1fe202aae Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 16 Dec 2021 14:45:16 +0200 Subject: [PATCH 02/55] add scope accessors to streams and conns --- network/conn.go | 3 +++ network/stream.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/network/conn.go b/network/conn.go index 6d59afc..f4b4e34 100644 --- a/network/conn.go +++ b/network/conn.go @@ -30,6 +30,9 @@ type Conn interface { // GetStreams returns all open streams over this conn. GetStreams() []Stream + + // Scope returns the connection resource scope + Scope() ConnectionScope } // ConnSecurity is the interface that one can mix into a connection interface to diff --git a/network/stream.go b/network/stream.go index c832c12..673a784 100644 --- a/network/stream.go +++ b/network/stream.go @@ -25,4 +25,7 @@ type Stream interface { // Conn returns the connection this stream is part of. Conn() Conn + + // Scope returns the stream resource scope + Scope() StreamScope } From 193ee25a7aa0549476797a93c7a143da7b0777cc Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 16 Dec 2021 14:46:51 +0200 Subject: [PATCH 03/55] add ResourceManager accessor to the Network interface --- network/network.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/network.go b/network/network.go index 3b8550e..7d5373f 100644 --- a/network/network.go +++ b/network/network.go @@ -146,7 +146,8 @@ type Network interface { // use the known local interfaces. InterfaceListenAddresses() ([]ma.Multiaddr, error) - io.Closer + // ResourceManager returns the ResourceManager associated with this network + ResourceManager() ResourceManager } // Dialer represents a service that can dial out to peers From 2afdeee847966c3cb01023bc82bd49a728825ffa Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 16 Dec 2021 14:57:18 +0200 Subject: [PATCH 04/55] allow initially unattached streams. --- network/rcmgr.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 2e89c4d..984407d 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -21,7 +21,7 @@ type ResourceManager interface { // GetPeerScope retrieces the resource management scope for a specific peer. GetPeerScope(peer.ID) PeerScope - // OpenConnection creates a connect scope not yet associated with any peer + // OpenConnection creates a connection scope not yet associated with any peer OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) // Close closes the resource manager @@ -60,6 +60,9 @@ type ProtocolScope interface { Protocols() []protocol.ID // IsDefault returns true if this is the default (global) scope. IsDefault() bool + + // AddStream adds a previously unassociated stream to this protocol scope. + AddStream(StreamScope) error } // PeerScope is the interface for peer resource scopes. @@ -71,7 +74,7 @@ type PeerScope interface { // OpenSconnect creates a new connection scope for this peer. OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) - // AddConnection adds a previously associated connect to this peer scope. + // AddConnection adds a previously associated connection to this peer scope. AddConnection(ConnectionScope) error } @@ -85,6 +88,8 @@ type ConnectionScope interface { PeerScope() PeerScope // OpenStream creates a new stream scope, with the specified protocols. + // An unnegotiated stream will have an empty protocol list and be initially unattached to any + // protocol scope. OpenStream(dir Direction, proto ...protocol.ID) (StreamScope, error) } @@ -95,7 +100,9 @@ type StreamScope interface { // PeerScope returns the peer resource scope associated with this stream. PeerScope() PeerScope + // ProtocolScope returns the protocol resource scope associated with this stream. + // It returns nil if the stream is not associated with any scope. ProtocolScope() ProtocolScope } From 46cbcfec7dd4f6557cc338848787bd889e479f62 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 21 Dec 2021 14:33:20 +0200 Subject: [PATCH 05/55] introduce service scopes, canonicalize ownership interface through setters --- network/rcmgr.go | 53 +++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 984407d..4bf4762 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -14,12 +14,14 @@ var ( // ResourceManager is the interface to the network resource management subsystem type ResourceManager interface { - // GetProtocolScope retrieves the resource management scope for a specific protocol. + // GetService retrieves a service-specific scope + GetService(srv string) ServiceScope + // GetProtocol retrieves the resource management scope for a specific protocol. // If there is no configured limits for a particular protocol, then the default scope is // returned. - GetProtocolScope(protocol.ID) ProtocolScope - // GetPeerScope retrieces the resource management scope for a specific peer. - GetPeerScope(peer.ID) PeerScope + GetProtocol(protocol.ID) ProtocolScope + // GetPeer retrieces the resource management scope for a specific peer. + GetPeer(peer.ID) PeerScope // OpenConnection creates a connection scope not yet associated with any peer OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) @@ -37,7 +39,9 @@ type ResourceScope interface { // GetBuffer reserves memory and allocates a buffer through the buffer pool. GetBuffer(size int) ([]byte, error) - // GrowBuffer grows a previous allocated buffer, reserving the appropriate memory space. + // GrowBuffer atomically grows a previous allocated buffer, reserving the appropriate memory space + // and releasing the old buffer. The copy parameter specifies the number of bytes to copy from + // the old buffer to the newly allocated buffer. GrowBuffer(buf []byte, newsize, copy int) ([]byte, error) // ReleaseBuffer releases a previous allocated buffer. ReleaseBuffer(buf []byte) @@ -52,17 +56,20 @@ type TransactionalScope interface { Done() } +// ServiceScope is the interface for service resource scopes +type ServiceScope interface { + ResourceScope + + // Name returns the name of this service + Name() string +} + // ProtocolScope is the interface for protocol resource scopes. type ProtocolScope interface { ResourceScope // Protocols returns the list of protocol IDs constrained by this scope. Protocols() []protocol.ID - // IsDefault returns true if this is the default (global) scope. - IsDefault() bool - - // AddStream adds a previously unassociated stream to this protocol scope. - AddStream(StreamScope) error } // PeerScope is the interface for peer resource scopes. @@ -74,8 +81,11 @@ type PeerScope interface { // OpenSconnect creates a new connection scope for this peer. OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) - // AddConnection adds a previously associated connection to this peer scope. - AddConnection(ConnectionScope) error + + // OpenStream creates a new stream scope, with the specified protocols. + // An unnegotiated stream will have an empty protocol list and be initially unattached to any + // protocol scope. + OpenStream(dir Direction, proto ...protocol.ID) (StreamScope, error) } // ConnectionScope is the interface for connection resource scopes. @@ -87,10 +97,8 @@ type ConnectionScope interface { // It reeturns nil if the connection is not yet asociated with any peer. PeerScope() PeerScope - // OpenStream creates a new stream scope, with the specified protocols. - // An unnegotiated stream will have an empty protocol list and be initially unattached to any - // protocol scope. - OpenStream(dir Direction, proto ...protocol.ID) (StreamScope, error) + // SetPeer sets the peer for a previously unassociated connection + SetPeer(peer.ID) error } // StreamScope is the interface for stream resource scopes @@ -98,12 +106,19 @@ type StreamScope interface { ResourceScope TransactionalScope - // PeerScope returns the peer resource scope associated with this stream. - PeerScope() PeerScope - // ProtocolScope returns the protocol resource scope associated with this stream. // It returns nil if the stream is not associated with any scope. ProtocolScope() ProtocolScope + // SetProtocol sets the protocol for a previously unnegotiated stream + SetProtocol(proto protocol.ID) error + + // ServiceScope returns the service owning the stream, if any. + ServiceScope() ServiceScope + // SetService sets the service owning this stream + SetService(srv string) error + + // PeerScope returns the peer resource scope associated with this stream. + PeerScope() PeerScope } // ScopeStat is a struct containing resource accounting information. From d4cfc9323ae22b672f2d403e7a0ab3e89207415c Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 21 Dec 2021 16:01:06 +0200 Subject: [PATCH 06/55] make system scope explicit --- network/rcmgr.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/network/rcmgr.go b/network/rcmgr.go index 4bf4762..52a4811 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -14,6 +14,8 @@ var ( // ResourceManager is the interface to the network resource management subsystem type ResourceManager interface { + // GetSystem retrieves the system wide resource scope + GetSystem() SystemScope // GetService retrieves a service-specific scope GetService(srv string) ServiceScope // GetProtocol retrieves the resource management scope for a specific protocol. @@ -56,6 +58,14 @@ type TransactionalScope interface { Done() } +// SystemScope is the system wide resource scope +type SystemScope interface { + ResourceScope + + // Services retrieves a list of active services. + Services() []ServiceScope +} + // ServiceScope is the interface for service resource scopes type ServiceScope interface { ResourceScope From 586f1d0a15cb12ba8ce84eff6a3e1595209ee712 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 21 Dec 2021 16:04:09 +0200 Subject: [PATCH 07/55] make memory stat an int64 --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 52a4811..9499cb0 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -137,5 +137,5 @@ type ScopeStat struct { NumConns int NumStreams int - Memory int + Memory int64 } From b3f9e1d381b05dbda9229ead4f3a5fc82677a0de Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 21 Dec 2021 16:17:55 +0200 Subject: [PATCH 08/55] make the system scope a generic resource scope, introduce the DMZ --- network/rcmgr.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 9499cb0..a3eba9b 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -15,7 +15,9 @@ var ( // ResourceManager is the interface to the network resource management subsystem type ResourceManager interface { // GetSystem retrieves the system wide resource scope - GetSystem() SystemScope + GetSystem() ResourceScope + // GetDMZ retrieves the DMZ resource scope + GetDMZ() ResourceScope // GetService retrieves a service-specific scope GetService(srv string) ServiceScope // GetProtocol retrieves the resource management scope for a specific protocol. @@ -25,7 +27,8 @@ type ResourceManager interface { // GetPeer retrieces the resource management scope for a specific peer. GetPeer(peer.ID) PeerScope - // OpenConnection creates a connection scope not yet associated with any peer + // OpenConnection creates a connection scope not yet associated with any peer; the connection + // is scoped at the DMZ. OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) // Close closes the resource manager @@ -58,14 +61,6 @@ type TransactionalScope interface { Done() } -// SystemScope is the system wide resource scope -type SystemScope interface { - ResourceScope - - // Services retrieves a list of active services. - Services() []ServiceScope -} - // ServiceScope is the interface for service resource scopes type ServiceScope interface { ResourceScope From 35ec4fdbbb670ae37cb912309393732c9b4292c7 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 21 Dec 2021 17:02:37 +0200 Subject: [PATCH 09/55] fix typo Co-authored-by: Marten Seemann --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index a3eba9b..ecc5263 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -84,7 +84,7 @@ type PeerScope interface { // Peer returns the peer ID for this scope Peer() peer.ID - // OpenSconnect creates a new connection scope for this peer. + // OpenConnection creates a new connection scope for this peer. OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) // OpenStream creates a new stream scope, with the specified protocols. From 081233f7c3f7e5c81482b580b334fc95532f45a5 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 21 Dec 2021 17:03:07 +0200 Subject: [PATCH 10/55] fix typo Co-authored-by: Marten Seemann --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index ecc5263..cc1183e 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -85,7 +85,7 @@ type PeerScope interface { Peer() peer.ID // OpenConnection creates a new connection scope for this peer. - OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) + OpenConnection(dir Direction, useFD bool) (ConnectionScope, error) // OpenStream creates a new stream scope, with the specified protocols. // An unnegotiated stream will have an empty protocol list and be initially unattached to any From aeb9233f0e8b6a3d9986c39cf5a9f01e7ae89aea Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 22 Dec 2021 11:17:32 +0200 Subject: [PATCH 11/55] rename DMZ to transient scope, remove OpenConnection from PeerScope --- network/rcmgr.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index cc1183e..f5e6516 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -16,8 +16,8 @@ var ( type ResourceManager interface { // GetSystem retrieves the system wide resource scope GetSystem() ResourceScope - // GetDMZ retrieves the DMZ resource scope - GetDMZ() ResourceScope + // GetTransient retrieves the transient (DMZ) resource scope + GetTransient() ResourceScope // GetService retrieves a service-specific scope GetService(srv string) ServiceScope // GetProtocol retrieves the resource management scope for a specific protocol. @@ -28,7 +28,7 @@ type ResourceManager interface { GetPeer(peer.ID) PeerScope // OpenConnection creates a connection scope not yet associated with any peer; the connection - // is scoped at the DMZ. + // is scoped at the transient scope. OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) // Close closes the resource manager @@ -84,12 +84,9 @@ type PeerScope interface { // Peer returns the peer ID for this scope Peer() peer.ID - // OpenConnection creates a new connection scope for this peer. - OpenConnection(dir Direction, useFD bool) (ConnectionScope, error) - // OpenStream creates a new stream scope, with the specified protocols. - // An unnegotiated stream will have an empty protocol list and be initially unattached to any - // protocol scope. + // An unnegotiated stream will have an empty protocol list and be initially + // unattached to any protocol scope and constrained by the transient scope. OpenStream(dir Direction, proto ...protocol.ID) (StreamScope, error) } From d997bbb6c565d318052420756cb7976d8706ab58 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 22 Dec 2021 12:10:52 +0200 Subject: [PATCH 12/55] remove ncopy param from GrowBuffer --- network/rcmgr.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index f5e6516..11ec034 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -45,9 +45,8 @@ type ResourceScope interface { // GetBuffer reserves memory and allocates a buffer through the buffer pool. GetBuffer(size int) ([]byte, error) // GrowBuffer atomically grows a previous allocated buffer, reserving the appropriate memory space - // and releasing the old buffer. The copy parameter specifies the number of bytes to copy from - // the old buffer to the newly allocated buffer. - GrowBuffer(buf []byte, newsize, copy int) ([]byte, error) + // and releasing the old buffer; the contents of the old buffer are copied to the new one. + GrowBuffer(buf []byte, newsize int) ([]byte, error) // ReleaseBuffer releases a previous allocated buffer. ReleaseBuffer(buf []byte) From 8f759d35ffcf81d02408d95dadbd8b9b797524ee Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 22 Dec 2021 13:18:23 +0200 Subject: [PATCH 13/55] remove protocols from OpenStream The stream is unnegotiated state until the actual protocol has been determined. --- network/rcmgr.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 11ec034..bb8f50f 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -83,10 +83,10 @@ type PeerScope interface { // Peer returns the peer ID for this scope Peer() peer.ID - // OpenStream creates a new stream scope, with the specified protocols. - // An unnegotiated stream will have an empty protocol list and be initially - // unattached to any protocol scope and constrained by the transient scope. - OpenStream(dir Direction, proto ...protocol.ID) (StreamScope, error) + // OpenStream creates a new stream scope, initially unnegotiated. + // An unnegotiated stream will be initially unattached to any protocol scope + // and constrained by the transient scope. + OpenStream(dir Direction) (StreamScope, error) } // ConnectionScope is the interface for connection resource scopes. @@ -108,7 +108,7 @@ type StreamScope interface { TransactionalScope // ProtocolScope returns the protocol resource scope associated with this stream. - // It returns nil if the stream is not associated with any scope. + // It returns nil if the stream is not associated with any protocol scope. ProtocolScope() ProtocolScope // SetProtocol sets the protocol for a previously unnegotiated stream SetProtocol(proto protocol.ID) error From dcef9376da704b38213dedef3a72a8e2c0fdb1e4 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 22 Dec 2021 13:30:57 +0200 Subject: [PATCH 14/55] document nil receiver contract, fix protocol scope protocol accessor method --- network/rcmgr.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index bb8f50f..cedc524 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -13,6 +13,7 @@ var ( ) // ResourceManager is the interface to the network resource management subsystem +// Implementations are required to provide a nil receiver intreface. type ResourceManager interface { // GetSystem retrieves the system wide resource scope GetSystem() ResourceScope @@ -36,6 +37,7 @@ type ResourceManager interface { } // ResourceScope is the interface for all scopes. +// Implementations are required to provide a nil receiver intreface. type ResourceScope interface { // ReserveMemory reserves memory/buffer space in the scope. ReserveMemory(size int) error @@ -55,12 +57,14 @@ type ResourceScope interface { } // TransactionalScope is a mixin interface for transactional scopes. +// Implementations are required to provide a nil receiver intreface. type TransactionalScope interface { // Done ends the transaction scope and releases associated resources. Done() } // ServiceScope is the interface for service resource scopes +// Implementations are required to provide a nil receiver intreface. type ServiceScope interface { ResourceScope @@ -69,14 +73,16 @@ type ServiceScope interface { } // ProtocolScope is the interface for protocol resource scopes. +// Implementations are required to provide a nil receiver intreface. type ProtocolScope interface { ResourceScope - // Protocols returns the list of protocol IDs constrained by this scope. - Protocols() []protocol.ID + // Protocol returns the list of protocol IDs constrained by this scope. + Protocol() protocol.ID } // PeerScope is the interface for peer resource scopes. +// Implementations are required to provide a nil receiver intreface. type PeerScope interface { ResourceScope @@ -90,6 +96,7 @@ type PeerScope interface { } // ConnectionScope is the interface for connection resource scopes. +// Implementations are required to provide a nil receiver intreface. type ConnectionScope interface { ResourceScope TransactionalScope @@ -102,7 +109,8 @@ type ConnectionScope interface { SetPeer(peer.ID) error } -// StreamScope is the interface for stream resource scopes +// StreamScope is the interface for stream resource scopes. +// Implementations are required to provide a nil receiver intreface. type StreamScope interface { ResourceScope TransactionalScope From c52807c6804ee167e9321570779ad04a52e5fe6f Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 23 Dec 2021 10:12:03 +0200 Subject: [PATCH 15/55] remove nil receiver contract requirement --- network/rcmgr.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index cedc524..0071e41 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -13,7 +13,6 @@ var ( ) // ResourceManager is the interface to the network resource management subsystem -// Implementations are required to provide a nil receiver intreface. type ResourceManager interface { // GetSystem retrieves the system wide resource scope GetSystem() ResourceScope @@ -37,7 +36,6 @@ type ResourceManager interface { } // ResourceScope is the interface for all scopes. -// Implementations are required to provide a nil receiver intreface. type ResourceScope interface { // ReserveMemory reserves memory/buffer space in the scope. ReserveMemory(size int) error @@ -57,14 +55,12 @@ type ResourceScope interface { } // TransactionalScope is a mixin interface for transactional scopes. -// Implementations are required to provide a nil receiver intreface. type TransactionalScope interface { // Done ends the transaction scope and releases associated resources. Done() } // ServiceScope is the interface for service resource scopes -// Implementations are required to provide a nil receiver intreface. type ServiceScope interface { ResourceScope @@ -73,7 +69,6 @@ type ServiceScope interface { } // ProtocolScope is the interface for protocol resource scopes. -// Implementations are required to provide a nil receiver intreface. type ProtocolScope interface { ResourceScope @@ -82,7 +77,6 @@ type ProtocolScope interface { } // PeerScope is the interface for peer resource scopes. -// Implementations are required to provide a nil receiver intreface. type PeerScope interface { ResourceScope @@ -96,7 +90,6 @@ type PeerScope interface { } // ConnectionScope is the interface for connection resource scopes. -// Implementations are required to provide a nil receiver intreface. type ConnectionScope interface { ResourceScope TransactionalScope @@ -110,7 +103,6 @@ type ConnectionScope interface { } // StreamScope is the interface for stream resource scopes. -// Implementations are required to provide a nil receiver intreface. type StreamScope interface { ResourceScope TransactionalScope From 76a25c9144453c75f5412f80b918ff2e04d95dd5 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 23 Dec 2021 17:29:18 +0200 Subject: [PATCH 16/55] flesh out stat struct --- network/rcmgr.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 0071e41..7657947 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -124,9 +124,11 @@ type StreamScope interface { // ScopeStat is a struct containing resource accounting information. type ScopeStat struct { - NumPeers int - NumConns int - NumStreams int + NumStreamsInbound int + NumStreamsOutbound int + NumConnsInbound int + NumConnsOutbound int + NumFD int Memory int64 } From 25d49311426474971991a1c4b8636e5832e204f0 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 23 Dec 2021 18:21:32 +0200 Subject: [PATCH 17/55] turn resource manager scope accessors into viewers --- network/rcmgr.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 7657947..b8b5c4e 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -14,18 +14,16 @@ var ( // ResourceManager is the interface to the network resource management subsystem type ResourceManager interface { - // GetSystem retrieves the system wide resource scope - GetSystem() ResourceScope - // GetTransient retrieves the transient (DMZ) resource scope - GetTransient() ResourceScope - // GetService retrieves a service-specific scope - GetService(srv string) ServiceScope - // GetProtocol retrieves the resource management scope for a specific protocol. - // If there is no configured limits for a particular protocol, then the default scope is - // returned. - GetProtocol(protocol.ID) ProtocolScope - // GetPeer retrieces the resource management scope for a specific peer. - GetPeer(peer.ID) PeerScope + // Viewystem views the system wide resource scope + ViewSystem(func(ResourceScope) error) error + // ViewTransient views the transient (DMZ) resource scope + ViewTransient(func(ResourceScope) error) error + // ViewService retrieves a service-specific scope + ViewService(string, func(ServiceScope) error) error + // ViewProtocol views the resource management scope for a specific protocol. + ViewProtocol(protocol.ID, func(ProtocolScope) error) error + // ViewPeer views the resource management scope for a specific peer. + ViewPeer(peer.ID, func(PeerScope) error) error // OpenConnection creates a connection scope not yet associated with any peer; the connection // is scoped at the transient scope. From deb1c1621cb03be90ea9797df8849d45df510c8c Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 24 Dec 2021 11:03:43 +0200 Subject: [PATCH 18/55] interface refiniments 1. Introduce transactions in all scopes 2. Limit the view of stream/connection scope for users, to avoid the Done footgun 3. Move OpenStream to the resource manager --- network/conn.go | 4 ++-- network/rcmgr.go | 33 ++++++++++++++++++++++++--------- network/stream.go | 4 ++-- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/network/conn.go b/network/conn.go index f4b4e34..aef43f1 100644 --- a/network/conn.go +++ b/network/conn.go @@ -31,8 +31,8 @@ type Conn interface { // GetStreams returns all open streams over this conn. GetStreams() []Stream - // Scope returns the connection resource scope - Scope() ConnectionScope + // Scope returns the user view of this connection's resource scope + Scope() UserConnectionScope } // ConnSecurity is the interface that one can mix into a connection interface to diff --git a/network/rcmgr.go b/network/rcmgr.go index b8b5c4e..02238b4 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -25,10 +25,15 @@ type ResourceManager interface { // ViewPeer views the resource management scope for a specific peer. ViewPeer(peer.ID, func(PeerScope) error) error - // OpenConnection creates a connection scope not yet associated with any peer; the connection + // OpenConnection creates a new connection scope not yet associated with any peer; the connection // is scoped at the transient scope. OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) + // OpenStream creates a new stream scope, initially unnegotiated. + // An unnegotiated stream will be initially unattached to any protocol scope + // and constrained by the transient scope. + OpenStream(p peer.ID, dir Direction) (StreamScope, error) + // Close closes the resource manager Close() error } @@ -50,10 +55,14 @@ type ResourceScope interface { // Stat retrieves current resource usage for the scope. Stat() ScopeStat + + // BeginTxn creates a new transactional scope rooted at this scope + BeginTxn() (TransactionalScope, error) } -// TransactionalScope is a mixin interface for transactional scopes. +// TransactionalScope is a ResourceScope with transactional semantics. type TransactionalScope interface { + ResourceScope // Done ends the transaction scope and releases associated resources. Done() } @@ -80,16 +89,10 @@ type PeerScope interface { // Peer returns the peer ID for this scope Peer() peer.ID - - // OpenStream creates a new stream scope, initially unnegotiated. - // An unnegotiated stream will be initially unattached to any protocol scope - // and constrained by the transient scope. - OpenStream(dir Direction) (StreamScope, error) } // ConnectionScope is the interface for connection resource scopes. type ConnectionScope interface { - ResourceScope TransactionalScope // PeerScope returns the peer scope associated with this connection. @@ -100,9 +103,13 @@ type ConnectionScope interface { SetPeer(peer.ID) error } +// UserConnectionScope is the user view of a ConnectionScope +type UserConnectionScope interface { + ResourceScope +} + // StreamScope is the interface for stream resource scopes. type StreamScope interface { - ResourceScope TransactionalScope // ProtocolScope returns the protocol resource scope associated with this stream. @@ -120,6 +127,14 @@ type StreamScope interface { PeerScope() PeerScope } +// UserStreamScope is the user view of a StreamScope +type UserStreamScope interface { + ResourceScope + + // SetService sets the service owning this stream + SetService(srv string) error +} + // ScopeStat is a struct containing resource accounting information. type ScopeStat struct { NumStreamsInbound int diff --git a/network/stream.go b/network/stream.go index 673a784..7a97e7c 100644 --- a/network/stream.go +++ b/network/stream.go @@ -26,6 +26,6 @@ type Stream interface { // Conn returns the connection this stream is part of. Conn() Conn - // Scope returns the stream resource scope - Scope() StreamScope + // Scope returns the user's view of this stream's resource scope + Scope() UserStreamScope } From 1f5a4148055d93682c7fa9eab8c9634d117b0262 Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 27 Dec 2021 15:34:36 +0200 Subject: [PATCH 19/55] add Buffer interface --- network/rcmgr.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 02238b4..a4d8ad8 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -46,12 +46,7 @@ type ResourceScope interface { ReleaseMemory(size int) // GetBuffer reserves memory and allocates a buffer through the buffer pool. - GetBuffer(size int) ([]byte, error) - // GrowBuffer atomically grows a previous allocated buffer, reserving the appropriate memory space - // and releasing the old buffer; the contents of the old buffer are copied to the new one. - GrowBuffer(buf []byte, newsize int) ([]byte, error) - // ReleaseBuffer releases a previous allocated buffer. - ReleaseBuffer(buf []byte) + GetBuffer(size int) (Buffer, error) // Stat retrieves current resource usage for the scope. Stat() ScopeStat @@ -60,6 +55,16 @@ type ResourceScope interface { BeginTxn() (TransactionalScope, error) } +// Buffer is a wrapper for a buffer managed by a resource scope +type Buffer interface { + // Data returns the byte slice for this buffer + Data() []byte + // Grow grows the buffer to a new size + Grow(newsize int) error + // Release releases the buffer + Release() +} + // TransactionalScope is a ResourceScope with transactional semantics. type TransactionalScope interface { ResourceScope From 6400bea66b63616d0f8428e4121f8c8da27773b2 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 28 Dec 2021 18:00:04 +0200 Subject: [PATCH 20/55] fix typo Co-authored-by: Marten Seemann --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index a4d8ad8..46912f0 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -14,7 +14,7 @@ var ( // ResourceManager is the interface to the network resource management subsystem type ResourceManager interface { - // Viewystem views the system wide resource scope + // ViewSystem views the system wide resource scope ViewSystem(func(ResourceScope) error) error // ViewTransient views the transient (DMZ) resource scope ViewTransient(func(ResourceScope) error) error From 33577525d0d1b4375c9dd02dedd81941463b5cf8 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 28 Dec 2021 18:00:32 +0200 Subject: [PATCH 21/55] fix typo Co-authored-by: Marten Seemann --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 46912f0..6a4b43b 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -84,7 +84,7 @@ type ServiceScope interface { type ProtocolScope interface { ResourceScope - // Protocol returns the list of protocol IDs constrained by this scope. + // Protocol returns the protocol for this scope Protocol() protocol.ID } From d99bef0aa28c4da9b64481069cf798f25e585ced Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 28 Dec 2021 18:00:52 +0200 Subject: [PATCH 22/55] fix typo Co-authored-by: Marten Seemann --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 6a4b43b..dbd9b84 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -101,7 +101,7 @@ type ConnectionScope interface { TransactionalScope // PeerScope returns the peer scope associated with this connection. - // It reeturns nil if the connection is not yet asociated with any peer. + // It returns nil if the connection is not yet asociated with any peer. PeerScope() PeerScope // SetPeer sets the peer for a previously unassociated connection From c452665bd127cb9aba2386aa0f1bbaffe40760a0 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 28 Dec 2021 18:08:29 +0200 Subject: [PATCH 23/55] rename user scopes to plain names, management scopes as such --- network/conn.go | 2 +- network/rcmgr.go | 18 +++++++++--------- network/stream.go | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/network/conn.go b/network/conn.go index aef43f1..50127b0 100644 --- a/network/conn.go +++ b/network/conn.go @@ -32,7 +32,7 @@ type Conn interface { GetStreams() []Stream // Scope returns the user view of this connection's resource scope - Scope() UserConnectionScope + Scope() ConnectionScope } // ConnSecurity is the interface that one can mix into a connection interface to diff --git a/network/rcmgr.go b/network/rcmgr.go index dbd9b84..83725f9 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -27,12 +27,12 @@ type ResourceManager interface { // OpenConnection creates a new connection scope not yet associated with any peer; the connection // is scoped at the transient scope. - OpenConnection(dir Direction, usefd bool) (ConnectionScope, error) + OpenConnection(dir Direction, usefd bool) (ConnectionManagementScope, error) // OpenStream creates a new stream scope, initially unnegotiated. // An unnegotiated stream will be initially unattached to any protocol scope // and constrained by the transient scope. - OpenStream(p peer.ID, dir Direction) (StreamScope, error) + OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) // Close closes the resource manager Close() error @@ -96,8 +96,8 @@ type PeerScope interface { Peer() peer.ID } -// ConnectionScope is the interface for connection resource scopes. -type ConnectionScope interface { +// ConnectionManagementScope is the interface for connection resource scopes. +type ConnectionManagementScope interface { TransactionalScope // PeerScope returns the peer scope associated with this connection. @@ -108,13 +108,13 @@ type ConnectionScope interface { SetPeer(peer.ID) error } -// UserConnectionScope is the user view of a ConnectionScope -type UserConnectionScope interface { +// ConnectionScope is the user view of a connection scope +type ConnectionScope interface { ResourceScope } -// StreamScope is the interface for stream resource scopes. -type StreamScope interface { +// StreamManagementScope is the interface for stream resource scopes. +type StreamManagementScope interface { TransactionalScope // ProtocolScope returns the protocol resource scope associated with this stream. @@ -133,7 +133,7 @@ type StreamScope interface { } // UserStreamScope is the user view of a StreamScope -type UserStreamScope interface { +type StreamScope interface { ResourceScope // SetService sets the service owning this stream diff --git a/network/stream.go b/network/stream.go index 7a97e7c..3e32010 100644 --- a/network/stream.go +++ b/network/stream.go @@ -27,5 +27,5 @@ type Stream interface { Conn() Conn // Scope returns the user's view of this stream's resource scope - Scope() UserStreamScope + Scope() StreamScope } From 219e9bccf8f54f1bdce2381d502b745231d476ca Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 28 Dec 2021 18:09:22 +0200 Subject: [PATCH 24/55] rename BeginTxn to BeginTransaction --- network/rcmgr.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 83725f9..a2f970a 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -51,8 +51,8 @@ type ResourceScope interface { // Stat retrieves current resource usage for the scope. Stat() ScopeStat - // BeginTxn creates a new transactional scope rooted at this scope - BeginTxn() (TransactionalScope, error) + // BeginTransaction creates a new transactional scope rooted at this scope + BeginTransaction() (TransactionalScope, error) } // Buffer is a wrapper for a buffer managed by a resource scope From 3ecf62cedf8fa885f69148726bdb513b8773d0ad Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 28 Dec 2021 18:14:28 +0200 Subject: [PATCH 25/55] RIP Buffers --- network/rcmgr.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index a2f970a..eb0c2fd 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -45,9 +45,6 @@ type ResourceScope interface { // ReleaseMemory explicitly releases memory previously reserved with ReserveMemory ReleaseMemory(size int) - // GetBuffer reserves memory and allocates a buffer through the buffer pool. - GetBuffer(size int) (Buffer, error) - // Stat retrieves current resource usage for the scope. Stat() ScopeStat @@ -55,16 +52,6 @@ type ResourceScope interface { BeginTransaction() (TransactionalScope, error) } -// Buffer is a wrapper for a buffer managed by a resource scope -type Buffer interface { - // Data returns the byte slice for this buffer - Data() []byte - // Grow grows the buffer to a new size - Grow(newsize int) error - // Release releases the buffer - Release() -} - // TransactionalScope is a ResourceScope with transactional semantics. type TransactionalScope interface { ResourceScope From 535c09582de1d1a17419de7c83a236d7dbd2f4f8 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 29 Dec 2021 19:59:30 +0200 Subject: [PATCH 26/55] make ErrResourceLimitExceeded a temporary error; move rcmgr errors with the other errors. --- network/errors.go | 21 ++++++++++++++++++++- network/rcmgr.go | 7 ------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/network/errors.go b/network/errors.go index fa75f3e..b42b4a1 100644 --- a/network/errors.go +++ b/network/errors.go @@ -1,6 +1,17 @@ package network -import "errors" +import ( + "errors" + "net" +) + +type TemporaryError string + +func (e TemporaryError) Error() string { return string(e) } +func (e TemporaryError) Temporary() bool { return true } +func (e TemporaryError) Timeout() bool { return false } + +var _ net.Error = TemporaryError("") // ErrNoRemoteAddrs is returned when there are no addresses associated with a peer during a dial. var ErrNoRemoteAddrs = errors.New("no remote addresses") @@ -12,3 +23,11 @@ var ErrNoConn = errors.New("no usable connection to peer") // ErrTransientConn is returned when attempting to open a stream to a peer with only a transient // connection, without specifying the UseTransient option. var ErrTransientConn = errors.New("transient connection to peer") + +// ErrResourceLimitExceeded is returned when attempting to perform an operation that would +// exceed system resource limits. +var ErrResourceLimitExceeded = TemporaryError("resource limit exceeded") + +// ErrResourceScopeClosed is returned when attemptig to reserve resources in a closed resource +// scope. +var ErrResourceScopeClosed = errors.New("resource scope closed") diff --git a/network/rcmgr.go b/network/rcmgr.go index eb0c2fd..a11f934 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -1,17 +1,10 @@ package network import ( - "errors" - "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/protocol" ) -var ( - ErrResourceLimitExceeded = errors.New("resource limit exceeded") - ErrResourceScopeClosed = errors.New("resource scope closed") -) - // ResourceManager is the interface to the network resource management subsystem type ResourceManager interface { // ViewSystem views the system wide resource scope From caacd9659af8bd07dda7684098135faeee29f478 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 30 Dec 2021 11:20:45 +0200 Subject: [PATCH 27/55] unexport TemporaryError --- network/errors.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/network/errors.go b/network/errors.go index b42b4a1..2209ee2 100644 --- a/network/errors.go +++ b/network/errors.go @@ -5,13 +5,13 @@ import ( "net" ) -type TemporaryError string +type temporaryError string -func (e TemporaryError) Error() string { return string(e) } -func (e TemporaryError) Temporary() bool { return true } -func (e TemporaryError) Timeout() bool { return false } +func (e temporaryError) Error() string { return string(e) } +func (e temporaryError) Temporary() bool { return true } +func (e temporaryError) Timeout() bool { return false } -var _ net.Error = TemporaryError("") +var _ net.Error = temporaryError("") // ErrNoRemoteAddrs is returned when there are no addresses associated with a peer during a dial. var ErrNoRemoteAddrs = errors.New("no remote addresses") @@ -26,7 +26,7 @@ var ErrTransientConn = errors.New("transient connection to peer") // ErrResourceLimitExceeded is returned when attempting to perform an operation that would // exceed system resource limits. -var ErrResourceLimitExceeded = TemporaryError("resource limit exceeded") +var ErrResourceLimitExceeded = temporaryError("resource limit exceeded") // ErrResourceScopeClosed is returned when attemptig to reserve resources in a closed resource // scope. From a5d2e419167c9549728d8bc0603e92457a142917 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 31 Dec 2021 10:48:37 +0200 Subject: [PATCH 28/55] null resource manager stub --- network/rcmgr.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/network/rcmgr.go b/network/rcmgr.go index a11f934..ee539ef 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -130,3 +130,61 @@ type ScopeStat struct { Memory int64 } + +// NullResourceManager is a stub for tests and initialization of default values +type NullResourceManager struct{} + +var _ ResourceManager = (*NullResourceManager)(nil) + +// NullScope is a stub for scopes used by the NullResourceManager +type NullScope struct{} + +var _ ResourceScope = (*NullScope)(nil) +var _ TransactionalScope = (*NullScope)(nil) +var _ ServiceScope = (*NullScope)(nil) +var _ ProtocolScope = (*NullScope)(nil) +var _ PeerScope = (*NullScope)(nil) +var _ ConnectionManagementScope = (*NullScope)(nil) +var _ ConnectionScope = (*NullScope)(nil) +var _ StreamManagementScope = (*NullScope)(nil) +var _ StreamScope = (*NullScope)(nil) + +func (n *NullResourceManager) ViewSystem(f func(ResourceScope) error) error { + return f((*NullScope)(nil)) +} +func (n *NullResourceManager) ViewTransient(f func(ResourceScope) error) error { + return f((*NullScope)(nil)) +} +func (n *NullResourceManager) ViewService(svc string, f func(ServiceScope) error) error { + return f((*NullScope)(nil)) +} +func (n *NullResourceManager) ViewProtocol(p protocol.ID, f func(ProtocolScope) error) error { + return f((*NullScope)(nil)) +} +func (n *NullResourceManager) ViewPeer(p peer.ID, f func(PeerScope) error) error { + return f((*NullScope)(nil)) +} +func (n *NullResourceManager) OpenConnection(dir Direction, usefd bool) (ConnectionManagementScope, error) { + return (*NullScope)(nil), nil +} +func (n *NullResourceManager) OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) { + return (*NullScope)(nil), nil +} +func (n *NullResourceManager) Close() error { + return nil +} + +func (n *NullScope) ReserveMemory(size int) error { return nil } +func (n *NullScope) ReleaseMemory(size int) {} +func (n *NullScope) Stat() ScopeStat { return ScopeStat{} } +func (n *NullScope) BeginTransaction() (TransactionalScope, error) { return (*NullScope)(nil), nil } +func (n *NullScope) Done() {} +func (n *NullScope) Name() string { return "" } +func (n *NullScope) Protocol() protocol.ID { return "" } +func (n *NullScope) Peer() peer.ID { return "" } +func (n *NullScope) PeerScope() PeerScope { return (*NullScope)(nil) } +func (n *NullScope) SetPeer(peer.ID) error { return nil } +func (n *NullScope) ProtocolScope() ProtocolScope { return (*NullScope)(nil) } +func (n *NullScope) SetProtocol(proto protocol.ID) error { return nil } +func (n *NullScope) ServiceScope() ServiceScope { return (*NullScope)(nil) } +func (n *NullScope) SetService(srv string) error { return nil } From b948cd7553c4b5fd4af1b0df954f9ce24c70ac0d Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 31 Dec 2021 10:53:15 +0200 Subject: [PATCH 29/55] unexport the null stubs, make entry point a variable --- network/rcmgr.go | 84 +++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index ee539ef..aabe533 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -132,59 +132,57 @@ type ScopeStat struct { } // NullResourceManager is a stub for tests and initialization of default values -type NullResourceManager struct{} +var NullResourceManager ResourceManager = (*nullResourceManager)(nil) -var _ ResourceManager = (*NullResourceManager)(nil) +type nullResourceManager struct{} +type nullScope struct{} -// NullScope is a stub for scopes used by the NullResourceManager -type NullScope struct{} +var _ ResourceScope = (*nullScope)(nil) +var _ TransactionalScope = (*nullScope)(nil) +var _ ServiceScope = (*nullScope)(nil) +var _ ProtocolScope = (*nullScope)(nil) +var _ PeerScope = (*nullScope)(nil) +var _ ConnectionManagementScope = (*nullScope)(nil) +var _ ConnectionScope = (*nullScope)(nil) +var _ StreamManagementScope = (*nullScope)(nil) +var _ StreamScope = (*nullScope)(nil) -var _ ResourceScope = (*NullScope)(nil) -var _ TransactionalScope = (*NullScope)(nil) -var _ ServiceScope = (*NullScope)(nil) -var _ ProtocolScope = (*NullScope)(nil) -var _ PeerScope = (*NullScope)(nil) -var _ ConnectionManagementScope = (*NullScope)(nil) -var _ ConnectionScope = (*NullScope)(nil) -var _ StreamManagementScope = (*NullScope)(nil) -var _ StreamScope = (*NullScope)(nil) - -func (n *NullResourceManager) ViewSystem(f func(ResourceScope) error) error { - return f((*NullScope)(nil)) +func (n *nullResourceManager) ViewSystem(f func(ResourceScope) error) error { + return f((*nullScope)(nil)) } -func (n *NullResourceManager) ViewTransient(f func(ResourceScope) error) error { - return f((*NullScope)(nil)) +func (n *nullResourceManager) ViewTransient(f func(ResourceScope) error) error { + return f((*nullScope)(nil)) } -func (n *NullResourceManager) ViewService(svc string, f func(ServiceScope) error) error { - return f((*NullScope)(nil)) +func (n *nullResourceManager) ViewService(svc string, f func(ServiceScope) error) error { + return f((*nullScope)(nil)) } -func (n *NullResourceManager) ViewProtocol(p protocol.ID, f func(ProtocolScope) error) error { - return f((*NullScope)(nil)) +func (n *nullResourceManager) ViewProtocol(p protocol.ID, f func(ProtocolScope) error) error { + return f((*nullScope)(nil)) } -func (n *NullResourceManager) ViewPeer(p peer.ID, f func(PeerScope) error) error { - return f((*NullScope)(nil)) +func (n *nullResourceManager) ViewPeer(p peer.ID, f func(PeerScope) error) error { + return f((*nullScope)(nil)) } -func (n *NullResourceManager) OpenConnection(dir Direction, usefd bool) (ConnectionManagementScope, error) { - return (*NullScope)(nil), nil +func (n *nullResourceManager) OpenConnection(dir Direction, usefd bool) (ConnectionManagementScope, error) { + return (*nullScope)(nil), nil } -func (n *NullResourceManager) OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) { - return (*NullScope)(nil), nil +func (n *nullResourceManager) OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) { + return (*nullScope)(nil), nil } -func (n *NullResourceManager) Close() error { +func (n *nullResourceManager) Close() error { return nil } -func (n *NullScope) ReserveMemory(size int) error { return nil } -func (n *NullScope) ReleaseMemory(size int) {} -func (n *NullScope) Stat() ScopeStat { return ScopeStat{} } -func (n *NullScope) BeginTransaction() (TransactionalScope, error) { return (*NullScope)(nil), nil } -func (n *NullScope) Done() {} -func (n *NullScope) Name() string { return "" } -func (n *NullScope) Protocol() protocol.ID { return "" } -func (n *NullScope) Peer() peer.ID { return "" } -func (n *NullScope) PeerScope() PeerScope { return (*NullScope)(nil) } -func (n *NullScope) SetPeer(peer.ID) error { return nil } -func (n *NullScope) ProtocolScope() ProtocolScope { return (*NullScope)(nil) } -func (n *NullScope) SetProtocol(proto protocol.ID) error { return nil } -func (n *NullScope) ServiceScope() ServiceScope { return (*NullScope)(nil) } -func (n *NullScope) SetService(srv string) error { return nil } +func (n *nullScope) ReserveMemory(size int) error { return nil } +func (n *nullScope) ReleaseMemory(size int) {} +func (n *nullScope) Stat() ScopeStat { return ScopeStat{} } +func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return (*nullScope)(nil), nil } +func (n *nullScope) Done() {} +func (n *nullScope) Name() string { return "" } +func (n *nullScope) Protocol() protocol.ID { return "" } +func (n *nullScope) Peer() peer.ID { return "" } +func (n *nullScope) PeerScope() PeerScope { return (*nullScope)(nil) } +func (n *nullScope) SetPeer(peer.ID) error { return nil } +func (n *nullScope) ProtocolScope() ProtocolScope { return (*nullScope)(nil) } +func (n *nullScope) SetProtocol(proto protocol.ID) error { return nil } +func (n *nullScope) ServiceScope() ServiceScope { return (*nullScope)(nil) } +func (n *nullScope) SetService(srv string) error { return nil } From 48c94b6fddece13ec7ec3fe543c982270809a4fd Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 31 Dec 2021 11:03:04 +0200 Subject: [PATCH 30/55] don't rely on typed nils but instead use actual null object instances So that we don't confuse the hell out of everyone! --- network/rcmgr.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index aabe533..1fa6e0a 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -132,7 +132,7 @@ type ScopeStat struct { } // NullResourceManager is a stub for tests and initialization of default values -var NullResourceManager ResourceManager = (*nullResourceManager)(nil) +var NullResourceManager ResourceManager = &nullResourceManager{} type nullResourceManager struct{} type nullScope struct{} @@ -147,26 +147,28 @@ var _ ConnectionScope = (*nullScope)(nil) var _ StreamManagementScope = (*nullScope)(nil) var _ StreamScope = (*nullScope)(nil) +var nullScopeObj = &nullScope{} + func (n *nullResourceManager) ViewSystem(f func(ResourceScope) error) error { - return f((*nullScope)(nil)) + return f(nullScopeObj) } func (n *nullResourceManager) ViewTransient(f func(ResourceScope) error) error { - return f((*nullScope)(nil)) + return f(nullScopeObj) } func (n *nullResourceManager) ViewService(svc string, f func(ServiceScope) error) error { - return f((*nullScope)(nil)) + return f(nullScopeObj) } func (n *nullResourceManager) ViewProtocol(p protocol.ID, f func(ProtocolScope) error) error { - return f((*nullScope)(nil)) + return f(nullScopeObj) } func (n *nullResourceManager) ViewPeer(p peer.ID, f func(PeerScope) error) error { - return f((*nullScope)(nil)) + return f(nullScopeObj) } func (n *nullResourceManager) OpenConnection(dir Direction, usefd bool) (ConnectionManagementScope, error) { - return (*nullScope)(nil), nil + return nullScopeObj, nil } func (n *nullResourceManager) OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) { - return (*nullScope)(nil), nil + return nullScopeObj, nil } func (n *nullResourceManager) Close() error { return nil @@ -175,14 +177,14 @@ func (n *nullResourceManager) Close() error { func (n *nullScope) ReserveMemory(size int) error { return nil } func (n *nullScope) ReleaseMemory(size int) {} func (n *nullScope) Stat() ScopeStat { return ScopeStat{} } -func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return (*nullScope)(nil), nil } +func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return nullScopeObj, nil } func (n *nullScope) Done() {} func (n *nullScope) Name() string { return "" } func (n *nullScope) Protocol() protocol.ID { return "" } func (n *nullScope) Peer() peer.ID { return "" } -func (n *nullScope) PeerScope() PeerScope { return (*nullScope)(nil) } +func (n *nullScope) PeerScope() PeerScope { return nullScopeObj } func (n *nullScope) SetPeer(peer.ID) error { return nil } -func (n *nullScope) ProtocolScope() ProtocolScope { return (*nullScope)(nil) } +func (n *nullScope) ProtocolScope() ProtocolScope { return nullScopeObj } func (n *nullScope) SetProtocol(proto protocol.ID) error { return nil } -func (n *nullScope) ServiceScope() ServiceScope { return (*nullScope)(nil) } +func (n *nullScope) ServiceScope() ServiceScope { return nullScopeObj } func (n *nullScope) SetService(srv string) error { return nil } From 5fcc7b607478c0abef5da03070ff078e833af7bd Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 31 Dec 2021 14:12:57 +0200 Subject: [PATCH 31/55] add Scope to the CapableConn interface --- network/conn.go | 11 ++++++++--- transport/transport.go | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/network/conn.go b/network/conn.go index 50127b0..791781a 100644 --- a/network/conn.go +++ b/network/conn.go @@ -20,6 +20,7 @@ type Conn interface { ConnSecurity ConnMultiaddrs ConnStat + ConnScope // ID returns an identifier that uniquely identifies this Conn within this // host, during this run. Connection IDs may repeat across restarts. @@ -30,9 +31,6 @@ type Conn interface { // GetStreams returns all open streams over this conn. GetStreams() []Stream - - // Scope returns the user view of this connection's resource scope - Scope() ConnectionScope } // ConnSecurity is the interface that one can mix into a connection interface to @@ -68,3 +66,10 @@ type ConnStat interface { // Stat stores metadata pertaining to this conn. Stat() ConnStats } + +// ConnScope is the interface that one can mix into a connection interfac to give it a resource +// management scope +type ConnScope interface { + // Scope returns the user view of this connection's resource scope + Scope() ConnectionScope +} diff --git a/transport/transport.go b/transport/transport.go index f413eb6..e2951ef 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -28,6 +28,7 @@ type CapableConn interface { mux.MuxedConn network.ConnSecurity network.ConnMultiaddrs + network.ConnScope // Transport returns the transport to which this connection belongs. Transport() Transport From 625a159ca921471580cd0155c790535ba322ac71 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 31 Dec 2021 14:24:03 +0200 Subject: [PATCH 32/55] rename ConnectionScope to ConnScope for consistency --- network/conn.go | 8 ++++---- network/rcmgr.go | 6 +++--- transport/transport.go | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/network/conn.go b/network/conn.go index 791781a..ca39140 100644 --- a/network/conn.go +++ b/network/conn.go @@ -20,7 +20,7 @@ type Conn interface { ConnSecurity ConnMultiaddrs ConnStat - ConnScope + ConnScoper // ID returns an identifier that uniquely identifies this Conn within this // host, during this run. Connection IDs may repeat across restarts. @@ -67,9 +67,9 @@ type ConnStat interface { Stat() ConnStats } -// ConnScope is the interface that one can mix into a connection interfac to give it a resource +// ConnScoper is the interface that one can mix into a connection interfac to give it a resource // management scope -type ConnScope interface { +type ConnScoper interface { // Scope returns the user view of this connection's resource scope - Scope() ConnectionScope + Scope() ConnScope } diff --git a/network/rcmgr.go b/network/rcmgr.go index 1fa6e0a..3316c6e 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -88,8 +88,8 @@ type ConnectionManagementScope interface { SetPeer(peer.ID) error } -// ConnectionScope is the user view of a connection scope -type ConnectionScope interface { +// ConnScope is the user view of a connection scope +type ConnScope interface { ResourceScope } @@ -143,7 +143,7 @@ var _ ServiceScope = (*nullScope)(nil) var _ ProtocolScope = (*nullScope)(nil) var _ PeerScope = (*nullScope)(nil) var _ ConnectionManagementScope = (*nullScope)(nil) -var _ ConnectionScope = (*nullScope)(nil) +var _ ConnScope = (*nullScope)(nil) var _ StreamManagementScope = (*nullScope)(nil) var _ StreamScope = (*nullScope)(nil) diff --git a/transport/transport.go b/transport/transport.go index e2951ef..c4c4e25 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -28,7 +28,7 @@ type CapableConn interface { mux.MuxedConn network.ConnSecurity network.ConnMultiaddrs - network.ConnScope + network.ConnScoper // Transport returns the transport to which this connection belongs. Transport() Transport From f205ca6d1220010936711993b46ae4d833ffa601 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 31 Dec 2021 14:25:45 +0200 Subject: [PATCH 33/55] fix typo --- network/conn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/conn.go b/network/conn.go index ca39140..b131bcc 100644 --- a/network/conn.go +++ b/network/conn.go @@ -67,7 +67,7 @@ type ConnStat interface { Stat() ConnStats } -// ConnScoper is the interface that one can mix into a connection interfac to give it a resource +// ConnScoper is the interface that one can mix into a connection interface to give it a resource // management scope type ConnScoper interface { // Scope returns the user view of this connection's resource scope From 31b6a33deebb268c693458f2b8b6208b7e965d7a Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 31 Dec 2021 14:30:08 +0200 Subject: [PATCH 34/55] rename ConnectionManagementScope to ConnManagementScope --- network/rcmgr.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 3316c6e..d5b5c09 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -20,7 +20,7 @@ type ResourceManager interface { // OpenConnection creates a new connection scope not yet associated with any peer; the connection // is scoped at the transient scope. - OpenConnection(dir Direction, usefd bool) (ConnectionManagementScope, error) + OpenConnection(dir Direction, usefd bool) (ConnManagementScope, error) // OpenStream creates a new stream scope, initially unnegotiated. // An unnegotiated stream will be initially unattached to any protocol scope @@ -76,8 +76,8 @@ type PeerScope interface { Peer() peer.ID } -// ConnectionManagementScope is the interface for connection resource scopes. -type ConnectionManagementScope interface { +// ConnManagementScope is the interface for connection resource scopes. +type ConnManagementScope interface { TransactionalScope // PeerScope returns the peer scope associated with this connection. @@ -142,7 +142,7 @@ var _ TransactionalScope = (*nullScope)(nil) var _ ServiceScope = (*nullScope)(nil) var _ ProtocolScope = (*nullScope)(nil) var _ PeerScope = (*nullScope)(nil) -var _ ConnectionManagementScope = (*nullScope)(nil) +var _ ConnManagementScope = (*nullScope)(nil) var _ ConnScope = (*nullScope)(nil) var _ StreamManagementScope = (*nullScope)(nil) var _ StreamScope = (*nullScope)(nil) @@ -164,7 +164,7 @@ func (n *nullResourceManager) ViewProtocol(p protocol.ID, f func(ProtocolScope) func (n *nullResourceManager) ViewPeer(p peer.ID, f func(PeerScope) error) error { return f(nullScopeObj) } -func (n *nullResourceManager) OpenConnection(dir Direction, usefd bool) (ConnectionManagementScope, error) { +func (n *nullResourceManager) OpenConnection(dir Direction, usefd bool) (ConnManagementScope, error) { return nullScopeObj, nil } func (n *nullResourceManager) OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) { From f4f1520d99c1df5d1d2389f4d12e10b563047d01 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Tue, 4 Jan 2022 13:56:04 +0400 Subject: [PATCH 35/55] add the ConnManagementScope to Upgrader.Upgrade --- transport/transport.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/transport.go b/transport/transport.go index 257d37d..2f1b849 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -113,5 +113,5 @@ type Upgrader interface { // UpgradeListener upgrades the passed multiaddr-net listener into a full libp2p-transport listener. UpgradeListener(Transport, manet.Listener) Listener // Upgrade upgrades the multiaddr/net connection into a full libp2p-transport connection. - Upgrade(ctx context.Context, t Transport, maconn manet.Conn, dir network.Direction, p peer.ID) (CapableConn, error) + Upgrade(ctx context.Context, t Transport, maconn manet.Conn, dir network.Direction, p peer.ID, rcmgr network.ConnManagementScope) (CapableConn, error) } From d2ff788907326b7514bf256791c7a9b3105ecb34 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Tue, 4 Jan 2022 13:58:37 +0400 Subject: [PATCH 36/55] fix argument name --- transport/transport.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/transport.go b/transport/transport.go index 2f1b849..dcdf741 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -113,5 +113,5 @@ type Upgrader interface { // UpgradeListener upgrades the passed multiaddr-net listener into a full libp2p-transport listener. UpgradeListener(Transport, manet.Listener) Listener // Upgrade upgrades the multiaddr/net connection into a full libp2p-transport connection. - Upgrade(ctx context.Context, t Transport, maconn manet.Conn, dir network.Direction, p peer.ID, rcmgr network.ConnManagementScope) (CapableConn, error) + Upgrade(ctx context.Context, t Transport, maconn manet.Conn, dir network.Direction, p peer.ID, scope network.ConnManagementScope) (CapableConn, error) } From d1a82f1abad98027c07a8782a20cbef5fdb3aaf1 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 4 Jan 2022 22:36:47 +0200 Subject: [PATCH 37/55] godocs for ResourceManager --- network/rcmgr.go | 114 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index d5b5c09..aa7dcbc 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -5,26 +5,110 @@ import ( "github.com/libp2p/go-libp2p-core/protocol" ) -// ResourceManager is the interface to the network resource management subsystem +// ResourceManager is the interface to the network resource management subsystem. +// The ResourceManager tracks and accounts for resource usage in the stack, from the internals +// to the application, and provides a mechanism to limit resource usage according to a user +// configurable policy. +// +// Resource Management through the ResourceManager is based on the concept of Resource +// Management Scopes, whereby resource usage is constrained by a DAG of scopes, +// The following diagram illustrates the structure of the resource constraint DAG: +// System +// +------------> Transient.............+................+ +// | . . +// +------------> Service------------- . ----------+ . +// | . | . +// +-------------> Protocol----------- . ----------+ . +// | . | . +// +--------------> Peer \ | . +// +------------> Connection | . +// | \ \ +// +---------------------------> Stream +// +// The basic resources accounted by the ResourceManager include memory, streams, connections, +// and file descriptors. These account for both space and time used by +// the stack, as each resource has a direct effect on the system +// availability and performance. +// +// The modus operandi of the resource manager is to restrict resource usage at the time of +// reservation. When a component of the stack needs to use a resource, it reserves it in the +// appropriate scope. The resource manager gates the reservation against the scope applicable +// limits; if the limit is exceeded, then an error (wrapping ErrResourceLimitExceeded) and it +// is up the component to act accordingly. At the lower levels of the stack, this will normally +// signal a filure of some sorts, like failing to opening a stream or a connection, which will +// propagate to the programmer. Some components may be able to handle resource reservation failure +// more gracefully; for instance a muxer trying to grow a buffer for a window change, will simply +// retain the existing window size and continue to operate normally albeit with some degraded +// throughput. +// All resources reserved in some scope are released when the scope is closed. For low level +// scopes, mainly Connection and Stream scopes, this happens when the connection or stream is +// closed. +// +// Service programmers will typically use the resource manager to reserve memory +// for their subsystem. +// This happens with two avenues: the programmer can attach a stream to a service, whereby +// resources reserved by the stream are automatically accounted in the service budget; or the +// programmer may directly interact with the service scope, by using ViewService through the +// resource manager interface. +// +// Application programmers can also directly reserve memory in some applicable scope. In order +// to failicate control flow delimited resource accounting, all scopes defined in the system +// allow for the user to create transactions. Transactions are temporary scopes rooted at some +// other scope and release their resources when the programmer is done with them. Transaction +// scopes can form trees, with nested transactions. +// +// Typical Usage: +// - Low level components of the system (transports, muxers) all have access to the resource +// manageer and create connection and stream scopes through it. These scopes are accessible +// to the user, albeit with a narrower interface, through Conn and Stream objects who have +// a Scope method. +// - Services typically center around streams, where the programmer can attach streams to a +// particular service. They can also directly reserve memory for a service by accessing the +// service scope using the ResourceManager interface. +// - Applications that want to account for their network resource usage can reserve memory, +// typically using a transaction, directly in the System or a Service scope; they can also +// opt to use appropriate steam scopes for streams that they create or own. +// +// User Serviceable Parts: the user has the option to specify their own implementation of the +// interface. We provide a canonical implementation in the go-libp2p-resource-manager package. +// The user of that package can specify limits for the various scopes, which can be static +// or dynamic. type ResourceManager interface { - // ViewSystem views the system wide resource scope + // ViewSystem views the system wide resource scope. + // The system scope is the top level scope that accounts for global + // resource usage at all levels of the system. This scope constrains all + // other scopes and institutes global hard limits. ViewSystem(func(ResourceScope) error) error - // ViewTransient views the transient (DMZ) resource scope + + // ViewTransient views the transient (DMZ) resource scope. + // The transient scope accounts for resources that are in the process of + // full establishment. For instance, a new connection prior to the + // handshake does not belong to any peer, but it still needs to be + // constrained as this opens an avenue for attacks in transient resource + // usage. Similarly, a stream that has not negotiated a protocol yet is + // constrained by the transient scope. ViewTransient(func(ResourceScope) error) error - // ViewService retrieves a service-specific scope + + // ViewService retrieves a service-specific scope. ViewService(string, func(ServiceScope) error) error + // ViewProtocol views the resource management scope for a specific protocol. ViewProtocol(protocol.ID, func(ProtocolScope) error) error + // ViewPeer views the resource management scope for a specific peer. ViewPeer(peer.ID, func(PeerScope) error) error // OpenConnection creates a new connection scope not yet associated with any peer; the connection // is scoped at the transient scope. + // The caller owns the returned scope and is responsible for calling Done in order to signify + // the end of th scope's span. OpenConnection(dir Direction, usefd bool) (ConnManagementScope, error) // OpenStream creates a new stream scope, initially unnegotiated. // An unnegotiated stream will be initially unattached to any protocol scope // and constrained by the transient scope. + // The caller owns the returned scope and is responsible for calling Done in order to signify + // the end of th scope's span. OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) // Close closes the resource manager @@ -46,6 +130,16 @@ type ResourceScope interface { } // TransactionalScope is a ResourceScope with transactional semantics. +// Transactional scopes are control flow delimited and release all their associated resources +// when the programmer calls Done. +// +// Example: +// txn, err := someScope.BeginTransaction() +// if err != nil { ... } +// defer txn.Done() +// +// if err := txn.ReserveMemory(...); err != nil { ... } +// // ... use memory type TransactionalScope interface { ResourceScope // Done ends the transaction scope and releases associated resources. @@ -76,7 +170,9 @@ type PeerScope interface { Peer() peer.ID } -// ConnManagementScope is the interface for connection resource scopes. +// ConnManagementScope is the low level interface for connection resource scopes. +// This interface is used by the low level components of the system who create and own +// the span of a connection scope. type ConnManagementScope interface { TransactionalScope @@ -94,6 +190,8 @@ type ConnScope interface { } // StreamManagementScope is the interface for stream resource scopes. +// This interface is used by the low level components of the system who create and own +// the span of a stream scope. type StreamManagementScope interface { TransactionalScope @@ -105,18 +203,18 @@ type StreamManagementScope interface { // ServiceScope returns the service owning the stream, if any. ServiceScope() ServiceScope - // SetService sets the service owning this stream + // SetService sets the service owning this stream. SetService(srv string) error // PeerScope returns the peer resource scope associated with this stream. PeerScope() PeerScope } -// UserStreamScope is the user view of a StreamScope +// StreamScope is the user view of a StreamScope. type StreamScope interface { ResourceScope - // SetService sets the service owning this stream + // SetService sets the service owning this stream. SetService(srv string) error } From 541324dbf926294a069dd93cc03524b341c3f6f7 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 5 Jan 2022 09:32:59 +0200 Subject: [PATCH 38/55] introduce MemoryStatus indicator in ReserveMemory --- network/rcmgr.go | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index aa7dcbc..e9b8a4e 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -115,10 +115,35 @@ type ResourceManager interface { Close() error } +// MemoryStatus is an indicator of the current level of available memory for scope reservations. +type MemoryStatus int + +const ( + // MemoryStatusOK indicates that the scope has sufficient memory. + MemoryStatusOK = iota + // MemoryStatusCaution indicates that the scope is using more than half its available memory. + MemoryStatusCaution + // MemoryStatusCritical indicates that the scope is using more than 80% of its available memory. + MemoryStatusCritical +) + // ResourceScope is the interface for all scopes. type ResourceScope interface { // ReserveMemory reserves memory/buffer space in the scope. - ReserveMemory(size int) error + // + // If ReserveMemory returns an error, then no memory was reserved and the caller should handle + // the failure condition. + // + // If the error is nil, then the returned MemoryStatus indicates the health of the memory + // subsystem for the scope, _after_ the reservation. + // A MemoryStatus of MemoryStatusCritical (Red) indicates that the scope already uses + // too much memory and it should only proceed with absolutely critical memory allocations. + // A MemoryStatus of MemorStatusCaution (Yellow) indicates that the scope uses a lot + // of memory and the caller should backoff if it is an optional operation (e.g. a window + // buffer increase in a muxer). + // A MemoryStatus of MemoryStatusOK (Green) indicates that the scope has sufficient memory + // available and the caller is free to proceed without concerns. + ReserveMemory(size int) (MemoryStatus, error) // ReleaseMemory explicitly releases memory previously reserved with ReserveMemory ReleaseMemory(size int) @@ -272,7 +297,7 @@ func (n *nullResourceManager) Close() error { return nil } -func (n *nullScope) ReserveMemory(size int) error { return nil } +func (n *nullScope) ReserveMemory(size int) (MemoryStatus, error) { return MemoryStatusOK, nil } func (n *nullScope) ReleaseMemory(size int) {} func (n *nullScope) Stat() ScopeStat { return ScopeStat{} } func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return nullScopeObj, nil } From cafe95a0e595e7263abdbad38e90f08616843cc2 Mon Sep 17 00:00:00 2001 From: vyzo Date: Wed, 5 Jan 2022 17:18:25 +0200 Subject: [PATCH 39/55] use uint8 for MemoryStatus Co-authored-by: Marten Seemann --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index e9b8a4e..89f779c 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -116,7 +116,7 @@ type ResourceManager interface { } // MemoryStatus is an indicator of the current level of available memory for scope reservations. -type MemoryStatus int +type MemoryStatus uint8 const ( // MemoryStatusOK indicates that the scope has sufficient memory. From 84d55d3cdb3fcb32725f08ce7a8d8dbe4377fb27 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 6 Jan 2022 09:59:28 +0200 Subject: [PATCH 40/55] rework reservation interface to pass priority instead of returning memory status so that we don't have to undo reservations if there is too much pressure. --- network/rcmgr.go | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 89f779c..1688fbe 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -115,16 +115,19 @@ type ResourceManager interface { Close() error } -// MemoryStatus is an indicator of the current level of available memory for scope reservations. -type MemoryStatus uint8 - const ( - // MemoryStatusOK indicates that the scope has sufficient memory. - MemoryStatusOK = iota - // MemoryStatusCaution indicates that the scope is using more than half its available memory. - MemoryStatusCaution - // MemoryStatusCritical indicates that the scope is using more than 80% of its available memory. - MemoryStatusCritical + // ReservationPriorityLow is a reservation priority that indicates a reservation if the scope + // memory utilization is at 40% or less. + ReservationPriorityLow uint8 = 101 + // Reservation PriorityMedium is a reservation priority that indicates a reservation if the scope + // memory utilization is at 60% or less. + ReservationPriorityMedium uint8 = 152 + // ReservationPriorityHigh is a reservation prioirity that indicates a reservation if the scope + // memory utilization is at 80% or less + ReservationPriorityHigh uint8 = 203 + // ReservationPriorityAlways is a reservation that indicates a reservation if there is enough + // memory. + ReservationPriorityAlways uint8 = 255 ) // ResourceScope is the interface for all scopes. @@ -134,16 +137,16 @@ type ResourceScope interface { // If ReserveMemory returns an error, then no memory was reserved and the caller should handle // the failure condition. // - // If the error is nil, then the returned MemoryStatus indicates the health of the memory - // subsystem for the scope, _after_ the reservation. - // A MemoryStatus of MemoryStatusCritical (Red) indicates that the scope already uses - // too much memory and it should only proceed with absolutely critical memory allocations. - // A MemoryStatus of MemorStatusCaution (Yellow) indicates that the scope uses a lot - // of memory and the caller should backoff if it is an optional operation (e.g. a window - // buffer increase in a muxer). - // A MemoryStatus of MemoryStatusOK (Green) indicates that the scope has sufficient memory - // available and the caller is free to proceed without concerns. - ReserveMemory(size int) (MemoryStatus, error) + // The priority argument indicates the priority of the memory reservation. A reservation + // will fail if the available memory is less than (1+prio)/256 of the scope limit, providing + // a mechanism to gracefully handle optional reservations that might overload the system. + // For instance, a muxer growing a window buffer will use a low priority and only grow the buffer + // if there is no memory pressure in the system. + // + // The are 4 predefined priority levels, Low, Medium, High and Always, + // capturing common patterns, but the user is free to use any granularity applicable to his case. + ReserveMemory(size int, prio uint8) error + // ReleaseMemory explicitly releases memory previously reserved with ReserveMemory ReleaseMemory(size int) @@ -297,7 +300,7 @@ func (n *nullResourceManager) Close() error { return nil } -func (n *nullScope) ReserveMemory(size int) (MemoryStatus, error) { return MemoryStatusOK, nil } +func (n *nullScope) ReserveMemory(size int, prio uint8) error { return nil } func (n *nullScope) ReleaseMemory(size int) {} func (n *nullScope) Stat() ScopeStat { return ScopeStat{} } func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return nullScopeObj, nil } From d9136f09019636c97071eeb00547b2227c3622db Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 6 Jan 2022 10:03:02 +0200 Subject: [PATCH 41/55] improve comment --- network/rcmgr.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 1688fbe..de4f384 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -123,10 +123,10 @@ const ( // memory utilization is at 60% or less. ReservationPriorityMedium uint8 = 152 // ReservationPriorityHigh is a reservation prioirity that indicates a reservation if the scope - // memory utilization is at 80% or less + // memory utilization is at 80% or less. ReservationPriorityHigh uint8 = 203 // ReservationPriorityAlways is a reservation that indicates a reservation if there is enough - // memory. + // memory, regardless of scope utilization. ReservationPriorityAlways uint8 = 255 ) From 2192774acd82b82df75083bfeb623aa4b21c2b83 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 6 Jan 2022 10:03:54 +0200 Subject: [PATCH 42/55] fix typo --- network/rcmgr.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index de4f384..419ed21 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -125,8 +125,8 @@ const ( // ReservationPriorityHigh is a reservation prioirity that indicates a reservation if the scope // memory utilization is at 80% or less. ReservationPriorityHigh uint8 = 203 - // ReservationPriorityAlways is a reservation that indicates a reservation if there is enough - // memory, regardless of scope utilization. + // ReservationPriorityAlways is a reservation priority that indicates a reservation if there is + // enough memory, regardless of scope utilization. ReservationPriorityAlways uint8 = 255 ) From 005b84b557bb12a0a262fc34155142f930c27b45 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Fri, 7 Jan 2022 12:35:45 +0400 Subject: [PATCH 43/55] export the NullScope --- network/rcmgr.go | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 419ed21..b7dcc02 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -273,28 +273,29 @@ var _ ConnScope = (*nullScope)(nil) var _ StreamManagementScope = (*nullScope)(nil) var _ StreamScope = (*nullScope)(nil) -var nullScopeObj = &nullScope{} +// NullScope is a stub for tests and initialization of default values +var NullScope = &nullScope{} func (n *nullResourceManager) ViewSystem(f func(ResourceScope) error) error { - return f(nullScopeObj) + return f(NullScope) } func (n *nullResourceManager) ViewTransient(f func(ResourceScope) error) error { - return f(nullScopeObj) + return f(NullScope) } func (n *nullResourceManager) ViewService(svc string, f func(ServiceScope) error) error { - return f(nullScopeObj) + return f(NullScope) } func (n *nullResourceManager) ViewProtocol(p protocol.ID, f func(ProtocolScope) error) error { - return f(nullScopeObj) + return f(NullScope) } func (n *nullResourceManager) ViewPeer(p peer.ID, f func(PeerScope) error) error { - return f(nullScopeObj) + return f(NullScope) } func (n *nullResourceManager) OpenConnection(dir Direction, usefd bool) (ConnManagementScope, error) { - return nullScopeObj, nil + return NullScope, nil } func (n *nullResourceManager) OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) { - return nullScopeObj, nil + return NullScope, nil } func (n *nullResourceManager) Close() error { return nil @@ -303,14 +304,14 @@ func (n *nullResourceManager) Close() error { func (n *nullScope) ReserveMemory(size int, prio uint8) error { return nil } func (n *nullScope) ReleaseMemory(size int) {} func (n *nullScope) Stat() ScopeStat { return ScopeStat{} } -func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return nullScopeObj, nil } +func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return NullScope, nil } func (n *nullScope) Done() {} func (n *nullScope) Name() string { return "" } func (n *nullScope) Protocol() protocol.ID { return "" } func (n *nullScope) Peer() peer.ID { return "" } -func (n *nullScope) PeerScope() PeerScope { return nullScopeObj } +func (n *nullScope) PeerScope() PeerScope { return NullScope } func (n *nullScope) SetPeer(peer.ID) error { return nil } -func (n *nullScope) ProtocolScope() ProtocolScope { return nullScopeObj } +func (n *nullScope) ProtocolScope() ProtocolScope { return NullScope } func (n *nullScope) SetProtocol(proto protocol.ID) error { return nil } -func (n *nullScope) ServiceScope() ServiceScope { return nullScopeObj } +func (n *nullScope) ServiceScope() ServiceScope { return NullScope } func (n *nullScope) SetService(srv string) error { return nil } From 9d473a86d8272796a6d37cb10260b20f93a5ca15 Mon Sep 17 00:00:00 2001 From: vyzo Date: Sun, 9 Jan 2022 15:12:16 +0200 Subject: [PATCH 44/55] Stream.SetProtocol can return an error It needs to attach the protocol to the protocol scope, which may fail. --- network/stream.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/stream.go b/network/stream.go index 3e32010..d1e2785 100644 --- a/network/stream.go +++ b/network/stream.go @@ -18,7 +18,7 @@ type Stream interface { ID() string Protocol() protocol.ID - SetProtocol(id protocol.ID) + SetProtocol(id protocol.ID) error // Stat returns metadata pertaining to this stream. Stat() Stats From 0c1046ca054a5faa17319ac11e41376721c468e1 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 13 Jan 2022 15:12:10 +0400 Subject: [PATCH 45/55] merge the mux package into network --- mux/mux.go | 100 +++++----------------------------------------- network/mux.go | 95 +++++++++++++++++++++++++++++++++++++++++++ network/stream.go | 3 +- 3 files changed, 105 insertions(+), 93 deletions(-) create mode 100644 network/mux.go diff --git a/mux/mux.go b/mux/mux.go index 09dc31a..32303c8 100644 --- a/mux/mux.go +++ b/mux/mux.go @@ -5,99 +5,17 @@ package mux import ( - "context" - "errors" - "io" - "net" - "time" + "github.com/libp2p/go-libp2p-core/network" ) -// ErrReset is returned when reading or writing on a reset stream. -var ErrReset = errors.New("stream reset") +// Deprecated: use network.ErrReset instead. +var ErrReset = network.ErrReset -// Stream is a bidirectional io pipe within a connection. -type MuxedStream interface { - io.Reader - io.Writer +// Deprecated: use network.MuxedStream instead. +type MuxedStream = network.MuxedStream - // Close closes the stream. - // - // * Any buffered data for writing will be flushed. - // * Future reads will fail. - // * Any in-progress reads/writes will be interrupted. - // - // Close may be asynchronous and _does not_ guarantee receipt of the - // data. - // - // Close closes the stream for both reading and writing. - // Close is equivalent to calling `CloseRead` and `CloseWrite`. Importantly, Close will not wait for any form of acknowledgment. - // If acknowledgment is required, the caller must call `CloseWrite`, then wait on the stream for a response (or an EOF), - // then call Close() to free the stream object. - // - // When done with a stream, the user must call either Close() or `Reset()` to discard the stream, even after calling `CloseRead` and/or `CloseWrite`. - io.Closer +// Deprecated: use network.MuxedConn instead. +type MuxedConn = network.MuxedConn - // CloseWrite closes the stream for writing but leaves it open for - // reading. - // - // CloseWrite does not free the stream, users must still call Close or - // Reset. - CloseWrite() error - - // CloseRead closes the stream for reading but leaves it open for - // writing. - // - // When CloseRead is called, all in-progress Read calls are interrupted with a non-EOF error and - // no further calls to Read will succeed. - // - // The handling of new incoming data on the stream after calling this function is implementation defined. - // - // CloseRead does not free the stream, users must still call Close or - // Reset. - CloseRead() error - - // Reset closes both ends of the stream. Use this to tell the remote - // side to hang up and go away. - Reset() error - - SetDeadline(time.Time) error - SetReadDeadline(time.Time) error - SetWriteDeadline(time.Time) error -} - -// NoopHandler do nothing. Resets streams as soon as they are opened. -var NoopHandler = func(s MuxedStream) { s.Reset() } - -// MuxedConn represents a connection to a remote peer that has been -// extended to support stream multiplexing. -// -// A MuxedConn allows a single net.Conn connection to carry many logically -// independent bidirectional streams of binary data. -// -// Together with network.ConnSecurity, MuxedConn is a component of the -// transport.CapableConn interface, which represents a "raw" network -// connection that has been "upgraded" to support the libp2p capabilities -// of secure communication and stream multiplexing. -type MuxedConn interface { - // Close closes the stream muxer and the the underlying net.Conn. - io.Closer - - // IsClosed returns whether a connection is fully closed, so it can - // be garbage collected. - IsClosed() bool - - // OpenStream creates a new stream. - OpenStream(context.Context) (MuxedStream, error) - - // AcceptStream accepts a stream opened by the other side. - AcceptStream() (MuxedStream, error) -} - -// Multiplexer wraps a net.Conn with a stream multiplexing -// implementation and returns a MuxedConn that supports opening -// multiple streams over the underlying net.Conn -type Multiplexer interface { - - // NewConn constructs a new connection - NewConn(c net.Conn, isServer bool) (MuxedConn, error) -} +// Deprecated: use network.Multiplexer instead. +type Multiplexer = network.Multiplexer diff --git a/network/mux.go b/network/mux.go new file mode 100644 index 0000000..fe886bd --- /dev/null +++ b/network/mux.go @@ -0,0 +1,95 @@ +package network + +import ( + "context" + "errors" + "io" + "net" + "time" +) + +// ErrReset is returned when reading or writing on a reset stream. +var ErrReset = errors.New("stream reset") + +// MuxedStream is a bidirectional io pipe within a connection. +type MuxedStream interface { + io.Reader + io.Writer + + // Close closes the stream. + // + // * Any buffered data for writing will be flushed. + // * Future reads will fail. + // * Any in-progress reads/writes will be interrupted. + // + // Close may be asynchronous and _does not_ guarantee receipt of the + // data. + // + // Close closes the stream for both reading and writing. + // Close is equivalent to calling `CloseRead` and `CloseWrite`. Importantly, Close will not wait for any form of acknowledgment. + // If acknowledgment is required, the caller must call `CloseWrite`, then wait on the stream for a response (or an EOF), + // then call Close() to free the stream object. + // + // When done with a stream, the user must call either Close() or `Reset()` to discard the stream, even after calling `CloseRead` and/or `CloseWrite`. + io.Closer + + // CloseWrite closes the stream for writing but leaves it open for + // reading. + // + // CloseWrite does not free the stream, users must still call Close or + // Reset. + CloseWrite() error + + // CloseRead closes the stream for reading but leaves it open for + // writing. + // + // When CloseRead is called, all in-progress Read calls are interrupted with a non-EOF error and + // no further calls to Read will succeed. + // + // The handling of new incoming data on the stream after calling this function is implementation defined. + // + // CloseRead does not free the stream, users must still call Close or + // Reset. + CloseRead() error + + // Reset closes both ends of the stream. Use this to tell the remote + // side to hang up and go away. + Reset() error + + SetDeadline(time.Time) error + SetReadDeadline(time.Time) error + SetWriteDeadline(time.Time) error +} + +// MuxedConn represents a connection to a remote peer that has been +// extended to support stream multiplexing. +// +// A MuxedConn allows a single net.Conn connection to carry many logically +// independent bidirectional streams of binary data. +// +// Together with network.ConnSecurity, MuxedConn is a component of the +// transport.CapableConn interface, which represents a "raw" network +// connection that has been "upgraded" to support the libp2p capabilities +// of secure communication and stream multiplexing. +type MuxedConn interface { + // Close closes the stream muxer and the the underlying net.Conn. + io.Closer + + // IsClosed returns whether a connection is fully closed, so it can + // be garbage collected. + IsClosed() bool + + // OpenStream creates a new stream. + OpenStream(context.Context) (MuxedStream, error) + + // AcceptStream accepts a stream opened by the other side. + AcceptStream() (MuxedStream, error) +} + +// Multiplexer wraps a net.Conn with a stream multiplexing +// implementation and returns a MuxedConn that supports opening +// multiple streams over the underlying net.Conn +type Multiplexer interface { + // NewConn constructs a new connection + NewConn(c net.Conn, isServer bool) (MuxedConn, error) +} diff --git a/network/stream.go b/network/stream.go index d1e2785..d1f928b 100644 --- a/network/stream.go +++ b/network/stream.go @@ -1,7 +1,6 @@ package network import ( - "github.com/libp2p/go-libp2p-core/mux" "github.com/libp2p/go-libp2p-core/protocol" ) @@ -11,7 +10,7 @@ import ( // // Streams are backed by a multiplexer underneath the hood. type Stream interface { - mux.MuxedStream + MuxedStream // ID returns an identifier that uniquely identifies this Stream within this // host, during this run. Stream IDs may repeat across restarts. From 0391e674afe4c1e2cb357af07df2eb51c85005ae Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 13 Jan 2022 15:15:01 +0400 Subject: [PATCH 46/55] pass the PeerScope to Multiplexer.NetConn --- network/mux.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/mux.go b/network/mux.go index fe886bd..d12e2ea 100644 --- a/network/mux.go +++ b/network/mux.go @@ -91,5 +91,5 @@ type MuxedConn interface { // multiple streams over the underlying net.Conn type Multiplexer interface { // NewConn constructs a new connection - NewConn(c net.Conn, isServer bool) (MuxedConn, error) + NewConn(c net.Conn, isServer bool, scope PeerScope) (MuxedConn, error) } From d3d9ac741b60271c2375862c443d69d0d71a0688 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 13 Jan 2022 14:58:02 +0200 Subject: [PATCH 47/55] Update network/rcmgr.go Co-authored-by: raulk --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index b7dcc02..0de6955 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -52,7 +52,7 @@ import ( // resource manager interface. // // Application programmers can also directly reserve memory in some applicable scope. In order -// to failicate control flow delimited resource accounting, all scopes defined in the system +// to facilitate control flow delimited resource accounting, all scopes defined in the system // allow for the user to create transactions. Transactions are temporary scopes rooted at some // other scope and release their resources when the programmer is done with them. Transaction // scopes can form trees, with nested transactions. From 140d0edc736a76cbff9fed8579f2f4f8e9b4771d Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 13 Jan 2022 14:58:10 +0200 Subject: [PATCH 48/55] Update network/rcmgr.go Co-authored-by: raulk --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 0de6955..381ed42 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -59,7 +59,7 @@ import ( // // Typical Usage: // - Low level components of the system (transports, muxers) all have access to the resource -// manageer and create connection and stream scopes through it. These scopes are accessible +// manager and create connection and stream scopes through it. These scopes are accessible // to the user, albeit with a narrower interface, through Conn and Stream objects who have // a Scope method. // - Services typically center around streams, where the programmer can attach streams to a From 7a1c47e065369aa5030197952a7d2ee10100669c Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 13 Jan 2022 14:58:34 +0200 Subject: [PATCH 49/55] Update network/rcmgr.go Co-authored-by: raulk --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 381ed42..f116ea4 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -35,7 +35,7 @@ import ( // appropriate scope. The resource manager gates the reservation against the scope applicable // limits; if the limit is exceeded, then an error (wrapping ErrResourceLimitExceeded) and it // is up the component to act accordingly. At the lower levels of the stack, this will normally -// signal a filure of some sorts, like failing to opening a stream or a connection, which will +// signal a failure of some sorts, like failing to opening a stream or a connection, which will // propagate to the programmer. Some components may be able to handle resource reservation failure // more gracefully; for instance a muxer trying to grow a buffer for a window change, will simply // retain the existing window size and continue to operate normally albeit with some degraded From e2bac5c0a10814429631b18f1eefab845b7f53d0 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 14 Jan 2022 11:57:43 +0200 Subject: [PATCH 50/55] Update network/rcmgr.go Co-authored-by: Adin Schmahmann --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index f116ea4..7618697 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -101,7 +101,7 @@ type ResourceManager interface { // OpenConnection creates a new connection scope not yet associated with any peer; the connection // is scoped at the transient scope. // The caller owns the returned scope and is responsible for calling Done in order to signify - // the end of th scope's span. + // the end of the scope's span. OpenConnection(dir Direction, usefd bool) (ConnManagementScope, error) // OpenStream creates a new stream scope, initially unnegotiated. From 4bfde8e8c600472b6332bac51aacb5779fc566ae Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 14 Jan 2022 12:00:59 +0200 Subject: [PATCH 51/55] remove reference to deprecated mux.MuxedConn --- transport/transport.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/transport/transport.go b/transport/transport.go index dcdf741..91cb75a 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -6,7 +6,6 @@ import ( "context" "net" - "github.com/libp2p/go-libp2p-core/mux" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" @@ -26,7 +25,7 @@ import ( // CapableConn provides accessors for the local and remote multiaddrs used to // establish the connection and an accessor for the underlying Transport. type CapableConn interface { - mux.MuxedConn + network.MuxedConn network.ConnSecurity network.ConnMultiaddrs network.ConnScoper From 68e492f2089ec3971e1a8efc036c391be31c1a05 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 14 Jan 2022 12:05:06 +0200 Subject: [PATCH 52/55] rename transaction to span --- network/rcmgr.go | 60 ++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 7618697..3a7d871 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -53,9 +53,9 @@ import ( // // Application programmers can also directly reserve memory in some applicable scope. In order // to facilitate control flow delimited resource accounting, all scopes defined in the system -// allow for the user to create transactions. Transactions are temporary scopes rooted at some -// other scope and release their resources when the programmer is done with them. Transaction -// scopes can form trees, with nested transactions. +// allow for the user to create spans. Spans are temporary scopes rooted at some +// other scope and release their resources when the programmer is done with them. Span +// scopes can form trees, with nested spans. // // Typical Usage: // - Low level components of the system (transports, muxers) all have access to the resource @@ -66,7 +66,7 @@ import ( // particular service. They can also directly reserve memory for a service by accessing the // service scope using the ResourceManager interface. // - Applications that want to account for their network resource usage can reserve memory, -// typically using a transaction, directly in the System or a Service scope; they can also +// typically using a span, directly in the System or a Service scope; they can also // opt to use appropriate steam scopes for streams that they create or own. // // User Serviceable Parts: the user has the option to specify their own implementation of the @@ -153,24 +153,24 @@ type ResourceScope interface { // Stat retrieves current resource usage for the scope. Stat() ScopeStat - // BeginTransaction creates a new transactional scope rooted at this scope - BeginTransaction() (TransactionalScope, error) + // BeginSpan creates a new span scope rooted at this scope + BeginSpan() (ResourceScopeSpan, error) } -// TransactionalScope is a ResourceScope with transactional semantics. -// Transactional scopes are control flow delimited and release all their associated resources +// ResourceScopeSpan is a ResourceScope with a delimited span. +// Span scopes are control flow delimited and release all their associated resources // when the programmer calls Done. // // Example: -// txn, err := someScope.BeginTransaction() +// s, err := someScope.BeginSpan() // if err != nil { ... } -// defer txn.Done() +// defer s.Done() // -// if err := txn.ReserveMemory(...); err != nil { ... } +// if err := s.ReserveMemory(...); err != nil { ... } // // ... use memory -type TransactionalScope interface { +type ResourceScopeSpan interface { ResourceScope - // Done ends the transaction scope and releases associated resources. + // Done ends the span and releases associated resources. Done() } @@ -202,7 +202,7 @@ type PeerScope interface { // This interface is used by the low level components of the system who create and own // the span of a connection scope. type ConnManagementScope interface { - TransactionalScope + ResourceScopeSpan // PeerScope returns the peer scope associated with this connection. // It returns nil if the connection is not yet asociated with any peer. @@ -221,7 +221,7 @@ type ConnScope interface { // This interface is used by the low level components of the system who create and own // the span of a stream scope. type StreamManagementScope interface { - TransactionalScope + ResourceScopeSpan // ProtocolScope returns the protocol resource scope associated with this stream. // It returns nil if the stream is not associated with any protocol scope. @@ -264,7 +264,7 @@ type nullResourceManager struct{} type nullScope struct{} var _ ResourceScope = (*nullScope)(nil) -var _ TransactionalScope = (*nullScope)(nil) +var _ ResourceScopeSpan = (*nullScope)(nil) var _ ServiceScope = (*nullScope)(nil) var _ ProtocolScope = (*nullScope)(nil) var _ PeerScope = (*nullScope)(nil) @@ -301,17 +301,17 @@ func (n *nullResourceManager) Close() error { return nil } -func (n *nullScope) ReserveMemory(size int, prio uint8) error { return nil } -func (n *nullScope) ReleaseMemory(size int) {} -func (n *nullScope) Stat() ScopeStat { return ScopeStat{} } -func (n *nullScope) BeginTransaction() (TransactionalScope, error) { return NullScope, nil } -func (n *nullScope) Done() {} -func (n *nullScope) Name() string { return "" } -func (n *nullScope) Protocol() protocol.ID { return "" } -func (n *nullScope) Peer() peer.ID { return "" } -func (n *nullScope) PeerScope() PeerScope { return NullScope } -func (n *nullScope) SetPeer(peer.ID) error { return nil } -func (n *nullScope) ProtocolScope() ProtocolScope { return NullScope } -func (n *nullScope) SetProtocol(proto protocol.ID) error { return nil } -func (n *nullScope) ServiceScope() ServiceScope { return NullScope } -func (n *nullScope) SetService(srv string) error { return nil } +func (n *nullScope) ReserveMemory(size int, prio uint8) error { return nil } +func (n *nullScope) ReleaseMemory(size int) {} +func (n *nullScope) Stat() ScopeStat { return ScopeStat{} } +func (n *nullScope) BeginSpan() (ResourceScopeSpan, error) { return NullScope, nil } +func (n *nullScope) Done() {} +func (n *nullScope) Name() string { return "" } +func (n *nullScope) Protocol() protocol.ID { return "" } +func (n *nullScope) Peer() peer.ID { return "" } +func (n *nullScope) PeerScope() PeerScope { return NullScope } +func (n *nullScope) SetPeer(peer.ID) error { return nil } +func (n *nullScope) ProtocolScope() ProtocolScope { return NullScope } +func (n *nullScope) SetProtocol(proto protocol.ID) error { return nil } +func (n *nullScope) ServiceScope() ServiceScope { return NullScope } +func (n *nullScope) SetService(srv string) error { return nil } From 953320f41d8a0e00e07ed76d6562cefcff744243 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 14 Jan 2022 12:06:29 +0200 Subject: [PATCH 53/55] indicate bytes in ReserveMemory --- network/rcmgr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 3a7d871..711f7c6 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -132,7 +132,7 @@ const ( // ResourceScope is the interface for all scopes. type ResourceScope interface { - // ReserveMemory reserves memory/buffer space in the scope. + // ReserveMemory reserves memory/buffer space in the scope; the unit is bytes. // // If ReserveMemory returns an error, then no memory was reserved and the caller should handle // the failure condition. From 06aa6f9fc37aadbd37d56de52638a2798ef1a2ec Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 14 Jan 2022 12:13:49 +0200 Subject: [PATCH 54/55] break ResourceManager View methods into Viewer interface. --- network/rcmgr.go | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/network/rcmgr.go b/network/rcmgr.go index 711f7c6..0f6fe66 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -74,6 +74,28 @@ import ( // The user of that package can specify limits for the various scopes, which can be static // or dynamic. type ResourceManager interface { + ResourceScopeViewer + + // OpenConnection creates a new connection scope not yet associated with any peer; the connection + // is scoped at the transient scope. + // The caller owns the returned scope and is responsible for calling Done in order to signify + // the end of the scope's span. + OpenConnection(dir Direction, usefd bool) (ConnManagementScope, error) + + // OpenStream creates a new stream scope, initially unnegotiated. + // An unnegotiated stream will be initially unattached to any protocol scope + // and constrained by the transient scope. + // The caller owns the returned scope and is responsible for calling Done in order to signify + // the end of th scope's span. + OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) + + // Close closes the resource manager + Close() error +} + +// ResourceScopeViewer is a mixin interface providing view methods for accessing top level +// scopes. +type ResourceScopeViewer interface { // ViewSystem views the system wide resource scope. // The system scope is the top level scope that accounts for global // resource usage at all levels of the system. This scope constrains all @@ -97,22 +119,6 @@ type ResourceManager interface { // ViewPeer views the resource management scope for a specific peer. ViewPeer(peer.ID, func(PeerScope) error) error - - // OpenConnection creates a new connection scope not yet associated with any peer; the connection - // is scoped at the transient scope. - // The caller owns the returned scope and is responsible for calling Done in order to signify - // the end of the scope's span. - OpenConnection(dir Direction, usefd bool) (ConnManagementScope, error) - - // OpenStream creates a new stream scope, initially unnegotiated. - // An unnegotiated stream will be initially unattached to any protocol scope - // and constrained by the transient scope. - // The caller owns the returned scope and is responsible for calling Done in order to signify - // the end of th scope's span. - OpenStream(p peer.ID, dir Direction) (StreamManagementScope, error) - - // Close closes the resource manager - Close() error } const ( From 6b8d8bf59647727dbff71161a5d915227d77e9ab Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 14 Jan 2022 12:16:23 +0200 Subject: [PATCH 55/55] add experimental interface warning --- network/rcmgr.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/network/rcmgr.go b/network/rcmgr.go index 0f6fe66..630bc01 100644 --- a/network/rcmgr.go +++ b/network/rcmgr.go @@ -73,6 +73,9 @@ import ( // interface. We provide a canonical implementation in the go-libp2p-resource-manager package. // The user of that package can specify limits for the various scopes, which can be static // or dynamic. +// +// WARNING The ResourceManager interface is considered experimental and subject to change +// in subsequent releases. type ResourceManager interface { ResourceScopeViewer