Skip to content

Commit 3a2fe62

Browse files
committed
database/sql: add DB.SetMaxIdleConns
Update #4805 R=golang-dev, r CC=golang-dev https://golang.org/cl/7634045
1 parent f005edd commit 3a2fe62

File tree

2 files changed

+70
-6
lines changed

2 files changed

+70
-6
lines changed

src/pkg/database/sql/sql.go

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ type DB struct {
197197
dep map[finalCloser]depSet
198198
onConnPut map[*driverConn][]func() // code (with mu held) run when conn is next returned
199199
lastPut map[*driverConn]string // stacktrace of last conn's put; debug only
200+
maxIdle int // zero means defaultMaxIdleConns; negative means 0
200201
}
201202

202203
// driverConn wraps a driver.Conn with a mutex, to
@@ -332,11 +333,45 @@ func (db *DB) Close() error {
332333
return err
333334
}
334335

335-
func (db *DB) maxIdleConns() int {
336-
const defaultMaxIdleConns = 2
337-
// TODO(bradfitz): ask driver, if supported, for its default preference
338-
// TODO(bradfitz): let users override?
339-
return defaultMaxIdleConns
336+
const defaultMaxIdleConns = 2
337+
338+
func (db *DB) maxIdleConnsLocked() int {
339+
n := db.maxIdle
340+
switch {
341+
case n == 0:
342+
// TODO(bradfitz): ask driver, if supported, for its default preference
343+
return defaultMaxIdleConns
344+
case n < 0:
345+
return 0
346+
default:
347+
return n
348+
}
349+
}
350+
351+
// SetMaxIdleConns sets the maximum number of connections in the idle
352+
// connection pool.
353+
//
354+
// If n <= 0, no idle connections are retained.
355+
func (db *DB) SetMaxIdleConns(n int) {
356+
db.mu.Lock()
357+
defer db.mu.Unlock()
358+
if n > 0 {
359+
db.maxIdle = n
360+
} else {
361+
// No idle connections.
362+
db.maxIdle = -1
363+
}
364+
for len(db.freeConn) > 0 && len(db.freeConn) > n {
365+
nfree := len(db.freeConn)
366+
dc := db.freeConn[nfree-1]
367+
db.freeConn[nfree-1] = nil
368+
db.freeConn = db.freeConn[:nfree-1]
369+
go func() {
370+
dc.Lock()
371+
dc.ci.Close()
372+
dc.Unlock()
373+
}()
374+
}
340375
}
341376

342377
// conn returns a newly-opened or cached *driverConn
@@ -441,7 +476,7 @@ func (db *DB) putConn(dc *driverConn, err error) {
441476
if putConnHook != nil {
442477
putConnHook(db, dc)
443478
}
444-
if n := len(db.freeConn); !db.closed && n < db.maxIdleConns() {
479+
if n := len(db.freeConn); !db.closed && n < db.maxIdleConnsLocked() {
445480
db.freeConn = append(db.freeConn, dc)
446481
db.mu.Unlock()
447482
return

src/pkg/database/sql/sql_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,3 +761,32 @@ func TestSimultaneousQueries(t *testing.T) {
761761
}
762762
defer r2.Close()
763763
}
764+
765+
func TestMaxIdleConns(t *testing.T) {
766+
db := newTestDB(t, "people")
767+
defer closeDB(t, db)
768+
769+
tx, err := db.Begin()
770+
if err != nil {
771+
t.Fatal(err)
772+
}
773+
tx.Commit()
774+
if got := len(db.freeConn); got != 1 {
775+
t.Errorf("freeConns = %d; want 1", got)
776+
}
777+
778+
db.SetMaxIdleConns(0)
779+
780+
if got := len(db.freeConn); got != 0 {
781+
t.Errorf("freeConns after set to zero = %d; want 0", got)
782+
}
783+
784+
tx, err = db.Begin()
785+
if err != nil {
786+
t.Fatal(err)
787+
}
788+
tx.Commit()
789+
if got := len(db.freeConn); got != 0 {
790+
t.Errorf("freeConns = %d; want 0", got)
791+
}
792+
}

0 commit comments

Comments
 (0)