-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathconnection.go
109 lines (95 loc) · 3.04 KB
/
connection.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package mybench
import (
"fmt"
"github.com/go-mysql-org/go-mysql/client"
"github.com/go-mysql-org/go-mysql/mysql"
)
// The database config object that can be turned into a single connection
// (without connection pooling).
type DatabaseConfig struct {
// TODO: Unix socket
Host string
Port int
User string
Pass string
Database string
// If this is set, a connection will not be established. This is useful for
// non-database-related tests such as selfbench.
// TODO: this is kind of a hack...
NoConnection bool
// The number of underlying connections per Connection object, implemented as a
// static pool from which connections are fetched in a round-robin sequence with
// each successive request. The sole purpose of this feature is to multiply the
// number of open connections to the database to assess any performance impact
// specific to the overall number of open database connections.
//
// Note: this feature does not work on all benchmarks at this moment. It only
// works with benchmarks that uses the mybench.Connection.GetRoundRobinConnection
// function to get their connections and execute queries.
ConnectionMultiplier int
// Enable CLIENT_MULTI_STATEMENTS options on the client
ClientMultiStatements bool
}
// A thin wrapper around https://pkg.go.dev/github.com/go-mysql-org/go-mysql/client#Conn
// for now. It is possible in the future to extend this to support databases
// other than MySQL.
//
// This should only be initialized via DatabaseConfig.Connection().
type Connection struct {
*client.Conn
connList []*client.Conn
connIndex int
}
// Creates a new database if it doesn't exist
func (cfg DatabaseConfig) CreateDatabaseIfNeeded() error {
addr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
conn, err := client.Connect(addr, cfg.User, cfg.Pass, "")
if err == nil {
_, err = conn.Execute(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s`", cfg.Database))
conn.Close()
}
return err
}
// Returns a connection object based on the database configuration
func (cfg DatabaseConfig) Connection() (*Connection, error) {
if cfg.NoConnection {
return &Connection{}, nil
}
if cfg.ConnectionMultiplier == 0 {
cfg.ConnectionMultiplier = 1
}
addr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
connList := make([]*client.Conn, cfg.ConnectionMultiplier)
var options []func(*client.Conn)
if cfg.ClientMultiStatements {
options = append(options, func(c *client.Conn) {
c.SetCapability(mysql.CLIENT_MULTI_STATEMENTS)
})
}
for i := 0; i < cfg.ConnectionMultiplier; i++ {
conn, err := client.Connect(addr, cfg.User, cfg.Pass, cfg.Database, options...)
if err != nil {
return nil, err
}
connList[i] = conn
}
return &Connection{
Conn: connList[0],
connList: connList,
connIndex: 0,
}, nil
}
func (c *Connection) GetRoundRobinConnection() *client.Conn {
c.connIndex = (c.connIndex + 1) % len(c.connList)
return c.connList[c.connIndex]
}
func (c *Connection) Close() error {
var err error
for _, conn := range c.connList {
err = conn.Close()
if err != nil {
return err
}
}
return nil
}