/
mysqld.go
199 lines (172 loc) · 4.2 KB
/
mysqld.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
* Xenon
*
* Copyright 2018 The Xenon Authors.
* Code is licensed under the GPLv3.
*
*/
package mysqld
import (
"config"
"model"
"strconv"
"strings"
"sync"
"time"
"xbase/common"
"xbase/xlog"
)
// Mysqld tuple.
type Mysqld struct {
conf *config.BackupConfig
log *xlog.Log
cmd common.Command
backup *Backup
monitorTicker *time.Ticker
monitorRunning bool
mutex sync.RWMutex
status model.MYSQLD_STATUS
stats model.MysqldStats
argsHandler ArgsHandler
}
// NewMysqld creates the new Mysqld.
func NewMysqld(conf *config.BackupConfig, log *xlog.Log) *Mysqld {
return &Mysqld{
conf: conf,
log: log,
cmd: common.NewLinuxCommand(log),
backup: NewBackup(conf, log),
status: model.MYSQLD_NOTRUNNING,
argsHandler: NewLinuxArgs(conf),
}
}
// SetArgsHandler used to set the args handler.
func (m *Mysqld) SetArgsHandler(h ArgsHandler) {
m.argsHandler = h
}
// StartMysqld used to start mysql using mysqld_safe.
func (m *Mysqld) StartMysqld() error {
log := m.log
log.Warning("mysqld.prepare.to.start...")
if m.isMysqldRunning() {
log.Warning("mysqld.already.running...")
return nil
}
timeout := 3000
args := m.argsHandler.Start()
if _, err := m.cmd.RunCommandWithTimeout(timeout, bash, args); err != nil {
log.Error("mysqld.start..error[%+v]", err)
return err
}
log.Warning("mysqld.start.done...")
m.IncMysqldStarts()
return nil
}
// StopMysqld used to shutdown mysqld using mysqldadmin.
func (m *Mysqld) StopMysqld() error {
log := m.log
log.Warning("mysqld.prepare.to.shutdown...")
if !m.isMysqldRunning() {
return nil
}
timeout := 5000
args := m.argsHandler.Stop()
if _, err := m.cmd.RunCommandWithTimeout(timeout, bash, args); err != nil {
log.Error("mysqld.stop.mysqld.error[%+v]", err)
return err
}
m.setStatus(model.MYSQLD_SHUTDOWNING)
m.IncMysqldStops()
log.Warning("mysqld.shutdown.done...")
return nil
}
// KillMysqld is used to shutdown mysql before we rebuild it.
func (m *Mysqld) KillMysqld() error {
timeout := 3000
log := m.log
args := m.argsHandler.Kill()
log.Warning("mysqld.prepare.to.kill[%v]...", args)
if _, err := m.cmd.RunCommandWithTimeout(timeout, bash, args); err != nil {
log.Error("mysqld.kill.mysqld.error[%+v]", err)
return err
}
m.setStatus(model.MYSQLD_SHUTDOWNING)
m.IncMysqldStops()
log.Warning("mysqld.kill.done...")
return nil
}
// check the mysqld_safe --defaults-file=[] process is running.
func (m *Mysqld) isMysqldRunning() bool {
log := m.log
args := m.argsHandler.IsRunning()
outs, err := m.cmd.RunCommand(bash, args)
if err != nil {
log.Error("mysqld57.isMysqldRunning.error[%v:%+v]", outs, err)
return false
}
running, err := strconv.Atoi(strings.TrimSpace(outs))
if err != nil {
log.Error("isMysqldRunning.error[%+v]", err)
return true
}
return (running > 0)
}
func (m *Mysqld) monitor() {
if !m.isMysqldRunning() {
m.setStatus(model.MYSQLD_NOTRUNNING)
m.log.Error("mysqld_safe.is.dead.prepare.to.start.it...")
m.StartMysqld()
} else {
m.setStatus(model.MYSQLD_ISRUNNING)
}
}
// MonitorStart used to monite mysqld_safe is running or not.
func (m *Mysqld) MonitorStart() {
if m.monitorRunning {
return
}
// create ticker
m.monitorTicker = common.NormalTicker(m.conf.MysqldMonitorInterval)
go func() {
for range m.monitorTicker.C {
m.monitor()
}
}()
m.monitorRunning = true
m.IncMonitorStarts()
m.log.Info("mysqld[%v].monitor.start...", m.conf.DefaultsFile)
}
// MonitorStop used to stop the monitor.
func (m *Mysqld) MonitorStop() {
if !m.monitorRunning {
return
}
m.monitorTicker.Stop()
m.monitorRunning = false
// set mysqld status to UNKNOW
m.setStatus(model.MYSQLD_UNKNOW)
m.IncMonitorStops()
m.log.Info("mysqld[%v].monitor.stop...", m.conf.DefaultsFile)
}
func (m *Mysqld) setStatus(s model.MYSQLD_STATUS) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.status = s
}
func (m *Mysqld) getStatus() model.MYSQLD_STATUS {
m.mutex.RLock()
defer m.mutex.RUnlock()
return m.status
}
func (m *Mysqld) getMonitorInfo() string {
if m.monitorRunning {
return "ON"
}
return "OFF"
}
func (m *Mysqld) getMysqldInfo() string {
if m.monitorRunning {
return string(m.getStatus())
}
return "UNKNOW"
}