Skip to content

Commit b88f271

Browse files
committed
Improve timeouts implementation
- use local attributes for timeouts - do not type assert to net.Conn each time - DSN params are CamelCase
1 parent 4613f32 commit b88f271

File tree

7 files changed

+35
-30
lines changed

7 files changed

+35
-30
lines changed

Diff for: benchmark_test.go

+5-7
Original file line numberDiff line numberDiff line change
@@ -215,16 +215,14 @@ func BenchmarkRoundtripBin(b *testing.B) {
215215
}
216216

217217
func BenchmarkInterpolation(b *testing.B) {
218-
cfg := &config{
219-
interpolateParams: true,
220-
loc: time.UTC,
221-
}
222-
223218
mc := &mysqlConn{
224-
cfg: cfg,
219+
cfg: &config{
220+
interpolateParams: true,
221+
loc: time.UTC,
222+
},
225223
maxPacketAllowed: maxPacketSize,
226224
maxWriteSize: maxPacketSize - 1,
227-
buf: newBuffer(nil, cfg),
225+
buf: newBuffer(nil),
228226
}
229227

230228
args := []driver.Value{

Diff for: buffer.go

+15-14
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
package mysql
1010

11-
import "io"
12-
import "net"
13-
import "time"
11+
import (
12+
"io"
13+
"net"
14+
"time"
15+
)
1416

1517
const defaultBufSize = 4096
1618

@@ -20,19 +22,18 @@ const defaultBufSize = 4096
2022
// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
2123
// Also highly optimized for this particular use case.
2224
type buffer struct {
23-
buf []byte
24-
rd io.Reader
25-
idx int
26-
length int
27-
cfg *config
25+
buf []byte
26+
nc net.Conn
27+
idx int
28+
length int
29+
timeout time.Duration
2830
}
2931

30-
func newBuffer(rd io.Reader, cfg *config) buffer {
32+
func newBuffer(nc net.Conn) buffer {
3133
var b [defaultBufSize]byte
3234
return buffer{
3335
buf: b[:],
34-
rd: rd,
35-
cfg: cfg,
36+
nc: nc,
3637
}
3738
}
3839

@@ -58,13 +59,13 @@ func (b *buffer) fill(need int) error {
5859
b.idx = 0
5960

6061
for {
61-
if conn, ok := b.rd.(net.Conn); ok && b.cfg.readTimeout > 0 {
62-
if err := conn.SetReadDeadline(time.Now().Add(b.cfg.readTimeout)); err != nil {
62+
if b.timeout > 0 {
63+
if err := b.nc.SetReadDeadline(time.Now().Add(b.timeout)); err != nil {
6364
return err
6465
}
6566
}
6667

67-
nn, err := b.rd.Read(b.buf[n:])
68+
nn, err := b.nc.Read(b.buf[n:])
6869
n += nn
6970

7071
switch err {

Diff for: connection.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type mysqlConn struct {
2626
cfg *config
2727
maxPacketAllowed int
2828
maxWriteSize int
29+
writeTimeout time.Duration
2930
flags clientFlag
3031
status statusFlag
3132
sequence uint8
@@ -131,7 +132,7 @@ func (mc *mysqlConn) Close() (err error) {
131132
}
132133

133134
mc.cfg = nil
134-
mc.buf.rd = nil
135+
mc.buf.nc = nil
135136

136137
return
137138
}

Diff for: driver.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
7979
}
8080
}
8181

82-
mc.buf = newBuffer(mc.netConn, mc.cfg)
82+
mc.buf = newBuffer(mc.netConn)
83+
84+
// Set I/O timeouts
85+
mc.buf.timeout = mc.cfg.readTimeout
86+
mc.writeTimeout = mc.cfg.writeTimeout
8387

8488
// Reading Handshake Initialization Packet
8589
cipher, err := mc.readInitPacket()

Diff for: packets.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ func (mc *mysqlConn) writePacket(data []byte) error {
100100
data[3] = mc.sequence
101101

102102
// Write packet
103-
if mc.cfg.writeTimeout > 0 {
104-
if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.cfg.writeTimeout)); err != nil {
103+
if mc.writeTimeout > 0 {
104+
if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.writeTimeout)); err != nil {
105105
return err
106106
}
107107
}
@@ -284,7 +284,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
284284
return err
285285
}
286286
mc.netConn = tlsConn
287-
mc.buf.rd = tlsConn
287+
mc.buf.nc = tlsConn
288288
}
289289

290290
// Filler [23 bytes] (all 0x00)

Diff for: utils.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -260,14 +260,15 @@ func parseDSNParams(cfg *config, params string) (err error) {
260260
return
261261
}
262262

263-
// I/O Timeouts
264-
case "read_timeout":
263+
// I/O Read Timeout
264+
case "readTimeout":
265265
cfg.readTimeout, err = time.ParseDuration(value)
266266
if err != nil {
267267
return
268268
}
269269

270-
case "write_timeout":
270+
// I/O Write Timeout
271+
case "writeTimeout":
271272
cfg.writeTimeout, err = time.ParseDuration(value)
272273
if err != nil {
273274
return

Diff for: utils_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ var testDSNs = []struct {
2727
{"user@unix(/path/to/socket)/dbname?charset=utf8", "&{user:user passwd: net:unix addr:/path/to/socket dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
2828
{"user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
2929
{"user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8mb4,utf8] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
30-
{"user:password@/dbname?loc=UTC&timeout=30s&read_timeout=1s&write_timeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci", "&{user:user passwd:password net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:30000000000 readTimeout:1000000000 writeTimeout:1000000000 collation:224 allowAllFiles:true allowOldPasswords:true allowCleartextPasswords:false clientFoundRows:true columnsWithAlias:false interpolateParams:false}", time.UTC},
30+
{"user:password@/dbname?loc=UTC&timeout=30s&readTimeout=1s&writeTimeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci", "&{user:user passwd:password net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:30000000000 readTimeout:1000000000 writeTimeout:1000000000 collation:224 allowAllFiles:true allowOldPasswords:true allowCleartextPasswords:false clientFoundRows:true columnsWithAlias:false interpolateParams:false}", time.UTC},
3131
{"user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local", "&{user:user passwd:p@ss(word) net:tcp addr:[de:ad:be:ef::ca:fe]:80 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.Local},
3232
{"/dbname", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
3333
{"@/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},

0 commit comments

Comments
 (0)