Left: | ||
Right: |
LEFT | RIGHT |
---|---|
(no file at all) | |
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 package sql | 7 package sql |
8 | 8 |
9 import ( | 9 import ( |
10 "database/sql/driver" | 10 "database/sql/driver" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 // pool of idle connections. If observing session state is required, | 182 // pool of idle connections. If observing session state is required, |
183 // either do not share a *DB between multiple concurrent goroutines or | 183 // either do not share a *DB between multiple concurrent goroutines or |
184 // create and observe all state only within a transaction. Once | 184 // create and observe all state only within a transaction. Once |
185 // DB.Open is called, the returned Tx is bound to a single isolated | 185 // DB.Open is called, the returned Tx is bound to a single isolated |
186 // connection. Once Tx.Commit or Tx.Rollback is called, that | 186 // connection. Once Tx.Commit or Tx.Rollback is called, that |
187 // connection is returned to DB's idle connection pool. | 187 // connection is returned to DB's idle connection pool. |
188 type DB struct { | 188 type DB struct { |
189 driver driver.Driver | 189 driver driver.Driver |
190 dsn string | 190 dsn string |
191 | 191 |
192 » mu sync.Mutex // protects freeConn and closed | 192 » mu sync.Mutex // protects freeConn, closed and maxIdleConns |
193 » freeConn []driver.Conn | 193 » freeConn []driver.Conn |
194 » closed bool | 194 » closed bool |
195 » maxIdleConns int | |
195 } | 196 } |
196 | 197 |
197 // Open opens a database specified by its database driver name and a | 198 // Open opens a database specified by its database driver name and a |
198 // driver-specific data source name, usually consisting of at least a | 199 // driver-specific data source name, usually consisting of at least a |
199 // database name and connection information. | 200 // database name and connection information. |
200 // | 201 // |
201 // Most users will open a database via a driver-specific connection | 202 // Most users will open a database via a driver-specific connection |
202 // helper function that returns a *DB. | 203 // helper function that returns a *DB. |
203 func Open(driverName, dataSourceName string) (*DB, error) { | 204 func Open(driverName, dataSourceName string) (*DB, error) { |
204 driver, ok := drivers[driverName] | 205 driver, ok := drivers[driverName] |
205 if !ok { | 206 if !ok { |
206 return nil, fmt.Errorf("sql: unknown driver %q (forgotten import ?)", driverName) | 207 return nil, fmt.Errorf("sql: unknown driver %q (forgotten import ?)", driverName) |
207 } | 208 } |
208 » return &DB{driver: driver, dsn: dataSourceName}, nil | 209 » return &DB{driver: driver, dsn: dataSourceName, maxIdleConns: 2}, nil |
209 } | 210 } |
210 | 211 |
211 // Close closes the database, releasing any open resources. | 212 // Close closes the database, releasing any open resources. |
212 func (db *DB) Close() error { | 213 func (db *DB) Close() error { |
213 db.mu.Lock() | 214 db.mu.Lock() |
214 defer db.mu.Unlock() | 215 defer db.mu.Unlock() |
215 var err error | 216 var err error |
216 for _, c := range db.freeConn { | 217 for _, c := range db.freeConn { |
217 err1 := c.Close() | 218 err1 := c.Close() |
218 if err1 != nil { | 219 if err1 != nil { |
219 err = err1 | 220 err = err1 |
220 } | 221 } |
221 } | 222 } |
222 db.freeConn = nil | 223 db.freeConn = nil |
223 db.closed = true | 224 db.closed = true |
224 return err | 225 return err |
225 } | 226 } |
226 | 227 |
227 func (db *DB) maxIdleConns() int { | 228 // Adjust the maximum number of permanently retained database connections. This |
bradfitz
2013/03/08 22:40:08
See next comment.
// SetMaxIdleConns sets ...
| |
228 » const defaultMaxIdleConns = 2 | 229 // defaults to 2 for historical reasons. N.B. This is not the maximum number of |
bradfitz
2013/03/08 22:40:08
I think we should instead make an exported constan
| |
230 // connections that can be open, or the minimum. It is the maximum number that | |
231 // are retained between uses. | |
232 func (db *DB) SetMaxIdleConns(v int) int { | |
233 » db.mu.Lock() | |
234 » defer db.mu.Unlock() | |
235 » db.maxIdleConns = v | |
236 » return v | |
237 } | |
238 | |
239 // The current maximum number of idle database connections allowed. See | |
bradfitz
2013/03/08 22:40:08
Go comment style is to start sentences with the na
| |
240 // SetMaxIdleConns for more information. | |
241 func (db *DB) MaxIdleConns() int { | |
229 // TODO(bradfitz): ask driver, if supported, for its default preference | 242 // TODO(bradfitz): ask driver, if supported, for its default preference |
bradfitz
2013/03/08 22:40:08
probably not here anymore. Probably only once the
julienschmidt
2013/03/09 02:10:03
I like the idea of a config struct ( like I did he
| |
230 » // TODO(bradfitz): let users override? | 243 » db.mu.Lock() |
231 » return defaultMaxIdleConns | 244 » defer db.mu.Unlock() |
245 » return db.maxIdleConns | |
232 } | 246 } |
233 | 247 |
234 // conn returns a newly-opened or cached driver.Conn | 248 // conn returns a newly-opened or cached driver.Conn |
235 func (db *DB) conn() (driver.Conn, error) { | 249 func (db *DB) conn() (driver.Conn, error) { |
236 db.mu.Lock() | 250 db.mu.Lock() |
237 if db.closed { | 251 if db.closed { |
238 db.mu.Unlock() | 252 db.mu.Unlock() |
239 return nil, errors.New("sql: database is closed") | 253 return nil, errors.New("sql: database is closed") |
240 } | 254 } |
241 if n := len(db.freeConn); n > 0 { | 255 if n := len(db.freeConn); n > 0 { |
(...skipping 23 matching lines...) Expand all Loading... | |
265 // putConnHook is a hook for testing. | 279 // putConnHook is a hook for testing. |
266 var putConnHook func(*DB, driver.Conn) | 280 var putConnHook func(*DB, driver.Conn) |
267 | 281 |
268 // putConn adds a connection to the db's free pool. | 282 // putConn adds a connection to the db's free pool. |
269 // err is optionally the last error that occured on this connection. | 283 // err is optionally the last error that occured on this connection. |
270 func (db *DB) putConn(c driver.Conn, err error) { | 284 func (db *DB) putConn(c driver.Conn, err error) { |
271 if err == driver.ErrBadConn { | 285 if err == driver.ErrBadConn { |
272 // Don't reuse bad connections. | 286 // Don't reuse bad connections. |
273 return | 287 return |
274 } | 288 } |
289 // maxIdle is fetched before we open the lock. Ideally move to an RWLock | |
290 // instead, and retain it, which may reduce the time over which inconsis tent | |
291 // numbers of connections may be retained. The value also could just be | |
292 // modified using atomic. | |
293 maxIdle := db.MaxIdleConns() | |
bradfitz
2013/03/08 22:40:08
this is grabbing a lock and unlocking it, even tho
| |
275 db.mu.Lock() | 294 db.mu.Lock() |
276 if putConnHook != nil { | 295 if putConnHook != nil { |
277 putConnHook(db, c) | 296 putConnHook(db, c) |
278 } | 297 } |
279 » if n := len(db.freeConn); !db.closed && n < db.maxIdleConns() { | 298 » if n := len(db.freeConn); !db.closed && n < maxIdle { |
280 db.freeConn = append(db.freeConn, c) | 299 db.freeConn = append(db.freeConn, c) |
281 db.mu.Unlock() | 300 db.mu.Unlock() |
282 return | 301 return |
283 } | 302 } |
284 // TODO: check to see if we need this Conn for any prepared | 303 // TODO: check to see if we need this Conn for any prepared |
285 // statements which are still active? | 304 // statements which are still active? |
286 db.mu.Unlock() | 305 db.mu.Unlock() |
287 c.Close() | 306 c.Close() |
288 } | 307 } |
289 | 308 |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1035 | 1054 |
1036 // A Result summarizes an executed SQL command. | 1055 // A Result summarizes an executed SQL command. |
1037 type Result interface { | 1056 type Result interface { |
1038 LastInsertId() (int64, error) | 1057 LastInsertId() (int64, error) |
1039 RowsAffected() (int64, error) | 1058 RowsAffected() (int64, error) |
1040 } | 1059 } |
1041 | 1060 |
1042 type result struct { | 1061 type result struct { |
1043 driver.Result | 1062 driver.Result |
1044 } | 1063 } |
LEFT | RIGHT |