Skip to content

Commit

Permalink
database/sql: add DB.SetMaxIdleConns
Browse files Browse the repository at this point in the history
Update #4805

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/7634045
  • Loading branch information
bradfitz committed Mar 18, 2013
1 parent f005edd commit 3a2fe62
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
47 changes: 41 additions & 6 deletions src/pkg/database/sql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ type DB struct {
dep map[finalCloser]depSet
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
maxIdle int // zero means defaultMaxIdleConns; negative means 0
}

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

func (db *DB) maxIdleConns() int {
const defaultMaxIdleConns = 2
// TODO(bradfitz): ask driver, if supported, for its default preference
// TODO(bradfitz): let users override?
return defaultMaxIdleConns
const defaultMaxIdleConns = 2

func (db *DB) maxIdleConnsLocked() int {
n := db.maxIdle
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
Expand Down Expand Up @@ -441,7 +476,7 @@ func (db *DB) putConn(dc *driverConn, err error) {
if putConnHook != nil {
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.mu.Unlock()
return
Expand Down
29 changes: 29 additions & 0 deletions src/pkg/database/sql/sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -761,3 +761,32 @@ func TestSimultaneousQueries(t *testing.T) {
}
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)
}
}

0 comments on commit 3a2fe62

Please sign in to comment.