transactd 3.4.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CMakeLists.txt +2 -2
- data/bin/common/tdclc_32_3_5.dll +0 -0
- data/bin/common/tdclc_64_3_5.dll +0 -0
- data/build/common/options.cmake +12 -0
- data/build/common/transactd_cl_common.cmake +1 -0
- data/build/common/transactd_required.cmake +5 -0
- data/build/swig/ruby/tdclrb_wrap.cpp +1029 -130
- data/build/swig/tdcl.i +60 -5
- data/build/tdclc/CMakeLists.txt +30 -32
- data/build/tdclc/libtdclcm.map +1 -1
- data/build/tdclc/tdclc.cbproj +1 -1
- data/build/tdclc/tdclc.rc +4 -4
- data/build/tdclcpp/CMakeLists.txt +39 -48
- data/build/tdclcpp/tdclcpp.rc +4 -4
- data/build/tdclcpp/tdclcpp_bc.cbproj +4 -1
- data/build/tdclrb/CMakeLists.txt +5 -4
- data/build/tdclrb/tdclrb.rc +4 -4
- data/source/bzs/db/engine/mysql/database.cpp +45 -35
- data/source/bzs/db/engine/mysql/database.h +6 -8
- data/source/bzs/db/engine/mysql/dbManager.cpp +11 -0
- data/source/bzs/db/engine/mysql/dbManager.h +1 -0
- data/source/bzs/db/engine/mysql/ha.cpp +174 -0
- data/source/bzs/db/engine/mysql/ha.h +50 -0
- data/source/bzs/db/engine/mysql/mysqlInternal.h +18 -1
- data/source/bzs/db/engine/mysql/mysqlProtocol.cpp +222 -9
- data/source/bzs/db/engine/mysql/mysqlProtocol.h +5 -0
- data/source/bzs/db/protocol/tdap/client/client.cpp +23 -9
- data/source/bzs/db/protocol/tdap/client/client.h +125 -94
- data/source/bzs/db/protocol/tdap/client/connMgr.cpp +139 -30
- data/source/bzs/db/protocol/tdap/client/connMgr.h +40 -8
- data/source/bzs/db/protocol/tdap/client/database.cpp +17 -17
- data/source/bzs/db/protocol/tdap/client/database.h +15 -0
- data/source/bzs/db/protocol/tdap/client/dllmain.cpp +10 -4
- data/source/bzs/db/protocol/tdap/client/haNameResolver.cpp +486 -0
- data/source/bzs/db/protocol/tdap/client/haNameResolver.h +74 -0
- data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +102 -71
- data/source/bzs/db/protocol/tdap/client/nsDatabase.h +15 -3
- data/source/bzs/db/protocol/tdap/client/nsTable.cpp +2 -5
- data/source/bzs/db/protocol/tdap/client/nsTable.h +2 -1
- data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +2 -2
- data/source/bzs/db/protocol/tdap/client/table.cpp +1 -2
- data/source/bzs/db/protocol/tdap/client/trdboostapi.h +13 -0
- data/source/bzs/db/protocol/tdap/client/trnsctcl.def +1 -0
- data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +9 -7
- data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +2 -2
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +328 -117
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +7 -8
- data/source/bzs/db/protocol/tdap/tdapcapi.h +81 -41
- data/source/bzs/db/transactd/connManager.cpp +118 -93
- data/source/bzs/db/transactd/connManager.h +6 -1
- data/source/bzs/db/transactd/connectionRecord.h +27 -7
- data/source/bzs/db/transactd/transactd.cpp +24 -13
- data/source/bzs/env/crosscompile.h +2 -0
- data/source/bzs/netsvc/client/iconnection.h +2 -0
- data/source/bzs/netsvc/client/tcpClient.cpp +45 -14
- data/source/bzs/netsvc/client/tcpClient.h +21 -4
- data/source/bzs/netsvc/server/IAppModule.h +1 -0
- data/source/bzs/netsvc/server/serverCpt.cpp +1 -1
- data/source/bzs/netsvc/server/serverPipe.cpp +2 -0
- data/source/bzs/netsvc/server/serverTpool.cpp +3 -5
- data/source/bzs/test/tdclatl/test_v3.js +91 -3
- data/source/bzs/test/tdclphp/transactd_v3_Test.php +89 -3
- data/source/bzs/test/tdclrb/transactd_v3_spec.rb +69 -2
- data/source/bzs/test/trdclengn/testField.h +19 -1
- data/source/bzs/test/trdclengn/test_tdclcpp_ha.cpp +388 -0
- data/source/bzs/test/trdclengn/test_tdclcpp_v3.cpp +6 -1
- data/source/bzs/test/trdclengn/test_trdclengn.cpp +1 -0
- data/source/bzs/test/trdclengn/testbase.h +7 -1
- data/source/global/replication/haCommand.cpp +843 -0
- data/source/global/replication/haCommand.h +78 -0
- data/source/global/replication/haMgr.cpp +321 -0
- data/source/global/replication/replCommand.cpp +696 -0
- data/source/global/replication/replCommand.h +161 -0
- data/source/global/tdclatl/BinlogPos.cpp +10 -0
- data/source/global/tdclatl/BinlogPos.h +1 -0
- data/source/global/tdclatl/ConnMgr.cpp +89 -2
- data/source/global/tdclatl/ConnMgr.h +13 -1
- data/source/global/tdclatl/ConnRecord.cpp +8 -2
- data/source/global/tdclatl/ConnRecord.h +4 -3
- data/source/global/tdclatl/Database.cpp +13 -0
- data/source/global/tdclatl/Database.h +2 -0
- data/source/global/tdclatl/HaNameREsolver.cpp +54 -0
- data/source/global/tdclatl/HaNameREsolver.h +68 -0
- data/source/global/tdclatl/resource.h +0 -0
- data/source/global/tdclatl/tdclatl.idl +76 -5
- metadata +16 -6
- data/bin/common/tdclc_32_3_4.dll +0 -0
- data/bin/common/tdclc_64_3_4.dll +0 -0
- data/source/bzs/db/protocol/tdap/mysql/debuglog.cpp +0 -423
- data/source/bzs/db/protocol/tdap/mysql/debuglog.h +0 -116
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
#include "testField.h"
|
|
21
21
|
#include <bzs/db/protocol/tdap/fieldComp.h>
|
|
22
22
|
|
|
23
|
+
void init_commandLine(char* argv){};
|
|
24
|
+
|
|
23
25
|
class fixture
|
|
24
26
|
{
|
|
25
27
|
mutable database* m_db;
|
|
@@ -1056,11 +1058,14 @@ BOOST_AUTO_TEST_SUITE_END()
|
|
|
1056
1058
|
BOOST_AUTO_TEST_SUITE(tablelist)
|
|
1057
1059
|
BOOST_AUTO_TEST_CASE(tablelist)
|
|
1058
1060
|
{
|
|
1059
|
-
|
|
1061
|
+
testConnMgr();
|
|
1060
1062
|
}
|
|
1061
1063
|
BOOST_AUTO_TEST_CASE(createInfo)
|
|
1062
1064
|
{
|
|
1063
1065
|
testCreateInfo();
|
|
1064
1066
|
}
|
|
1065
1067
|
BOOST_AUTO_TEST_SUITE_END()
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1066
1071
|
// ------------------------------------------------------------------------
|
|
@@ -77,6 +77,9 @@ static bool use_mysqlNullMode = true;
|
|
|
77
77
|
|
|
78
78
|
boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]);
|
|
79
79
|
|
|
80
|
+
void init_commandLine(char* argv);
|
|
81
|
+
|
|
82
|
+
|
|
80
83
|
boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[])
|
|
81
84
|
{
|
|
82
85
|
for (int i = 1; i < argc; ++i)
|
|
@@ -115,7 +118,10 @@ boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[])
|
|
|
115
118
|
if (strstr(argv[i], "--nullfield=") == argv[i])
|
|
116
119
|
use_nullfield = atol(argv[i] + 12) != 0;
|
|
117
120
|
if (strstr(argv[i], "--mysqlnull=") == argv[i])
|
|
118
|
-
use_mysqlNullMode = atol(argv[i] + 12) != 0;
|
|
121
|
+
use_mysqlNullMode = atol(argv[i] + 12) != 0;
|
|
122
|
+
|
|
123
|
+
init_commandLine(argv[i]);
|
|
124
|
+
|
|
119
125
|
}
|
|
120
126
|
printf("Transactd test ... \nMay look like progress is stopped, \n"
|
|
121
127
|
"but it is such as record lock test, please wait.\n");
|
|
@@ -0,0 +1,843 @@
|
|
|
1
|
+
/*=================================================================
|
|
2
|
+
Copyright (C) 2016 BizStation Corp All rights reserved.
|
|
3
|
+
|
|
4
|
+
This program is free software; you can redistribute it and/or
|
|
5
|
+
modify it under the terms of the GNU General Public License
|
|
6
|
+
as published by the Free Software Foundation; either version 2
|
|
7
|
+
of the License, or (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
This program is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with this program; if not, write to the Free Software
|
|
16
|
+
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
17
|
+
02111-1307, USA.
|
|
18
|
+
=================================================================*/
|
|
19
|
+
#pragma hdrstop
|
|
20
|
+
#include "haCommand.h"
|
|
21
|
+
#include <vector>
|
|
22
|
+
#include <algorithm>
|
|
23
|
+
#pragma package(smart_init)
|
|
24
|
+
|
|
25
|
+
using namespace std;
|
|
26
|
+
using namespace bzs::db::protocol::tdap;
|
|
27
|
+
using namespace bzs::db::protocol::tdap::client;
|
|
28
|
+
|
|
29
|
+
#define SLAVES_SIZE 4096
|
|
30
|
+
|
|
31
|
+
void split(vector<_tstring>& ss, const _TCHAR* s)
|
|
32
|
+
{
|
|
33
|
+
const _TCHAR* p = s;
|
|
34
|
+
const _TCHAR* pp = _tcschr(p, _T(','));
|
|
35
|
+
while (pp)
|
|
36
|
+
{
|
|
37
|
+
ss.push_back(_tstring(p, pp));
|
|
38
|
+
p = pp + 1;
|
|
39
|
+
pp = _tcschr(p, _T(','));
|
|
40
|
+
}
|
|
41
|
+
size_t len = _tcslen(p);
|
|
42
|
+
if (len)
|
|
43
|
+
ss.push_back(_tstring(p, p + len));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#ifdef _UNICODE
|
|
47
|
+
inline void notify(haNotify* nf, int status, const wchar_t* msg)
|
|
48
|
+
{
|
|
49
|
+
if (nf) nf->onUpdateStaus(status, msg);
|
|
50
|
+
}
|
|
51
|
+
inline void notify(haNotify* nf, int status, const char* msg)
|
|
52
|
+
{
|
|
53
|
+
if (nf)
|
|
54
|
+
{
|
|
55
|
+
wchar_t wbuf[1024];
|
|
56
|
+
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, msg, -1, wbuf, 1024);
|
|
57
|
+
nf->onUpdateStaus(status, wbuf);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
#else
|
|
61
|
+
inline void notify(haNotify* nf, int status, const char* msg)
|
|
62
|
+
{
|
|
63
|
+
if (nf) nf->onUpdateStaus(status, msg);
|
|
64
|
+
}
|
|
65
|
+
#endif
|
|
66
|
+
inline void notify(haNotify* nf, int status, binlogPos& bpos)
|
|
67
|
+
{
|
|
68
|
+
if (nf)
|
|
69
|
+
{
|
|
70
|
+
char buf[2048];
|
|
71
|
+
sprintf_s(buf, 1024, "%s:%llu %s",bpos.filename, bpos.pos, bpos.gtid);
|
|
72
|
+
notify(nf, status, buf);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
inline void nfSetHostName(haNotify* nf, const _TCHAR* host)
|
|
77
|
+
{
|
|
78
|
+
if (nf) nf->setHostName(host);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
database_ptr createDb(const _TCHAR* host, const _TCHAR* user, const _TCHAR* passwd, bool newConnection)
|
|
82
|
+
{
|
|
83
|
+
connectParams cp(_T("tdap"), host, _T("mysql"),
|
|
84
|
+
NULL, user, passwd);
|
|
85
|
+
database_ptr db = createDatabaseObject();
|
|
86
|
+
if (db->connect(cp.uri(), newConnection))
|
|
87
|
+
db->open(cp.uri(), cp.type(), cp.mode());
|
|
88
|
+
return db;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
connMgr_ptr getMasterMgr(database_ptr db, const node& nd)
|
|
92
|
+
{
|
|
93
|
+
connMgr_ptr mgr = createConnMgr(db.get());
|
|
94
|
+
connectParams cp(_T("tdap"), nd.host.c_str(),
|
|
95
|
+
_T(""), NULL, nd.user.c_str(), nd.passwd.c_str());
|
|
96
|
+
mgr->connect(cp.uri());
|
|
97
|
+
validateStatus(mgr, _T("getMasterMgr"));
|
|
98
|
+
return mgr;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
_TCHAR* getHost(_TCHAR* hostStatus)
|
|
102
|
+
{
|
|
103
|
+
_TCHAR* p = _tcschr(hostStatus, _T('\t'));
|
|
104
|
+
if (p) *p = 0x00;
|
|
105
|
+
return hostStatus;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_TCHAR* slaveList(connMgr_ptr& mgr, _TCHAR* slaves)
|
|
109
|
+
{ // auto listup slave hosts from masetr
|
|
110
|
+
|
|
111
|
+
const connMgr::records& recs = mgr->slaveHosts();
|
|
112
|
+
validateStatus(mgr, _T("slaveHost"));
|
|
113
|
+
_TCHAR tmp[MAX_PATH];
|
|
114
|
+
if (recs.size())
|
|
115
|
+
_tcscpy_s(slaves, SLAVES_SIZE, getHost((_TCHAR*)recs[0].value(tmp, MAX_PATH)));
|
|
116
|
+
for (size_t i = 1; i < recs.size(); ++i)
|
|
117
|
+
{
|
|
118
|
+
_tcscat_s(slaves, SLAVES_SIZE, _T(","));
|
|
119
|
+
_tcscat_s(slaves, SLAVES_SIZE, getHost((_TCHAR*)recs[i].value(tmp, MAX_PATH)));
|
|
120
|
+
}
|
|
121
|
+
return slaves;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
int readHaVar(connMgr_ptr& mgr)
|
|
125
|
+
{
|
|
126
|
+
const connMgr::records& recs = mgr->statusvars();
|
|
127
|
+
int ha = HA_ROLE_SLAVE;
|
|
128
|
+
if (recs.size() > TD_SVAR_HA)
|
|
129
|
+
ha = (int)recs[TD_SVAR_HA].longValue;
|
|
130
|
+
return ha;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bool isEnableFailOver(int ha)
|
|
134
|
+
{
|
|
135
|
+
return (ha & HA_ENABLE_FAILOVER) == HA_ENABLE_FAILOVER;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
bool isRoleMaster(int ha)
|
|
139
|
+
{
|
|
140
|
+
return (ha & HA_ROLE_MASTER) == HA_ROLE_MASTER;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
bool isRoleMaster(connMgr_ptr& mgr)
|
|
144
|
+
{
|
|
145
|
+
return isRoleMaster(readHaVar(mgr));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
void makeSlaveList(const failOverParam& pm, bool* roleMaster=NULL)
|
|
149
|
+
{
|
|
150
|
+
database_ptr db = createDatabaseObject();
|
|
151
|
+
connMgr_ptr mgr = getMasterMgr(db, pm.master);
|
|
152
|
+
|
|
153
|
+
_TCHAR slaves[SLAVES_SIZE] = {0};
|
|
154
|
+
slaveList(mgr, slaves);
|
|
155
|
+
pm.slaves = slaves;
|
|
156
|
+
if (roleMaster)
|
|
157
|
+
*roleMaster = isRoleMaster(mgr);
|
|
158
|
+
mgr.reset();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
void getBinlogPos(connMgr_ptr mgr, binlogPos& bpos)
|
|
162
|
+
{
|
|
163
|
+
const connMgr::records& rs = mgr->extendedvars();
|
|
164
|
+
validateStatus(mgr, _T("extendedvars"));
|
|
165
|
+
if (rs.size() > TD_EXTENDED_VAR_BINLOG_GTID)
|
|
166
|
+
{
|
|
167
|
+
strcpy_s(bpos.filename, BINLOGNAME_SIZE, rs[TD_EXTENDED_VAR_BINLOG_FILE].name);
|
|
168
|
+
bpos.pos = (unsigned int)rs[TD_EXTENDED_VAR_BINLOG_POS].longValue;
|
|
169
|
+
bpos.setGtid(rs[TD_EXTENDED_VAR_BINLOG_GTID].value_ptr());
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
bool isMariadb(database_ptr db)
|
|
174
|
+
{
|
|
175
|
+
btrVersions vers;
|
|
176
|
+
db->getBtrVersion(&vers);
|
|
177
|
+
validateStatus(db, _T("isMariadb"));
|
|
178
|
+
btrVersion ver = vers.versions[VER_IDX_DB_SERVER];
|
|
179
|
+
return ver.isMariaDB();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
string getChannlName(connMgr_ptr mgr, const _TCHAR* oldMaster)
|
|
183
|
+
{
|
|
184
|
+
connRecords_ptr recs_p = createConnRecords(mgr->channels());
|
|
185
|
+
connMgr::records& recs = *recs_p.get();
|
|
186
|
+
|
|
187
|
+
for (size_t i = 0;i < recs.size(); ++i)
|
|
188
|
+
{
|
|
189
|
+
const connMgr::records& rs = mgr->slaveStatus(recs[i].name);
|
|
190
|
+
if (rs.size() > SLAVE_STATUS_MASTER_HOST)
|
|
191
|
+
{
|
|
192
|
+
_TCHAR buf[MAX_PATH];
|
|
193
|
+
if (_tcsicmp(rs[SLAVE_STATUS_MASTER_HOST].value(buf, MAX_PATH), oldMaster) == 0)
|
|
194
|
+
return recs[i].name;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return "";
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
void changeMaster(const node& nd, const masterNode& master, database_ptr db,
|
|
201
|
+
connMgr_ptr mgr, binlogPos* bpos, haNotify* nf)
|
|
202
|
+
{
|
|
203
|
+
_TCHAR host[MAX_PATH];
|
|
204
|
+
_TCHAR port[20];
|
|
205
|
+
endPoint(db->uri(), host, MAX_PATH, port, 20);
|
|
206
|
+
if (port[0])
|
|
207
|
+
{
|
|
208
|
+
_tcscat_s(host, MAX_PATH -_tcslen(host), _T(":"));
|
|
209
|
+
_tcscat_s(host, MAX_PATH -_tcslen(host), port);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
replicationParam pm;
|
|
213
|
+
pm.master = master;
|
|
214
|
+
pm.type = isMariadb(db) ? REP_TYPE_GTID_MA : REP_TYPE_GTID_MY;
|
|
215
|
+
pm.master.channel = getChannlName(mgr, nd.host.c_str());
|
|
216
|
+
|
|
217
|
+
nfSetHostName(nf, host);
|
|
218
|
+
notify(nf, HA_NF_CANNELNAME, pm.master.channel.c_str());
|
|
219
|
+
replSlave rpl(db, pm, mgr.get());
|
|
220
|
+
rpl.stop(all);
|
|
221
|
+
notify(nf, HA_SLAVE_STOP_ALL, _T(""));
|
|
222
|
+
if (bpos)
|
|
223
|
+
{
|
|
224
|
+
rpl.changeMaster(bpos);
|
|
225
|
+
notify(nf, HA_CHANGE_MASTER, bpos->gtid);
|
|
226
|
+
}
|
|
227
|
+
else
|
|
228
|
+
{
|
|
229
|
+
rpl.switchMaster(replSlave::slave_pos);
|
|
230
|
+
notify(nf, HA_SWITCH_MASTER, "slave_pos");
|
|
231
|
+
}
|
|
232
|
+
rpl.start();
|
|
233
|
+
notify(nf, HA_SLAVE_START, _T(""));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
connMgr_ptr createMgr(database_ptr db, const _TCHAR* host, const node& nd, bool throwError)
|
|
237
|
+
{
|
|
238
|
+
connectParams cp(_T("tdap"), host, _T(""), NULL,
|
|
239
|
+
nd.user.c_str(), nd.passwd.c_str());
|
|
240
|
+
|
|
241
|
+
connMgr_ptr mgr = createConnMgr(db.get());
|
|
242
|
+
if (!mgr->connect(cp.uri()))
|
|
243
|
+
{
|
|
244
|
+
if (throwError)
|
|
245
|
+
validateStatus(mgr, _T("connMgr connect"));
|
|
246
|
+
}
|
|
247
|
+
return mgr;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
class safeHaSalves
|
|
251
|
+
{
|
|
252
|
+
vector<connMgr_ptr> m_mgrs;
|
|
253
|
+
vector<_tstring>& m_slaves;
|
|
254
|
+
vector<database_ptr> m_dbs;
|
|
255
|
+
const string& m_channel;
|
|
256
|
+
const node& m_nd;
|
|
257
|
+
haNotify* m_nf;
|
|
258
|
+
size_t m_lockSize;
|
|
259
|
+
bool m_isSwitchOver;
|
|
260
|
+
bool m_isDisableOldMasterToSalve;
|
|
261
|
+
bool m_oldMasterRoleChanged;
|
|
262
|
+
bool m_newMasterRoleChanged;
|
|
263
|
+
|
|
264
|
+
void addMgr(const _TCHAR* host)
|
|
265
|
+
{
|
|
266
|
+
database_ptr db = createDatabaseObject();
|
|
267
|
+
m_dbs.push_back(db);
|
|
268
|
+
m_mgrs.push_back(createMgr(db, host, m_nd, m_isSwitchOver));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
void createMgrList()
|
|
272
|
+
{
|
|
273
|
+
for (size_t i= 0; i< m_slaves.size(); ++i)
|
|
274
|
+
addMgr(m_slaves[i].c_str());
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
void addDbs(vector<database_ptr>& dbs, const _TCHAR* host, bool newConnection)
|
|
278
|
+
{
|
|
279
|
+
database_ptr db = createDb(host, m_nd.user.c_str(), m_nd.passwd.c_str(), newConnection);
|
|
280
|
+
if (m_isSwitchOver)
|
|
281
|
+
validateStatus(db, _T("database connect open"));
|
|
282
|
+
dbs.push_back(db);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
void createDbList(vector<database_ptr>& dbs)
|
|
286
|
+
{
|
|
287
|
+
for (size_t i= 0; i< m_slaves.size(); ++i)
|
|
288
|
+
addDbs(dbs, m_slaves[i].c_str(), false);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
void doChangeMaster(const masterNode& master, database_ptr db,
|
|
292
|
+
connMgr_ptr mgr, binlogPos* bpos)
|
|
293
|
+
{
|
|
294
|
+
::changeMaster(m_nd, master, db, mgr, bpos, m_nf);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
void setMasterRoleStatus(connMgr_ptr mgr)
|
|
298
|
+
{
|
|
299
|
+
mgr->setRole(HA_ROLE_MASTER);
|
|
300
|
+
validateStatus(mgr, _T("setRole"));
|
|
301
|
+
m_newMasterRoleChanged = true;
|
|
302
|
+
if (!m_isSwitchOver || m_isDisableOldMasterToSalve)
|
|
303
|
+
m_oldMasterRoleChanged = true;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
void promoteMaster(const masterNode& master, database_ptr db, connMgr_ptr mgr,
|
|
307
|
+
binlogPos* bpos, bool readOnlyControl)
|
|
308
|
+
{
|
|
309
|
+
replicationParam pm;
|
|
310
|
+
pm.master = master;
|
|
311
|
+
pm.type = isMariadb(db) ? REP_TYPE_GTID_MA : REP_TYPE_GTID_MY;
|
|
312
|
+
if (m_isSwitchOver)
|
|
313
|
+
{
|
|
314
|
+
pm.master.channel = getChannlName(mgr, m_nd.host.c_str());
|
|
315
|
+
const_cast<masterNode&>(master).channel = pm.master.channel;
|
|
316
|
+
}
|
|
317
|
+
else
|
|
318
|
+
pm.master.channel = m_channel;
|
|
319
|
+
|
|
320
|
+
nfSetHostName(m_nf, master.host.c_str());
|
|
321
|
+
notify(m_nf, HA_NF_PROMOTE_MASTER, _T(""));
|
|
322
|
+
notify(m_nf, HA_NF_PROMOTE_CHANNEL, m_channel.c_str());
|
|
323
|
+
|
|
324
|
+
replSlave rpl(db, pm, mgr.get());
|
|
325
|
+
|
|
326
|
+
rpl.stop(one);
|
|
327
|
+
setMasterRoleStatus(mgr);
|
|
328
|
+
notify(m_nf, HA_NF_ROLE_MASTER, _T(""));
|
|
329
|
+
if (bpos)
|
|
330
|
+
{ // Sync SQLthread binlog pos to old master
|
|
331
|
+
rpl.startUntil(*bpos);
|
|
332
|
+
notify(m_nf, HA_NF_WAIT_POS_START, _T(""));
|
|
333
|
+
rpl.waitForSlaveSync(*bpos, 2, NULL);
|
|
334
|
+
notify(m_nf, HA_NF_WAIT_POS_COMP, *bpos);
|
|
335
|
+
|
|
336
|
+
rpl.stop(one);
|
|
337
|
+
notify(m_nf, HA_SLAVE_STOP, _T(""));
|
|
338
|
+
}
|
|
339
|
+
rpl.resetAll(); // reset only this channel
|
|
340
|
+
if (readOnlyControl)
|
|
341
|
+
{
|
|
342
|
+
db->execSql("set global read_only=OFF");
|
|
343
|
+
validateStatus(db, _T("read_only off"));
|
|
344
|
+
notify(m_nf, HA_SET_READ_ONLY, _T(""));
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
public:
|
|
349
|
+
|
|
350
|
+
safeHaSalves(vector<_tstring>& slaves, const failOverParam& pm, haNotify* nf) :
|
|
351
|
+
m_slaves(slaves), m_channel(pm.newMaster.channel),
|
|
352
|
+
m_nd(pm.master), m_nf(nf), m_lockSize(0),
|
|
353
|
+
m_isSwitchOver(pm.isSwitchOver()),
|
|
354
|
+
m_isDisableOldMasterToSalve(pm.isDisableOldMasterToSalve()),
|
|
355
|
+
m_oldMasterRoleChanged(false),
|
|
356
|
+
m_newMasterRoleChanged(false)
|
|
357
|
+
{
|
|
358
|
+
createMgrList();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
void lock()
|
|
362
|
+
{
|
|
363
|
+
m_lockSize = m_mgrs.size();
|
|
364
|
+
for (size_t i = 0; i < m_lockSize; ++i)
|
|
365
|
+
{
|
|
366
|
+
if (m_mgrs[i]->isOpen())
|
|
367
|
+
{
|
|
368
|
+
m_mgrs[i]->haLock();
|
|
369
|
+
validateStatus(m_mgrs[i], _T("haLock"));
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
int selectPromoteHost()
|
|
375
|
+
{
|
|
376
|
+
string fname;
|
|
377
|
+
unsigned int pos = 0;
|
|
378
|
+
int index = -1;
|
|
379
|
+
for (int i = 0; i < (int)m_mgrs.size(); ++i)
|
|
380
|
+
{
|
|
381
|
+
if (m_mgrs[i]->isOpen())
|
|
382
|
+
{
|
|
383
|
+
const connMgr::records& rss = m_mgrs[i]->statusvars();
|
|
384
|
+
if (rss.size() > TD_SVAR_HA)
|
|
385
|
+
{
|
|
386
|
+
int ha = (int)rss[TD_SVAR_HA].longValue;
|
|
387
|
+
if ((ha & HA_ENABLE_FAILOVER) != HA_ENABLE_FAILOVER)
|
|
388
|
+
return -2;
|
|
389
|
+
}
|
|
390
|
+
const connMgr::records& rs = m_mgrs[i]->slaveStatus(m_channel.c_str());
|
|
391
|
+
if (m_mgrs[i]->stat() == 0)
|
|
392
|
+
{
|
|
393
|
+
string tmp = rs[SLAVE_STATUS_MASTER_LOG_FILE].name;
|
|
394
|
+
unsigned int tmpPos = (unsigned int)rs[SLAVE_STATUS_EXEC_MASTER_LOG_POS].longValue;
|
|
395
|
+
if (tmp > fname)
|
|
396
|
+
{
|
|
397
|
+
fname = tmp;
|
|
398
|
+
pos = tmpPos;
|
|
399
|
+
index = i;
|
|
400
|
+
}else if(tmp == fname)
|
|
401
|
+
{
|
|
402
|
+
if (tmpPos > pos)
|
|
403
|
+
{
|
|
404
|
+
pos = tmpPos;
|
|
405
|
+
index = i;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return index;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
void changeMaster(const masterNode& master, size_t newMasterIndex, binlogPos* bpos,
|
|
415
|
+
bool readOnlyControl )
|
|
416
|
+
{
|
|
417
|
+
vector<database_ptr> dbs;
|
|
418
|
+
createDbList(dbs);
|
|
419
|
+
if (dbs.size() == 0) return;
|
|
420
|
+
// First promote new master
|
|
421
|
+
promoteMaster(master, dbs[newMasterIndex],
|
|
422
|
+
m_mgrs[newMasterIndex], bpos, readOnlyControl);
|
|
423
|
+
if (m_isSwitchOver && !m_isDisableOldMasterToSalve)
|
|
424
|
+
{
|
|
425
|
+
// The old master change to slave.
|
|
426
|
+
addMgr(m_nd.host.c_str()); //Append old master.
|
|
427
|
+
vector<connMgr_ptr>::iterator itmgr = m_mgrs.end() -1;
|
|
428
|
+
database_ptr db = createDb(m_nd.host.c_str(), m_nd.user.c_str(), m_nd.passwd.c_str(), true);
|
|
429
|
+
doChangeMaster(master, db, *itmgr, bpos);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
//Slaves change master.
|
|
433
|
+
for (size_t i = 0; i < dbs.size(); ++i)
|
|
434
|
+
{
|
|
435
|
+
if (i != newMasterIndex && dbs[i]->isOpened())
|
|
436
|
+
doChangeMaster(master, dbs[i], m_mgrs[i], NULL);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
void setEnableFailOver(bool v)
|
|
441
|
+
{
|
|
442
|
+
for (size_t i = 0; i < m_mgrs.size(); ++i)
|
|
443
|
+
{
|
|
444
|
+
if (m_mgrs[i]->isOpen())
|
|
445
|
+
{
|
|
446
|
+
m_mgrs[i]->setEnableFailover(v);
|
|
447
|
+
validateStatus(m_mgrs[i], _T("setEnableFailOver"));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
connMgr_ptr mgr(size_t index) { return m_mgrs[index];}
|
|
453
|
+
|
|
454
|
+
void setOldMasterRoleChanged() {m_oldMasterRoleChanged = true;}
|
|
455
|
+
|
|
456
|
+
void recoverMasterRole()
|
|
457
|
+
{
|
|
458
|
+
try
|
|
459
|
+
{
|
|
460
|
+
if (m_newMasterRoleChanged != m_oldMasterRoleChanged)
|
|
461
|
+
{
|
|
462
|
+
database_ptr db = createDatabaseObject();
|
|
463
|
+
connMgr_ptr mgr = createMgr(db, m_nd.host.c_str(), m_nd, m_isSwitchOver);
|
|
464
|
+
mgr->setRole(HA_ROLE_MASTER);
|
|
465
|
+
mgr.reset();
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch(...){}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
void unlock()
|
|
472
|
+
{
|
|
473
|
+
if (m_lockSize)
|
|
474
|
+
{
|
|
475
|
+
for (int i = (int)m_lockSize - 1; i >= 0 ; --i)
|
|
476
|
+
{
|
|
477
|
+
if (m_mgrs[i]->isOpen())
|
|
478
|
+
m_mgrs[i]->haUnlock();
|
|
479
|
+
}
|
|
480
|
+
m_lockSize = 0;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
~safeHaSalves()
|
|
485
|
+
{
|
|
486
|
+
unlock();
|
|
487
|
+
recoverMasterRole();
|
|
488
|
+
m_mgrs.clear();
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
class masterControl
|
|
493
|
+
{
|
|
494
|
+
database_ptr m_db;
|
|
495
|
+
connMgr_ptr m_mgr;
|
|
496
|
+
const node& m_nd;
|
|
497
|
+
bool m_locked;
|
|
498
|
+
|
|
499
|
+
void trxLock()
|
|
500
|
+
{
|
|
501
|
+
m_mgr->setTrxBlock(true);
|
|
502
|
+
validateStatus(m_mgr, _T("Master trx lock"));
|
|
503
|
+
m_locked = true;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
void trxUnlock()
|
|
507
|
+
{
|
|
508
|
+
if (m_locked)
|
|
509
|
+
m_mgr->setTrxBlock(false);
|
|
510
|
+
m_locked = false;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
public:
|
|
514
|
+
masterControl(const node& nd) : m_nd(nd), m_locked(false)
|
|
515
|
+
{
|
|
516
|
+
m_db = createDatabaseObject();
|
|
517
|
+
m_mgr = getMasterMgr(m_db, nd);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
~masterControl()
|
|
521
|
+
{
|
|
522
|
+
trxUnlock();
|
|
523
|
+
m_mgr.reset();
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
void waitForFinishTrx(binlogPos& bpos)
|
|
527
|
+
{
|
|
528
|
+
trxLock();
|
|
529
|
+
bool cancel = false;
|
|
530
|
+
int trx_count;
|
|
531
|
+
size_t use_db_count;
|
|
532
|
+
//connMgr::records recs;
|
|
533
|
+
connRecords_ptr recs_p = createConnRecords();
|
|
534
|
+
connMgr::records& recs = *recs_p.get();
|
|
535
|
+
do
|
|
536
|
+
{
|
|
537
|
+
trx_count = 0;
|
|
538
|
+
use_db_count = 0;
|
|
539
|
+
recs = m_mgr->connections();
|
|
540
|
+
for (size_t i = 0; i < recs.size(); ++i)
|
|
541
|
+
{
|
|
542
|
+
Sleep(1);
|
|
543
|
+
int trx_per_connection = 0;
|
|
544
|
+
size_t use_db_per_connection = 0;
|
|
545
|
+
const connMgr::records& rs = m_mgr->inUseDatabases(recs[i].conId);
|
|
546
|
+
for (size_t j = 0 ;j < rs.size(); ++j)
|
|
547
|
+
{
|
|
548
|
+
trx_per_connection += rs[j].inTransaction;
|
|
549
|
+
trx_count += trx_per_connection;
|
|
550
|
+
}
|
|
551
|
+
use_db_count += rs.size();
|
|
552
|
+
use_db_per_connection = rs.size();
|
|
553
|
+
// Killing connection that using database and no transactions.
|
|
554
|
+
if (trx_per_connection == 0 && use_db_per_connection)
|
|
555
|
+
m_mgr->postDisconnectOne(recs[i].conId);
|
|
556
|
+
}
|
|
557
|
+
}while ((trx_count != 0 || use_db_count != 0) && !cancel);
|
|
558
|
+
|
|
559
|
+
getBinlogPos(m_mgr, bpos);
|
|
560
|
+
|
|
561
|
+
trxUnlock();
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
bool setRole(int v)
|
|
565
|
+
{
|
|
566
|
+
m_mgr->setRole(v);
|
|
567
|
+
validateStatus(m_mgr, _T("setRole"));
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
class masterReadOnly
|
|
573
|
+
{
|
|
574
|
+
database_ptr m_db;
|
|
575
|
+
public:
|
|
576
|
+
masterReadOnly(const node& nd, bool toReadOnly)
|
|
577
|
+
{
|
|
578
|
+
if (toReadOnly)
|
|
579
|
+
{
|
|
580
|
+
m_db = createDb(nd.host.c_str(), nd.user.c_str(), nd.passwd.c_str(), true);
|
|
581
|
+
//db->execSql("flush tables with read lock");
|
|
582
|
+
//validateStatus(db, _T("flush tables"));
|
|
583
|
+
m_db->execSql("set global read_only=ON");
|
|
584
|
+
validateStatus(m_db, _T("read_only ON"));
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
void check()
|
|
588
|
+
{
|
|
589
|
+
m_db.reset();
|
|
590
|
+
}
|
|
591
|
+
~masterReadOnly()
|
|
592
|
+
{
|
|
593
|
+
if (m_db)
|
|
594
|
+
m_db->execSql("set global read_only=OFF");
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
string getNewMasterPort(const string& host, const string& map)
|
|
599
|
+
{
|
|
600
|
+
char tmp[MAX_PATH];
|
|
601
|
+
char* p;
|
|
602
|
+
strcpy_s(tmp, sizeof(tmp), host.c_str());
|
|
603
|
+
p = strchr(tmp, ':');
|
|
604
|
+
if (p)
|
|
605
|
+
{
|
|
606
|
+
++p;
|
|
607
|
+
strcat_s(p, sizeof(tmp) - (p - tmp), ":");
|
|
608
|
+
size_t pos = map.find(p);
|
|
609
|
+
if (pos != string::npos)
|
|
610
|
+
{
|
|
611
|
+
int n = atol(map.c_str() + pos + strlen(p));
|
|
612
|
+
_ltoa_s(n, tmp, sizeof(tmp), 10);
|
|
613
|
+
return tmp;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return "3306";
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
void doSwitchOrver(const failOverParam& pm, haNotify* nf)
|
|
620
|
+
{
|
|
621
|
+
vector<_tstring> slaves;
|
|
622
|
+
slaves.reserve(10);
|
|
623
|
+
overrideCompatibleMode cpblMode(database::CMP_MODE_MYSQL_NULL);
|
|
624
|
+
size_t newMasterIndex;
|
|
625
|
+
if (pm.slaves == _T(""))
|
|
626
|
+
THROW_BZS_ERROR_WITH_MSG(_T("No slave host(s)."));
|
|
627
|
+
split(slaves, pm.slaves.c_str());
|
|
628
|
+
if (pm.isSwitchOver())
|
|
629
|
+
{
|
|
630
|
+
vector<_tstring>::iterator it = find(slaves.begin(), slaves.end(), pm.newMaster.host);
|
|
631
|
+
newMasterIndex = it - slaves.begin();
|
|
632
|
+
}
|
|
633
|
+
binlogPos* bpos_ptr = NULL;
|
|
634
|
+
binlogPos bpos;
|
|
635
|
+
bool readOnlyControl = (pm.option & OPT_READONLY_CONTROL) != 0;
|
|
636
|
+
|
|
637
|
+
nfSetHostName(nf, _T(""));
|
|
638
|
+
notify(nf, HA_NF_SLAVE_LIST, pm.slaves.c_str());
|
|
639
|
+
safeHaSalves slvs(slaves, pm, nf);
|
|
640
|
+
slvs.lock();
|
|
641
|
+
if (pm.isSwitchOver())
|
|
642
|
+
{
|
|
643
|
+
masterReadOnly read_only(pm.master, readOnlyControl);
|
|
644
|
+
{
|
|
645
|
+
masterControl oldMaster(pm.master);
|
|
646
|
+
// block new connection to old master
|
|
647
|
+
if (oldMaster.setRole(HA_ROLE_SLAVE))
|
|
648
|
+
{
|
|
649
|
+
slvs.setOldMasterRoleChanged();
|
|
650
|
+
nfSetHostName(nf, pm.master.host.c_str());
|
|
651
|
+
notify(nf, HA_NF_ROLE_SLAVE, _T(""));
|
|
652
|
+
}
|
|
653
|
+
// wait for current transaction
|
|
654
|
+
notify(nf, HA_NF_WAIT_TRX_START, _T(""));
|
|
655
|
+
oldMaster.waitForFinishTrx(bpos);
|
|
656
|
+
notify(nf, HA_NF_WAIT_TRX_COMP, bpos);
|
|
657
|
+
bpos_ptr = &bpos;
|
|
658
|
+
// release master trx lock
|
|
659
|
+
}
|
|
660
|
+
read_only.check();
|
|
661
|
+
}else if (pm.isFailOver())
|
|
662
|
+
{
|
|
663
|
+
int index = slvs.selectPromoteHost();
|
|
664
|
+
if (index < 0 || index >= (int)slaves.size())
|
|
665
|
+
{
|
|
666
|
+
if (index == -2)
|
|
667
|
+
THROW_BZS_ERROR_WITH_MSG(_T("Failover is disabled."));
|
|
668
|
+
else
|
|
669
|
+
THROW_BZS_ERROR_WITH_MSG(_T("Invalid new Master."));
|
|
670
|
+
}
|
|
671
|
+
newMasterIndex = (size_t)index;
|
|
672
|
+
failOverParam& mp = const_cast<failOverParam&>(pm);
|
|
673
|
+
mp.newMaster.host = slaves[newMasterIndex];
|
|
674
|
+
mp.newMaster.repPort = getNewMasterPort(toUtf8(pm.newMaster.host), pm.portMap);
|
|
675
|
+
}
|
|
676
|
+
slvs.changeMaster(pm.newMaster, newMasterIndex, bpos_ptr, readOnlyControl);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
void failOrver(const failOverParam& pm, haNotify* nf)
|
|
680
|
+
{
|
|
681
|
+
pm.option |= OPT_FO_FAILOVER;
|
|
682
|
+
pm.option &= ~OPT_SO_AUTO_SLVAE_LIST;
|
|
683
|
+
doSwitchOrver(pm, nf);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
void switchOrver(const failOverParam& pm, haNotify* nf)
|
|
687
|
+
{
|
|
688
|
+
if (pm.option & OPT_SO_AUTO_SLVAE_LIST)
|
|
689
|
+
makeSlaveList(pm);
|
|
690
|
+
pm.option &= ~OPT_FO_FAILOVER;
|
|
691
|
+
doSwitchOrver(pm, nf);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
void demoteToSlave(const failOverParam& pm, haNotify* nf)
|
|
695
|
+
{
|
|
696
|
+
overrideCompatibleMode cpblMode(database::CMP_MODE_MYSQL_NULL);
|
|
697
|
+
database_ptr dbt = createDb(pm.master.host.c_str(), pm.master.user.c_str(),
|
|
698
|
+
pm.master.passwd.c_str(), false);
|
|
699
|
+
nfSetHostName(nf, pm.master.host.c_str());
|
|
700
|
+
database_ptr db = createDatabaseObject();
|
|
701
|
+
connMgr_ptr mgr = getMasterMgr(db, pm.master);
|
|
702
|
+
|
|
703
|
+
mgr->setRole(HA_ROLE_SLAVE);
|
|
704
|
+
validateStatus(mgr, _T("setRoleMaster"));
|
|
705
|
+
notify(nf, HA_NF_ROLE_SLAVE, _T(""));
|
|
706
|
+
changeMaster(pm.master, pm.newMaster, dbt, mgr, NULL, nf);
|
|
707
|
+
mgr.reset();
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
void setEnableFailOver(const failOverParam& pm, bool v)
|
|
711
|
+
{
|
|
712
|
+
if (pm.option & OPT_SO_AUTO_SLVAE_LIST)
|
|
713
|
+
makeSlaveList(pm);
|
|
714
|
+
vector<_tstring> slaves;
|
|
715
|
+
split(slaves, pm.slaves.c_str());
|
|
716
|
+
pm.option &= ~OPT_FO_FAILOVER;
|
|
717
|
+
safeHaSalves slvs(slaves, pm, NULL);
|
|
718
|
+
slvs.setEnableFailOver(v);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
void setServerRole(const failOverParam& pm, int v)
|
|
722
|
+
{
|
|
723
|
+
masterControl srv(pm.master);
|
|
724
|
+
srv.setRole(v);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const _TCHAR* roleName(bool isMaster)
|
|
728
|
+
{
|
|
729
|
+
return isMaster ? _T("Role = Master") : _T("Role = Slave");
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
void notifyBrank(haNotify* nf)
|
|
733
|
+
{
|
|
734
|
+
nfSetHostName(nf, _T(""));
|
|
735
|
+
notify(nf, HA_NF_BLANK, _T(""));
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
bool lockTest(connMgr_ptr mgr, haNotify* nf)
|
|
739
|
+
{
|
|
740
|
+
bool lock = mgr->haLock();
|
|
741
|
+
if (lock)
|
|
742
|
+
mgr->haUnlock();
|
|
743
|
+
notify(nf, lock ? HA_NF_MSG_OK : HA_NF_MSG_NG, "HA lock");
|
|
744
|
+
return lock;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
int healthCheck(const failOverParam& pm, haNotify* nf)
|
|
748
|
+
{
|
|
749
|
+
int ret = 0;
|
|
750
|
+
overrideCompatibleMode cpblMode(database::CMP_MODE_MYSQL_NULL);
|
|
751
|
+
bool roleMaster;
|
|
752
|
+
|
|
753
|
+
vector<_tstring> slaves_param;
|
|
754
|
+
split(slaves_param, pm.slaves.c_str());
|
|
755
|
+
|
|
756
|
+
makeSlaveList(pm, &roleMaster);
|
|
757
|
+
vector<_tstring> slaves;
|
|
758
|
+
split(slaves, pm.slaves.c_str());
|
|
759
|
+
nfSetHostName(nf, _T(""));
|
|
760
|
+
if (slaves_param.size())
|
|
761
|
+
{
|
|
762
|
+
vector<_tstring> slaves_tmp = slaves;
|
|
763
|
+
if (slaves_param.size() != slaves_tmp.size())
|
|
764
|
+
{
|
|
765
|
+
_TCHAR tmp[256];
|
|
766
|
+
_stprintf_s(tmp, 256 ,_T("slaves count(%u) not equal real slave count(%u)"),
|
|
767
|
+
(unsigned int)slaves_param.size(), (unsigned int)slaves_tmp.size());
|
|
768
|
+
notify(nf, HA_NF_BLANK, tmp);
|
|
769
|
+
++ret;
|
|
770
|
+
}
|
|
771
|
+
std::sort(slaves_param.begin(), slaves_param.end());
|
|
772
|
+
std::sort(slaves_tmp.begin(), slaves_tmp.end());
|
|
773
|
+
size_t n = min(slaves_param.size(), slaves_tmp.size());
|
|
774
|
+
for (size_t i = 0; i < n; ++i)
|
|
775
|
+
{
|
|
776
|
+
if (slaves_param[i] != slaves_tmp[i])
|
|
777
|
+
{
|
|
778
|
+
_TCHAR tmp[1024];
|
|
779
|
+
_stprintf_s(tmp, 1024 ,_T("Unmatch host name beetween the command line and slaveHosts of master.")
|
|
780
|
+
_T("\n command line=%s : master detect=%s"),
|
|
781
|
+
slaves_param[i].c_str(), slaves_tmp[i].c_str());
|
|
782
|
+
notify(nf, HA_NF_BLANK, tmp);
|
|
783
|
+
++ret;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
notify(nf, HA_NF_SLAVE_LIST, pm.slaves.c_str());
|
|
789
|
+
nfSetHostName(nf, pm.master.host.c_str());
|
|
790
|
+
notify(nf, roleMaster ? HA_NF_MSG_OK : HA_NF_MSG_NG, roleName(roleMaster));
|
|
791
|
+
if (!roleMaster) ++ret;
|
|
792
|
+
|
|
793
|
+
{ //master lock test
|
|
794
|
+
database_ptr db = createDatabaseObject();
|
|
795
|
+
connMgr_ptr mgr = createMgr(db, pm.master.host.c_str(), pm.master, false);
|
|
796
|
+
if (!lockTest(mgr, nf)) ++ret;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
for (size_t i=0;i < slaves.size(); ++i)
|
|
800
|
+
{
|
|
801
|
+
database_ptr db = createDatabaseObject();
|
|
802
|
+
connMgr_ptr mgr = createMgr(db, slaves[i].c_str(), pm.master, false);
|
|
803
|
+
notifyBrank(nf);
|
|
804
|
+
nfSetHostName(nf, slaves[i].c_str());
|
|
805
|
+
int ha = readHaVar(mgr);
|
|
806
|
+
roleMaster = isRoleMaster(ha);
|
|
807
|
+
notify(nf, roleMaster ? HA_NF_MSG_NG : HA_NF_MSG_OK, roleName(roleMaster));
|
|
808
|
+
if (roleMaster) ++ret;
|
|
809
|
+
|
|
810
|
+
bool fo = isEnableFailOver(ha);
|
|
811
|
+
notify(nf, fo ? HA_NF_MSG_OK : HA_NF_MSG_NG, fo ? "Failover is enabled" : "Failover is disabled");
|
|
812
|
+
if (!fo) ++ret;
|
|
813
|
+
|
|
814
|
+
if (!lockTest(mgr, nf)) ++ret;
|
|
815
|
+
|
|
816
|
+
string channel = getChannlName(mgr, pm.master.host.c_str());
|
|
817
|
+
notify(nf, HA_NF_CANNELNAME, channel.c_str());
|
|
818
|
+
const connMgr::records& recs = mgr->slaveStatus(channel.c_str());
|
|
819
|
+
if (recs.size() <= SLAVE_STATUS_EXEC_MASTER_LOG_POS)
|
|
820
|
+
{
|
|
821
|
+
notify(nf, HA_NF_MSG_NG, _T("Can not read slave status."));
|
|
822
|
+
++ret;
|
|
823
|
+
}
|
|
824
|
+
else
|
|
825
|
+
{
|
|
826
|
+
bool sql_run = _stricmp(recs[SLAVE_STATUS_SLAVE_SQL_RUNNING].name, "Yes") == 0;
|
|
827
|
+
bool io_run = _stricmp(recs[SLAVE_STATUS_SLAVE_IO_RUNNING].name, "Yes") == 0;
|
|
828
|
+
notify(nf, sql_run ? HA_NF_MSG_OK : HA_NF_MSG_NG, _T("SQL thread running"));
|
|
829
|
+
notify(nf, sql_run ? HA_NF_MSG_OK : HA_NF_MSG_NG, _T("IO thread running"));
|
|
830
|
+
if (!sql_run) ++ret;
|
|
831
|
+
if (!io_run) ++ret;
|
|
832
|
+
__int64 read_pos = recs[SLAVE_STATUS_READ_MASTER_LOG_POS].longValue;
|
|
833
|
+
__int64 write_pos = recs[SLAVE_STATUS_EXEC_MASTER_LOG_POS].longValue;
|
|
834
|
+
_TCHAR tmp[50];
|
|
835
|
+
_i64tot_s(read_pos - write_pos, tmp, 50, 10);
|
|
836
|
+
notify(nf, HA_NF_DELAY, tmp);
|
|
837
|
+
}
|
|
838
|
+
mgr.reset();
|
|
839
|
+
}
|
|
840
|
+
return ret;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
|