github.com/Cloud-Foundations/Dominator@v0.3.4/lib/connpool/api.go (about)

     1  /*
     2  	Package connpool provides for managing network connections with a resource
     3  	pool.
     4  
     5  	Package connpool may be used to create and free network connections.
     6  	The number of concurrent network connections that may be open is limited to
     7  	fit within the underlying file descriptor limit. Connections may be placed
     8  	on an internal freelist for later re-use, potentially eliminating connection
     9  	setup overhead for frequently re-opened connections.
    10  
    11  	An application will typically call New once for each network address it
    12  	expects to later connect to. When the application wants to connect it calls
    13  	the Get method and calls the Put method to release the connection.
    14  	A typical programming pattern is:
    15  		cr0 := New(...)
    16  		cr1 := New(...)
    17  		go func() {
    18  			for ... {
    19  				c := cr0.Get(...)
    20  				defer c.Put()
    21  				if err { c.Close() }
    22  			}
    23  		}()
    24  		go func() {
    25  			for ... {
    26  				c := cr1.Get(...)
    27  				defer c.Put()
    28  				if err { c.Close() }
    29  			}
    30  		}()
    31  	This pattern ensures Get and Put are always matched, and if there is a
    32  	communications error, Close shuts down the connection so that a subsequent
    33  	Get	creates a new underlying connection.
    34  
    35  	It is resonable to create one goroutine for each resource, since the Get
    36  	methods will block, waiting for available resources.
    37  */
    38  package connpool
    39  
    40  import (
    41  	"net"
    42  	"time"
    43  
    44  	"github.com/Cloud-Foundations/Dominator/lib/resourcepool"
    45  )
    46  
    47  // Dialer implements a dialer that can be use to create connections.
    48  type Dialer interface {
    49  	Dial(network, address string) (net.Conn, error)
    50  }
    51  
    52  // GetResourcePool returns a global resourcepool.Pool which may be used by other
    53  // packages which need to share a common resource pool with the connpool
    54  // package. This is needed for efficient sharing of the underlying file
    55  // descriptors (connection slots).
    56  func GetResourcePool() *resourcepool.Pool {
    57  	return getResourcePool()
    58  }
    59  
    60  type privateConnResource struct {
    61  	connResource *ConnResource
    62  	dialer       Dialer
    63  }
    64  
    65  // ConnResource manages a single Conn.
    66  type ConnResource struct {
    67  	network             string
    68  	address             string
    69  	resource            *resourcepool.Resource
    70  	privateConnResource privateConnResource
    71  	conn                *Conn
    72  	netConn             net.Conn
    73  }
    74  
    75  // New returns a ConnResource for the specified network address. It may be used
    76  // later to obtain a Conn network connection which is part of a managed pool of
    77  // connection slots (to limit consumption of resources such as file
    78  // descriptors). Connections can be released with the Put method but the
    79  // underlying connection may be kept open for later re-use. The Conn is placed
    80  // on an internal list.
    81  func New(network, address string) *ConnResource {
    82  	return newConnResource(network, address)
    83  }
    84  
    85  // Get will return a Conn network connection. It implements the net.Conn
    86  // interface from the standard library. Get will wait until a resource is
    87  // available or a message is received on cancelChannel. If cancelChannel is nil
    88  // then Get will wait indefinitely until a resource is available. If the wait is
    89  // cancelled then Get will return ErrorResourceLimitExceeded. The timeout
    90  // specifies how long to wait (after a resource is available) to make the
    91  // connection. If timeout is zero or less, the underlying OS timeout is used
    92  // (typically 3 minutes for TCP).
    93  // Get will panic if it is called again without an intervening Close or Put.
    94  func (cr *ConnResource) Get(cancelChannel <-chan struct{},
    95  	timeout time.Duration) (*Conn, error) {
    96  	return cr.get(cancelChannel, &net.Dialer{Timeout: timeout})
    97  }
    98  
    99  // GetWithDialer will return a Conn network connection which implements the
   100  // net.Conn interface from the standard library. GetWithDialer will wait until
   101  // a resource is available or a message is received on cancelChannel. If
   102  // cancelChannel is nil then GetWithDialer will wait indefinitely until a
   103  // resource is available. If the wait is cancelled then GetWithDialer will
   104  // return ErrorResourceLimitExceeded.
   105  // The dialer is used to perform the operation which creates the connection. A
   106  // *net.Dialer type from the standard library satisfies the Dialer interface,
   107  // and may be used to specify how long to wait (after a resource is available)
   108  // to make the connection. The OS may impose it's own timeout (typically 3
   109  // minutes for TCP). A different dialer may be used to create TLS connections.
   110  // Note that changing dialer types does not guarantee the connection type
   111  // returned, as the dialer may not be called on every call to GetWithDialer,
   112  // thus changing dialer types will result in unpredictable behaviour.
   113  // GetWithDialer will panic if it is called again without an intervening Close
   114  // or Put.
   115  func (cr *ConnResource) GetWithDialer(cancelChannel <-chan struct{},
   116  	dialer Dialer) (*Conn, error) {
   117  	return cr.get(cancelChannel, dialer)
   118  }
   119  
   120  // ScheduleClose will immediately Close the associated Conn if it is not in use
   121  // or will mark the Conn to be closed when it is next Put.
   122  func (cr *ConnResource) ScheduleClose() {
   123  	cr.resource.ScheduleRelease()
   124  }
   125  
   126  // Conn is a managed network connection. It implements the net.Conn interface
   127  // from the standard library.
   128  type Conn struct {
   129  	net.Conn
   130  	resource *ConnResource
   131  }
   132  
   133  // Close will close the connection, immediately freeing the underlying resource.
   134  // It may no longer be used for communication.
   135  func (conn *Conn) Close() error {
   136  	return conn.close()
   137  }
   138  
   139  // Put will release the connection. It may no longer be used for communication.
   140  // It may be internally closed later if required to free limited resources (such
   141  // as file descriptors). If Put is called after Close, no action is taken (this
   142  // is a safe operation and is commonly used in some programming patterns).
   143  func (conn *Conn) Put() {
   144  	conn.put()
   145  }