-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
Copy pathconnection_go18.go
90 lines (78 loc) · 1.96 KB
/
connection_go18.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// +build go1.8
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"context"
"database/sql/driver"
"net"
"time"
)
func (mc *mysqlConn) Ping(ctx context.Context) error {
var err error
if ctx == nil {
return mc.pingImpl()
}
mc.ctx = ctx
defer func() {
mc.ctx = nil
}()
if deadline, ok := ctx.Deadline(); ok {
if err = mc.netConn.SetDeadline(deadline); err != nil {
return err
}
}
if ctx.Done() == nil {
return mc.pingImpl()
}
result := make(chan error)
go func() {
result <- mc.pingImpl()
}()
select {
case <-ctx.Done():
// Because buffer.fill() and mysqlConn.writePacket() may overwrite the
// deadline of read/write again and again in the above goroutine,
// it has to use a loop to make sure SetDeadline() works.
UpdateDeadlineLoop:
for {
// Copy it as a local variable because mc.netConn may be closed and
// assigned nil in the above goroutine.
netConn := mc.netConn
if netConn != nil {
errDeadline := netConn.SetDeadline(time.Now())
if errDeadline != nil {
errLog.Print(errDeadline)
}
}
select {
case <-time.After(200 * time.Millisecond):
// Prevent from leaking the above goroutine.
case err = <-result:
break UpdateDeadlineLoop
}
}
case err = <-result:
}
if netErr, ok := err.(net.Error); ok {
// We don't know where it timed out and it may leave some redundant data
// in the connection so make it to be closed by DB.puConn() of the
// caller.
if netErr.Timeout() {
return driver.ErrBadConn
}
}
return err
}
func (mc *mysqlConn) pingImpl() error {
if err := mc.writeCommandPacket(comPing); err != nil {
return err
}
_, err := mc.readResultOK()
return err
}