From a2976247d17a12e897ab8cc1ccb011ba528e6499 Mon Sep 17 00:00:00 2001 From: zhenghuabin Date: Wed, 25 Mar 2015 20:09:54 +0800 Subject: [PATCH 1/4] add MarkUnreusable to pooled connection to make it possible to discard unreusable connections --- channel_test.go | 29 ++++++++++++++++++++++++++++- conn.go | 22 +++++++++++++++++----- conn_test.go | 2 +- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/channel_test.go b/channel_test.go index 642a456..2be79cc 100644 --- a/channel_test.go +++ b/channel_test.go @@ -40,7 +40,7 @@ func TestPool_Get_Impl(t *testing.T) { t.Errorf("Get error: %s", err) } - _, ok := conn.(poolConn) + _, ok := conn.(*PoolConn) if !ok { t.Errorf("Conn is not of type poolConn") } @@ -119,6 +119,33 @@ func TestPool_Put(t *testing.T) { } } +func TestPool_PutUnreusableConn(t *testing.T) { + p, _ := newChannelPool() + defer p.Close() + + // ensure pool is not empty + conn, _ := p.Get() + conn.Close() + + poolSize := p.Len() + conn, _ = p.Get() + conn.Close() + if p.Len() != poolSize { + t.Errorf("Pool size is expected to be equal to initial size") + } + + conn, _ = p.Get() + if pc, ok := conn.(*PoolConn); !ok { + t.Errorf("impossible") + } else { + pc.MarkUnreusable() + } + conn.Close() + if p.Len() != poolSize-1 { + t.Errorf("Pool size is expected to be initial_size - 1", p.Len(), poolSize-1) + } +} + func TestPool_UsedCapacity(t *testing.T) { p, _ := newChannelPool() defer p.Close() diff --git a/conn.go b/conn.go index b87ac71..9b2a9c0 100644 --- a/conn.go +++ b/conn.go @@ -2,21 +2,33 @@ package pool import "net" -// poolConn is a wrapper around net.Conn to modify the the behavior of +// PoolConn is a wrapper around net.Conn to modify the the behavior of // net.Conn's Close() method. -type poolConn struct { +type PoolConn struct { net.Conn - c *channelPool + c *channelPool + unreusable bool } // Close() puts the given connects back to the pool instead of closing it. -func (p poolConn) Close() error { +func (p PoolConn) Close() error { + if p.unreusable { + if p.Conn != nil { + p.Conn.Close() + } + return nil + } return p.c.put(p.Conn) } +// MarkUnreusable() marks the connection is not reusable. +func (p *PoolConn) MarkUnreusable() { + p.unreusable = true +} + // newConn wraps a standard net.Conn to a poolConn net.Conn. func (c *channelPool) wrapConn(conn net.Conn) net.Conn { - p := poolConn{c: c} + p := &PoolConn{c: c} p.Conn = conn return p } diff --git a/conn_test.go b/conn_test.go index 6d287c6..55f9237 100644 --- a/conn_test.go +++ b/conn_test.go @@ -6,5 +6,5 @@ import ( ) func TestConn_Impl(t *testing.T) { - var _ net.Conn = new(poolConn) + var _ net.Conn = new(PoolConn) } From 6bf1d0ecafa51cc7b3fe6078a5c05e683b8759f4 Mon Sep 17 00:00:00 2001 From: zhenghuabin Date: Wed, 25 Mar 2015 21:17:09 +0800 Subject: [PATCH 2/4] rename MarkUnreusable to MarkUnusable --- channel_test.go | 4 ++-- conn.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/channel_test.go b/channel_test.go index 2be79cc..7d5522f 100644 --- a/channel_test.go +++ b/channel_test.go @@ -119,7 +119,7 @@ func TestPool_Put(t *testing.T) { } } -func TestPool_PutUnreusableConn(t *testing.T) { +func TestPool_PutUnusableConn(t *testing.T) { p, _ := newChannelPool() defer p.Close() @@ -138,7 +138,7 @@ func TestPool_PutUnreusableConn(t *testing.T) { if pc, ok := conn.(*PoolConn); !ok { t.Errorf("impossible") } else { - pc.MarkUnreusable() + pc.MarkUnusable() } conn.Close() if p.Len() != poolSize-1 { diff --git a/conn.go b/conn.go index 9b2a9c0..286304a 100644 --- a/conn.go +++ b/conn.go @@ -7,12 +7,12 @@ import "net" type PoolConn struct { net.Conn c *channelPool - unreusable bool + unusable bool } // Close() puts the given connects back to the pool instead of closing it. func (p PoolConn) Close() error { - if p.unreusable { + if p.unusable { if p.Conn != nil { p.Conn.Close() } @@ -22,8 +22,8 @@ func (p PoolConn) Close() error { } // MarkUnreusable() marks the connection is not reusable. -func (p *PoolConn) MarkUnreusable() { - p.unreusable = true +func (p *PoolConn) MarkUnusable() { + p.unusable = true } // newConn wraps a standard net.Conn to a poolConn net.Conn. From e4dcc218766fb6acd8a1a0c9914d7a0e23424247 Mon Sep 17 00:00:00 2001 From: collinmsn <4130944@qq.com> Date: Wed, 25 Mar 2015 21:36:35 +0800 Subject: [PATCH 3/4] Update conn.go --- conn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conn.go b/conn.go index 286304a..b3fbb3f 100644 --- a/conn.go +++ b/conn.go @@ -14,7 +14,7 @@ type PoolConn struct { func (p PoolConn) Close() error { if p.unusable { if p.Conn != nil { - p.Conn.Close() + return p.Conn.Close() } return nil } From f67a7ba05b4ba694f8a07799053b7104a473885a Mon Sep 17 00:00:00 2001 From: collinmsn <4130944@qq.com> Date: Wed, 25 Mar 2015 21:44:10 +0800 Subject: [PATCH 4/4] Update conn.go update comment --- conn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conn.go b/conn.go index b3fbb3f..bc2d705 100644 --- a/conn.go +++ b/conn.go @@ -21,7 +21,7 @@ func (p PoolConn) Close() error { return p.c.put(p.Conn) } -// MarkUnreusable() marks the connection is not reusable. +// MarkUnusable() marks the connection not usable any more, to let the pool close it instead of returning it to pool. func (p *PoolConn) MarkUnusable() { p.unusable = true }