From de0bbfa4d67d14b1200efaba0cb6bd5e5181e8d5 Mon Sep 17 00:00:00 2001 From: Chakrit Wichian Date: Fri, 25 Sep 2015 15:03:51 +0700 Subject: [PATCH 1/4] read_timeout and write_timeout --- benchmark_test.go | 12 +++++++----- buffer.go | 12 +++++++++++- driver.go | 2 +- dsn.go | 35 +++++++++++++++++++++++++---------- dsn_test.go | 26 +++++++++++++------------- packets.go | 6 ++++++ 6 files changed, 63 insertions(+), 30 deletions(-) diff --git a/benchmark_test.go b/benchmark_test.go index 7ccb46fcc..bcceedfdb 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -215,14 +215,16 @@ func BenchmarkRoundtripBin(b *testing.B) { } func BenchmarkInterpolation(b *testing.B) { + cfg := &Config{ + InterpolateParams: true, + Loc: time.UTC, + } + mc := &mysqlConn{ - cfg: &Config{ - InterpolateParams: true, - Loc: time.UTC, - }, + cfg: cfg, maxPacketAllowed: maxPacketSize, maxWriteSize: maxPacketSize - 1, - buf: newBuffer(nil), + buf: newBuffer(nil, cfg), } args := []driver.Value{ diff --git a/buffer.go b/buffer.go index 509ce89e4..060f5285c 100644 --- a/buffer.go +++ b/buffer.go @@ -9,6 +9,8 @@ package mysql import "io" +import "net" +import "time" const defaultBufSize = 4096 @@ -22,13 +24,15 @@ type buffer struct { rd io.Reader idx int length int + cfg *Config } -func newBuffer(rd io.Reader) buffer { +func newBuffer(rd io.Reader, cfg *Config) buffer { var b [defaultBufSize]byte return buffer{ buf: b[:], rd: rd, + cfg: cfg, } } @@ -54,6 +58,12 @@ func (b *buffer) fill(need int) error { b.idx = 0 for { + if conn, ok := b.rd.(net.Conn); ok && b.cfg.ReadTimeout > 0 { + if err := conn.SetReadDeadline(time.Now().Add(b.cfg.ReadTimeout)); err != nil { + return err + } + } + nn, err := b.rd.Read(b.buf[n:]) n += nn diff --git a/driver.go b/driver.go index 1d7723b82..ef412844f 100644 --- a/driver.go +++ b/driver.go @@ -81,7 +81,7 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { } } - mc.buf = newBuffer(mc.netConn) + mc.buf = newBuffer(mc.netConn, mc.cfg) // Reading Handshake Initialization Packet cipher, err := mc.readInitPacket() diff --git a/dsn.go b/dsn.go index 45b4899d9..0cf269ba5 100644 --- a/dsn.go +++ b/dsn.go @@ -27,16 +27,18 @@ var ( // Config is a configuration parsed from a DSN string type Config struct { - User string // Username - Passwd string // Password - Net string // Network type - Addr string // Network address - DBName string // Database name - Params map[string]string // Connection parameters - Loc *time.Location // Location for time.Time values - TLS *tls.Config // TLS configuration - Timeout time.Duration // Dial timeout - Collation uint8 // Connection collation + User string // Username + Passwd string // Password + Net string // Network type + Addr string // Network address + DBName string // Database name + Params map[string]string // Connection parameters + Loc *time.Location // Location for time.Time values + TLS *tls.Config // TLS configuration + Timeout time.Duration // Dial timeout + ReadTimeout time.Duration // I/O read timeout + WriteTimeout time.Duration // I/O write timeout + Collation uint8 // Connection collation AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE AllowCleartextPasswords bool // Allows the cleartext client side plugin @@ -256,6 +258,19 @@ func parseDSNParams(cfg *Config, params string) (err error) { return } + // I/O Timeouts + case "read_timeout": + cfg.ReadTimeout, err = time.ParseDuration(value) + if err != nil { + return + } + + case "write_timeout": + cfg.WriteTimeout, err = time.ParseDuration(value) + if err != nil { + return + } + // TLS-Encryption case "tls": boolValue, isBool := readBool(value) diff --git a/dsn_test.go b/dsn_test.go index 4ac1f562c..9a0ee99c3 100644 --- a/dsn_test.go +++ b/dsn_test.go @@ -19,19 +19,19 @@ var testDSNs = []struct { in string out string }{ - {"username:password@protocol(address)/dbname?param=value", "&{User:username Passwd:password Net:protocol Addr:address DBName:dbname Params:map[param:value] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"username:password@protocol(address)/dbname?param=value&columnsWithAlias=true", "&{User:username Passwd:password Net:protocol Addr:address DBName:dbname Params:map[param:value] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:true InterpolateParams:false ParseTime:false Strict:false}"}, - {"user@unix(/path/to/socket)/dbname?charset=utf8", "&{User:user Passwd: Net:unix Addr:/path/to/socket DBName:dbname Params:map[charset:utf8] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"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:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"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:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"user:password@/dbname?loc=UTC&timeout=30s&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:UTC TLS: Timeout:30s Collation:224 AllowAllFiles:true AllowCleartextPasswords:false AllowOldPasswords:true ClientFoundRows:true ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"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:Local TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"/dbname", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName:dbname Params:map[] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"@/", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"/", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"user:p@/ssword@/", "&{User:user Passwd:p@/ssword Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"unix/?arg=%2Fsome%2Fpath.ext", "&{User: Passwd: Net:unix Addr:/tmp/mysql.sock DBName: Params:map[arg:/some/path.ext] Loc:UTC TLS: Timeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"username:password@protocol(address)/dbname?param=value", "&{User:username Passwd:password Net:protocol Addr:address DBName:dbname Params:map[param:value] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"username:password@protocol(address)/dbname?param=value&columnsWithAlias=true", "&{User:username Passwd:password Net:protocol Addr:address DBName:dbname Params:map[param:value] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:true InterpolateParams:false ParseTime:false Strict:false}"}, + {"user@unix(/path/to/socket)/dbname?charset=utf8", "&{User:user Passwd: Net:unix Addr:/path/to/socket DBName:dbname Params:map[charset:utf8] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"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:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"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:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"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:UTC TLS: Timeout:30s ReadTimeout:1s WriteTimeout:1s Collation:224 AllowAllFiles:true AllowCleartextPasswords:false AllowOldPasswords:true ClientFoundRows:true ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"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:Local TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"/dbname", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName:dbname Params:map[] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"@/", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"/", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"user:p@/ssword@/", "&{User:user Passwd:p@/ssword Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"unix/?arg=%2Fsome%2Fpath.ext", "&{User: Passwd: Net:unix Addr:/tmp/mysql.sock DBName: Params:map[arg:/some/path.ext] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, } func TestDSNParser(t *testing.T) { diff --git a/packets.go b/packets.go index 532c56c96..81b2326ee 100644 --- a/packets.go +++ b/packets.go @@ -100,6 +100,12 @@ func (mc *mysqlConn) writePacket(data []byte) error { data[3] = mc.sequence // Write packet + if mc.cfg.WriteTimeout > 0 { + if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.cfg.WriteTimeout)); err != nil { + return err + } + } + n, err := mc.netConn.Write(data[:4+size]) if err == nil && n == 4+size { mc.sequence++ From 68ca989dd40fb96ae66976689f8df4b696fb0765 Mon Sep 17 00:00:00 2001 From: Julien Schmidt Date: Tue, 12 Jan 2016 23:12:54 +0100 Subject: [PATCH 2/4] Improve timeouts implementation - use local attributes for timeouts - do not type assert to net.Conn each time - DSN params are CamelCase --- benchmark_test.go | 12 +++++------- buffer.go | 29 +++++++++++++++-------------- connection.go | 3 ++- driver.go | 6 +++++- dsn.go | 27 ++++++++++++++------------- dsn_test.go | 2 +- packets.go | 6 +++--- 7 files changed, 45 insertions(+), 40 deletions(-) diff --git a/benchmark_test.go b/benchmark_test.go index bcceedfdb..7ccb46fcc 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -215,16 +215,14 @@ func BenchmarkRoundtripBin(b *testing.B) { } func BenchmarkInterpolation(b *testing.B) { - cfg := &Config{ - InterpolateParams: true, - Loc: time.UTC, - } - mc := &mysqlConn{ - cfg: cfg, + cfg: &Config{ + InterpolateParams: true, + Loc: time.UTC, + }, maxPacketAllowed: maxPacketSize, maxWriteSize: maxPacketSize - 1, - buf: newBuffer(nil, cfg), + buf: newBuffer(nil), } args := []driver.Value{ diff --git a/buffer.go b/buffer.go index 060f5285c..2001feacd 100644 --- a/buffer.go +++ b/buffer.go @@ -8,9 +8,11 @@ package mysql -import "io" -import "net" -import "time" +import ( + "io" + "net" + "time" +) const defaultBufSize = 4096 @@ -20,19 +22,18 @@ const defaultBufSize = 4096 // The buffer is similar to bufio.Reader / Writer but zero-copy-ish // Also highly optimized for this particular use case. type buffer struct { - buf []byte - rd io.Reader - idx int - length int - cfg *Config + buf []byte + nc net.Conn + idx int + length int + timeout time.Duration } -func newBuffer(rd io.Reader, cfg *Config) buffer { +func newBuffer(nc net.Conn) buffer { var b [defaultBufSize]byte return buffer{ buf: b[:], - rd: rd, - cfg: cfg, + nc: nc, } } @@ -58,13 +59,13 @@ func (b *buffer) fill(need int) error { b.idx = 0 for { - if conn, ok := b.rd.(net.Conn); ok && b.cfg.ReadTimeout > 0 { - if err := conn.SetReadDeadline(time.Now().Add(b.cfg.ReadTimeout)); err != nil { + if b.timeout > 0 { + if err := b.nc.SetReadDeadline(time.Now().Add(b.timeout)); err != nil { return err } } - nn, err := b.rd.Read(b.buf[n:]) + nn, err := b.nc.Read(b.buf[n:]) n += nn switch err { diff --git a/connection.go b/connection.go index c708796f8..c3899de0e 100644 --- a/connection.go +++ b/connection.go @@ -24,6 +24,7 @@ type mysqlConn struct { cfg *Config maxPacketAllowed int maxWriteSize int + writeTimeout time.Duration flags clientFlag status statusFlag sequence uint8 @@ -98,7 +99,7 @@ func (mc *mysqlConn) cleanup() { mc.netConn = nil } mc.cfg = nil - mc.buf.rd = nil + mc.buf.nc = nil } func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) { diff --git a/driver.go b/driver.go index ef412844f..965b663b7 100644 --- a/driver.go +++ b/driver.go @@ -81,7 +81,11 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { } } - mc.buf = newBuffer(mc.netConn, mc.cfg) + mc.buf = newBuffer(mc.netConn) + + // Set I/O timeouts + mc.buf.timeout = mc.cfg.ReadTimeout + mc.writeTimeout = mc.cfg.WriteTimeout // Reading Handshake Initialization Packet cipher, err := mc.readInitPacket() diff --git a/dsn.go b/dsn.go index 0cf269ba5..8ca73dc68 100644 --- a/dsn.go +++ b/dsn.go @@ -243,6 +243,13 @@ func parseDSNParams(cfg *Config, params string) (err error) { return errors.New("Invalid Bool value: " + value) } + // I/O read Timeout + case "readTimeout": + cfg.ReadTimeout, err = time.ParseDuration(value) + if err != nil { + return + } + // Strict mode case "strict": var isBool bool @@ -258,19 +265,6 @@ func parseDSNParams(cfg *Config, params string) (err error) { return } - // I/O Timeouts - case "read_timeout": - cfg.ReadTimeout, err = time.ParseDuration(value) - if err != nil { - return - } - - case "write_timeout": - cfg.WriteTimeout, err = time.ParseDuration(value) - if err != nil { - return - } - // TLS-Encryption case "tls": boolValue, isBool := readBool(value) @@ -297,6 +291,13 @@ func parseDSNParams(cfg *Config, params string) (err error) { } } + // I/O write Timeout + case "writeTimeout": + cfg.WriteTimeout, err = time.ParseDuration(value) + if err != nil { + return + } + default: // lazy init if cfg.Params == nil { diff --git a/dsn_test.go b/dsn_test.go index 9a0ee99c3..3e2a4b37a 100644 --- a/dsn_test.go +++ b/dsn_test.go @@ -24,7 +24,7 @@ var testDSNs = []struct { {"user@unix(/path/to/socket)/dbname?charset=utf8", "&{User:user Passwd: Net:unix Addr:/path/to/socket DBName:dbname Params:map[charset:utf8] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, {"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:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, {"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:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, - {"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:UTC TLS: Timeout:30s ReadTimeout:1s WriteTimeout:1s Collation:224 AllowAllFiles:true AllowCleartextPasswords:false AllowOldPasswords:true ClientFoundRows:true ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, + {"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:UTC TLS: Timeout:30s ReadTimeout:1s WriteTimeout:1s Collation:224 AllowAllFiles:true AllowCleartextPasswords:false AllowOldPasswords:true ClientFoundRows:true ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, {"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:Local TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, {"/dbname", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName:dbname Params:map[] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, {"@/", "&{User: Passwd: Net:tcp Addr:127.0.0.1:3306 DBName: Params:map[] Loc:UTC TLS: Timeout:0 ReadTimeout:0 WriteTimeout:0 Collation:33 AllowAllFiles:false AllowCleartextPasswords:false AllowOldPasswords:false ClientFoundRows:false ColumnsWithAlias:false InterpolateParams:false ParseTime:false Strict:false}"}, diff --git a/packets.go b/packets.go index 81b2326ee..88d990a2d 100644 --- a/packets.go +++ b/packets.go @@ -100,8 +100,8 @@ func (mc *mysqlConn) writePacket(data []byte) error { data[3] = mc.sequence // Write packet - if mc.cfg.WriteTimeout > 0 { - if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.cfg.WriteTimeout)); err != nil { + if mc.writeTimeout > 0 { + if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.writeTimeout)); err != nil { return err } } @@ -284,7 +284,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { return err } mc.netConn = tlsConn - mc.buf.rd = tlsConn + mc.buf.nc = tlsConn } // Filler [23 bytes] (all 0x00) From 2cd96dd9ba18cbc7b96e2ba863d9b5b66509056b Mon Sep 17 00:00:00 2001 From: Julien Schmidt Date: Tue, 12 Jan 2016 23:51:10 +0100 Subject: [PATCH 3/4] Update README.md Add readTimeout and writeTimeout params --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 706b7ef2e..c02b6a245 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,16 @@ Default: false `parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string` +##### `readTimeout` + +``` +Type: decimal number +Default: 0 +``` + +I/O read timeout. The value must be a string of decimal numbers, each with optional fraction and a unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. + + ##### `strict` ``` @@ -265,6 +275,16 @@ Default: false `tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side). Use a custom value registered with [`mysql.RegisterTLSConfig`](http://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig). +##### `writeTimeout` + +``` +Type: decimal number +Default: 0 +``` + +I/O write timeout. The value must be a string of decimal numbers, each with optional fraction and a unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. + + ##### System Variables All other parameters are interpreted as system variables: From f7f9f33777eb46a937c22408a288518520129627 Mon Sep 17 00:00:00 2001 From: Julien Schmidt Date: Tue, 19 Jan 2016 16:03:51 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c02b6a245..f3190e8ab 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,7 @@ Type: decimal number Default: 0 ``` -I/O read timeout. The value must be a string of decimal numbers, each with optional fraction and a unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. +I/O read timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. ##### `strict` @@ -261,7 +261,7 @@ Type: decimal number Default: OS default ``` -*Driver* side connection timeout. The value must be a string of decimal numbers, each with optional fraction and a unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. To set a server side timeout, use the parameter [`wait_timeout`](http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout). +*Driver* side connection timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. To set a server side timeout, use the parameter [`wait_timeout`](http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout). ##### `tls` @@ -282,7 +282,7 @@ Type: decimal number Default: 0 ``` -I/O write timeout. The value must be a string of decimal numbers, each with optional fraction and a unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. +I/O write timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. ##### System Variables