Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(245)

Side by Side Diff: src/pkg/database/sql/sql.go

Issue 14642044: code review 14642044: database/sql: Fix connection leaks and numOpen count (Closed)
Patch Set: diff -r 9d0d95344a6c https://code.google.com/p/go Created 11 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/pkg/database/sql/sql_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Package sql provides a generic interface around SQL (or SQL-like) 5 // Package sql provides a generic interface around SQL (or SQL-like)
6 // databases. 6 // databases.
7 // 7 //
8 // The sql package must be used in conjunction with a database driver. 8 // The sql package must be used in conjunction with a database driver.
9 // See http://golang.org/s/sqldrivers for a list of drivers. 9 // See http://golang.org/s/sqldrivers for a list of drivers.
10 package sql 10 package sql
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 497
498 // SetMaxIdleConns sets the maximum number of connections in the idle 498 // SetMaxIdleConns sets the maximum number of connections in the idle
499 // connection pool. 499 // connection pool.
500 // 500 //
501 // If MaxOpenConns is greater than 0 but less than the new MaxIdleConns 501 // If MaxOpenConns is greater than 0 but less than the new MaxIdleConns
502 // then the new MaxIdleConns will be reduced to match the MaxOpenConns limit 502 // then the new MaxIdleConns will be reduced to match the MaxOpenConns limit
503 // 503 //
504 // If n <= 0, no idle connections are retained. 504 // If n <= 0, no idle connections are retained.
505 func (db *DB) SetMaxIdleConns(n int) { 505 func (db *DB) SetMaxIdleConns(n int) {
506 db.mu.Lock() 506 db.mu.Lock()
507 defer db.mu.Unlock()
508 if n > 0 { 507 if n > 0 {
509 db.maxIdle = n 508 db.maxIdle = n
510 } else { 509 } else {
511 // No idle connections. 510 // No idle connections.
512 db.maxIdle = -1 511 db.maxIdle = -1
513 } 512 }
514 // Make sure maxIdle doesn't exceed maxOpen 513 // Make sure maxIdle doesn't exceed maxOpen
515 if db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen { 514 if db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen {
516 db.maxIdle = db.maxOpen 515 db.maxIdle = db.maxOpen
517 } 516 }
517 var closing []*driverConn
518 for db.freeConn.Len() > db.maxIdleConnsLocked() { 518 for db.freeConn.Len() > db.maxIdleConnsLocked() {
519 dc := db.freeConn.Back().Value.(*driverConn) 519 dc := db.freeConn.Back().Value.(*driverConn)
520 dc.listElem = nil 520 dc.listElem = nil
521 db.freeConn.Remove(db.freeConn.Back()) 521 db.freeConn.Remove(db.freeConn.Back())
522 » » go dc.Close() 522 » » closing = append(closing, dc)
523 » }
524 » db.mu.Unlock()
525 » for _, c := range closing {
526 » » c.Close()
523 } 527 }
524 } 528 }
525 529
526 // SetMaxOpenConns sets the maximum number of open connections to the database. 530 // SetMaxOpenConns sets the maximum number of open connections to the database.
527 // 531 //
528 // If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than 532 // If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
529 // MaxIdleConns, then MaxIdleConns will be reduced to match the new 533 // MaxIdleConns, then MaxIdleConns will be reduced to match the new
530 // MaxOpenConns limit 534 // MaxOpenConns limit
531 // 535 //
532 // If n <= 0, then there is no limit on the number of open connections. 536 // If n <= 0, then there is no limit on the number of open connections.
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 dc.inUse = false 740 dc.inUse = false
737 741
738 for _, fn := range dc.onPut { 742 for _, fn := range dc.onPut {
739 fn() 743 fn()
740 } 744 }
741 dc.onPut = nil 745 dc.onPut = nil
742 746
743 if err == driver.ErrBadConn { 747 if err == driver.ErrBadConn {
744 // Don't reuse bad connections. 748 // Don't reuse bad connections.
745 // Since the conn is considered bad and is being discarded, trea t it 749 // Since the conn is considered bad and is being discarded, trea t it
746 » » // as closed. Decrement the open count. 750 » » // as closed. Don't decrement the open count here, finalClose wi ll
747 » » db.numOpen-- 751 » » // take care of that.
748 db.maybeOpenNewConnections() 752 db.maybeOpenNewConnections()
749 db.mu.Unlock() 753 db.mu.Unlock()
750 dc.Close() 754 dc.Close()
751 return 755 return
752 } 756 }
753 if putConnHook != nil { 757 if putConnHook != nil {
754 putConnHook(db, dc) 758 putConnHook(db, dc)
755 } 759 }
756 added := db.putConnDBLocked(dc, nil) 760 added := db.putConnDBLocked(dc, nil)
757 db.mu.Unlock() 761 db.mu.Unlock()
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after
1600 // the Rows in our defer, when we return from this function. 1604 // the Rows in our defer, when we return from this function.
1601 // the contract with the driver.Next(...) interface is that it 1605 // the contract with the driver.Next(...) interface is that it
1602 // can return slices into read-only temporary memory that's 1606 // can return slices into read-only temporary memory that's
1603 // only valid until the next Scan/Close. But the TODO is that 1607 // only valid until the next Scan/Close. But the TODO is that
1604 // for a lot of drivers, this copy will be unnecessary. We 1608 // for a lot of drivers, this copy will be unnecessary. We
1605 // should provide an optional interface for drivers to 1609 // should provide an optional interface for drivers to
1606 // implement to say, "don't worry, the []bytes that I return 1610 // implement to say, "don't worry, the []bytes that I return
1607 // from Next will not be modified again." (for instance, if 1611 // from Next will not be modified again." (for instance, if
1608 // they were obtained from the network anyway) But for now we 1612 // they were obtained from the network anyway) But for now we
1609 // don't care. 1613 // don't care.
1614 defer r.rows.Close()
1610 for _, dp := range dest { 1615 for _, dp := range dest {
1611 if _, ok := dp.(*RawBytes); ok { 1616 if _, ok := dp.(*RawBytes); ok {
1612 return errors.New("sql: RawBytes isn't allowed on Row.Sc an") 1617 return errors.New("sql: RawBytes isn't allowed on Row.Sc an")
1613 } 1618 }
1614 } 1619 }
1615 1620
1616 defer r.rows.Close()
1617 if !r.rows.Next() { 1621 if !r.rows.Next() {
1618 return ErrNoRows 1622 return ErrNoRows
1619 } 1623 }
1620 err := r.rows.Scan(dest...) 1624 err := r.rows.Scan(dest...)
1621 if err != nil { 1625 if err != nil {
1622 return err 1626 return err
1623 } 1627 }
1624 1628
1625 return nil 1629 return nil
1626 } 1630 }
(...skipping 25 matching lines...) Expand all
1652 var buf [2 << 10]byte 1656 var buf [2 << 10]byte
1653 return string(buf[:runtime.Stack(buf[:], false)]) 1657 return string(buf[:runtime.Stack(buf[:], false)])
1654 } 1658 }
1655 1659
1656 // withLock runs while holding lk. 1660 // withLock runs while holding lk.
1657 func withLock(lk sync.Locker, fn func()) { 1661 func withLock(lk sync.Locker, fn func()) {
1658 lk.Lock() 1662 lk.Lock()
1659 fn() 1663 fn()
1660 lk.Unlock() 1664 lk.Unlock()
1661 } 1665 }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/database/sql/sql_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b