| LEFT | RIGHT |
| 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 // | 10 // |
| (...skipping 1308 matching lines...) | | Loading... |
| 1319 if s.tx != nil { | 1319 if s.tx != nil { |
| 1320 s.mu.Unlock() | 1320 s.mu.Unlock() |
| 1321 ci, err = s.tx.grabConn() // blocks, waiting for the connection. | 1321 ci, err = s.tx.grabConn() // blocks, waiting for the connection. |
| 1322 if err != nil { | 1322 if err != nil { |
| 1323 return | 1323 return |
| 1324 } | 1324 } |
| 1325 releaseConn = func(error) {} | 1325 releaseConn = func(error) {} |
| 1326 return ci, releaseConn, s.txsi.si, nil | 1326 return ci, releaseConn, s.txsi.si, nil |
| 1327 } | 1327 } |
| 1328 | 1328 |
| 1329 » var cs connStmt | 1329 » connStmtInfo := func(cs connStmt) (ci *driverConn, releaseConn func(erro
r), si driver.Stmt, err error) { |
bradfitz
2014年09月02日 16:08:06
This could be a top-level function, but better I r
|
| 1330 » var dc *driverConn | 1330 » » conn := cs.dc |
| 1331 » match := false | 1331 » » return conn, conn.releaseConn, cs.si, nil |
| 1332 » } |
| 1333 |
| 1332 for i := 0; i < len(s.css); i++ { | 1334 for i := 0; i < len(s.css); i++ { |
| 1333 v := s.css[i] | 1335 v := s.css[i] |
| 1334 _, err := s.db.connIfFree(v.dc) | 1336 _, err := s.db.connIfFree(v.dc) |
| 1335 if err == nil { | 1337 if err == nil { |
| 1336 » » » match = true | 1338 » » » s.mu.Unlock() |
| 1337 » » » cs = v | 1339 » » » return connStmtInfo(v) |
| 1338 » » » break |
| 1339 } | 1340 } |
| 1340 if err == errConnClosed { | 1341 if err == errConnClosed { |
| 1341 // Lazily remove dead conn from our freelist. | 1342 // Lazily remove dead conn from our freelist. |
| 1342 s.css[i] = s.css[len(s.css)-1] | 1343 s.css[i] = s.css[len(s.css)-1] |
| 1343 s.css = s.css[:len(s.css)-1] | 1344 s.css = s.css[:len(s.css)-1] |
| 1344 i-- | 1345 i-- |
| 1345 } | 1346 } |
| 1346 | 1347 |
| 1347 } | 1348 } |
| 1348 s.mu.Unlock() | 1349 s.mu.Unlock() |
| 1349 if match { |
| 1350 goto found |
| 1351 } |
| 1352 | 1350 |
| 1353 // If all connections are busy, either wait for one to become available
(if | 1351 // If all connections are busy, either wait for one to become available
(if |
| 1354 // we've already hit the maximum number of open connections) or create a | 1352 // we've already hit the maximum number of open connections) or create a |
| 1355 // new one. | 1353 // new one. |
| 1356 // | 1354 // |
| 1357 // TODO(bradfitz): or always wait for one? make configurable later? | 1355 // TODO(bradfitz): or always wait for one? make configurable later? |
| 1358 » dc, err = s.db.conn() | 1356 » dc, err := s.db.conn() |
| 1359 if err != nil { | 1357 if err != nil { |
| 1360 return nil, nil, nil, err | 1358 return nil, nil, nil, err |
| 1361 } | 1359 } |
| 1362 | 1360 |
| 1363 // Do another pass over the list to see whether this statement has | 1361 // Do another pass over the list to see whether this statement has |
| 1364 // already been prepared on the connection assigned to us. | 1362 // already been prepared on the connection assigned to us. |
| 1365 s.mu.Lock() | 1363 s.mu.Lock() |
| 1366 for _, v := range s.css { | 1364 for _, v := range s.css { |
| 1367 if v.dc == dc { | 1365 if v.dc == dc { |
| 1368 » » » match = true | 1366 » » » s.mu.Unlock() |
| 1369 » » » cs = v | 1367 » » » return connStmtInfo(v) |
| 1370 » » » break |
| 1371 } | 1368 } |
| 1372 } | 1369 } |
| 1373 s.mu.Unlock() | 1370 s.mu.Unlock() |
| 1374 if match { |
| 1375 goto found |
| 1376 } |
| 1377 | 1371 |
| 1378 // No luck; we need to prepare the statement on this connection | 1372 // No luck; we need to prepare the statement on this connection |
| 1379 dc.Lock() | 1373 dc.Lock() |
| 1380 si, err = dc.prepareLocked(s.query) | 1374 si, err = dc.prepareLocked(s.query) |
| 1381 dc.Unlock() | 1375 dc.Unlock() |
| 1382 if err != nil { | 1376 if err != nil { |
| 1383 s.db.putConn(dc, err) | 1377 s.db.putConn(dc, err) |
| 1384 return nil, nil, nil, err | 1378 return nil, nil, nil, err |
| 1385 } | 1379 } |
| 1386 s.mu.Lock() | 1380 s.mu.Lock() |
| 1387 » cs = connStmt{dc, si} | 1381 » cs := connStmt{dc, si} |
| 1388 s.css = append(s.css, cs) | 1382 s.css = append(s.css, cs) |
| 1389 s.mu.Unlock() | 1383 s.mu.Unlock() |
| 1390 | 1384 |
| 1391 found: | 1385 » return connStmtInfo(cs) |
| 1392 » conn := cs.dc |
| 1393 » return conn, conn.releaseConn, cs.si, nil |
| 1394 } | 1386 } |
| 1395 | 1387 |
| 1396 // Query executes a prepared query statement with the given arguments | 1388 // Query executes a prepared query statement with the given arguments |
| 1397 // and returns the query results as a *Rows. | 1389 // and returns the query results as a *Rows. |
| 1398 func (s *Stmt) Query(args ...interface{}) (*Rows, error) { | 1390 func (s *Stmt) Query(args ...interface{}) (*Rows, error) { |
| 1399 s.closemu.RLock() | 1391 s.closemu.RLock() |
| 1400 defer s.closemu.RUnlock() | 1392 defer s.closemu.RUnlock() |
| 1401 | 1393 |
| 1402 var rowsi driver.Rows | 1394 var rowsi driver.Rows |
| 1403 for i := 0; i < maxBadConnRetries; i++ { | 1395 for i := 0; i < maxBadConnRetries; i++ { |
| (...skipping 323 matching lines...) | | Loading... |
| 1727 var buf [2 << 10]byte | 1719 var buf [2 << 10]byte |
| 1728 return string(buf[:runtime.Stack(buf[:], false)]) | 1720 return string(buf[:runtime.Stack(buf[:], false)]) |
| 1729 } | 1721 } |
| 1730 | 1722 |
| 1731 // withLock runs while holding lk. | 1723 // withLock runs while holding lk. |
| 1732 func withLock(lk sync.Locker, fn func()) { | 1724 func withLock(lk sync.Locker, fn func()) { |
| 1733 lk.Lock() | 1725 lk.Lock() |
| 1734 fn() | 1726 fn() |
| 1735 lk.Unlock() | 1727 lk.Unlock() |
| 1736 } | 1728 } |
| LEFT | RIGHT |