Commit 3a2fe62f authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

database/sql: add DB.SetMaxIdleConns

Update #4805

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/7634045
parent f005eddb
...@@ -197,6 +197,7 @@ type DB struct { ...@@ -197,6 +197,7 @@ type DB struct {
dep map[finalCloser]depSet dep map[finalCloser]depSet
onConnPut map[*driverConn][]func() // code (with mu held) run when conn is next returned onConnPut map[*driverConn][]func() // code (with mu held) run when conn is next returned
lastPut map[*driverConn]string // stacktrace of last conn's put; debug only lastPut map[*driverConn]string // stacktrace of last conn's put; debug only
maxIdle int // zero means defaultMaxIdleConns; negative means 0
} }
// driverConn wraps a driver.Conn with a mutex, to // driverConn wraps a driver.Conn with a mutex, to
...@@ -332,11 +333,45 @@ func (db *DB) Close() error { ...@@ -332,11 +333,45 @@ func (db *DB) Close() error {
return err return err
} }
func (db *DB) maxIdleConns() int { const defaultMaxIdleConns = 2
const defaultMaxIdleConns = 2
// TODO(bradfitz): ask driver, if supported, for its default preference func (db *DB) maxIdleConnsLocked() int {
// TODO(bradfitz): let users override? n := db.maxIdle
return defaultMaxIdleConns switch {
case n == 0:
// TODO(bradfitz): ask driver, if supported, for its default preference
return defaultMaxIdleConns
case n < 0:
return 0
default:
return n
}
}
// SetMaxIdleConns sets the maximum number of connections in the idle
// connection pool.
//
// If n <= 0, no idle connections are retained.
func (db *DB) SetMaxIdleConns(n int) {
db.mu.Lock()
defer db.mu.Unlock()
if n > 0 {
db.maxIdle = n
} else {
// No idle connections.
db.maxIdle = -1
}
for len(db.freeConn) > 0 && len(db.freeConn) > n {
nfree := len(db.freeConn)
dc := db.freeConn[nfree-1]
db.freeConn[nfree-1] = nil
db.freeConn = db.freeConn[:nfree-1]
go func() {
dc.Lock()
dc.ci.Close()
dc.Unlock()
}()
}
} }
// conn returns a newly-opened or cached *driverConn // conn returns a newly-opened or cached *driverConn
...@@ -441,7 +476,7 @@ func (db *DB) putConn(dc *driverConn, err error) { ...@@ -441,7 +476,7 @@ func (db *DB) putConn(dc *driverConn, err error) {
if putConnHook != nil { if putConnHook != nil {
putConnHook(db, dc) putConnHook(db, dc)
} }
if n := len(db.freeConn); !db.closed && n < db.maxIdleConns() { if n := len(db.freeConn); !db.closed && n < db.maxIdleConnsLocked() {
db.freeConn = append(db.freeConn, dc) db.freeConn = append(db.freeConn, dc)
db.mu.Unlock() db.mu.Unlock()
return return
......
...@@ -761,3 +761,32 @@ func TestSimultaneousQueries(t *testing.T) { ...@@ -761,3 +761,32 @@ func TestSimultaneousQueries(t *testing.T) {
} }
defer r2.Close() defer r2.Close()
} }
func TestMaxIdleConns(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
tx, err := db.Begin()
if err != nil {
t.Fatal(err)
}
tx.Commit()
if got := len(db.freeConn); got != 1 {
t.Errorf("freeConns = %d; want 1", got)
}
db.SetMaxIdleConns(0)
if got := len(db.freeConn); got != 0 {
t.Errorf("freeConns after set to zero = %d; want 0", got)
}
tx, err = db.Begin()
if err != nil {
t.Fatal(err)
}
tx.Commit()
if got := len(db.freeConn); got != 0 {
t.Errorf("freeConns = %d; want 0", got)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment