transactd 3.4.1 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,78 @@
|
|
1
|
+
#ifndef GLOBAL_REPLICATION_HACOMMANDH
|
2
|
+
#define GLOBAL_REPLICATION_HACOMMANDH
|
3
|
+
/*=================================================================
|
4
|
+
Copyright (C) 2016 BizStation Corp All rights reserved.
|
5
|
+
|
6
|
+
This program is free software; you can redistribute it and/or
|
7
|
+
modify it under the terms of the GNU General Public License
|
8
|
+
as published by the Free Software Foundation; either version 2
|
9
|
+
of the License, or (at your option) any later version.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU General Public License
|
17
|
+
along with this program; if not, write to the Free Software
|
18
|
+
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
19
|
+
02111-1307, USA.
|
20
|
+
=================================================================*/
|
21
|
+
#include "replCommand.h"
|
22
|
+
|
23
|
+
#define OPT_SO_AUTO_SLVAE_LIST 1
|
24
|
+
#define OPT_FO_FAILOVER 2
|
25
|
+
#define OPT_DISABLE_OLD_TO_SLAVE 4
|
26
|
+
#define OPT_READONLY_CONTROL 8
|
27
|
+
|
28
|
+
struct failOverParam
|
29
|
+
{
|
30
|
+
mutable int option;
|
31
|
+
mutable std::_tstring slaves;
|
32
|
+
masterNode newMaster;
|
33
|
+
node master;
|
34
|
+
std::string portMap;
|
35
|
+
failOverParam() : option(0){}
|
36
|
+
bool isFailOver() const {return (option & OPT_FO_FAILOVER) != 0;}
|
37
|
+
bool isSwitchOver() const {return !isFailOver();}
|
38
|
+
bool isDisableOldMasterToSalve() const
|
39
|
+
{return (option & OPT_DISABLE_OLD_TO_SLAVE) != 0;}
|
40
|
+
};
|
41
|
+
|
42
|
+
class haNotify
|
43
|
+
{
|
44
|
+
public:
|
45
|
+
virtual ~haNotify() {};
|
46
|
+
virtual void onUpdateStaus(int status, const _TCHAR* msg) = 0;
|
47
|
+
virtual void setHostName(const _TCHAR* host) = 0;
|
48
|
+
};
|
49
|
+
|
50
|
+
#define HA_NF_ROLE_SLAVE 1
|
51
|
+
#define HA_NF_ROLE_MASTER 2
|
52
|
+
#define HA_NF_CANNELNAME 3
|
53
|
+
#define HA_SLAVE_START 4
|
54
|
+
#define HA_SLAVE_STOP 5
|
55
|
+
#define HA_SLAVE_STOP_ALL 6
|
56
|
+
#define HA_CHANGE_MASTER 7
|
57
|
+
#define HA_SWITCH_MASTER 8
|
58
|
+
#define HA_NF_WAIT_TRX_START 9
|
59
|
+
#define HA_NF_WAIT_TRX_COMP 10
|
60
|
+
#define HA_NF_SLAVE_LIST 11
|
61
|
+
#define HA_NF_PROMOTE_MASTER 12
|
62
|
+
#define HA_NF_PROMOTE_CHANNEL 13
|
63
|
+
#define HA_NF_WAIT_POS_START 14
|
64
|
+
#define HA_NF_WAIT_POS_COMP 15
|
65
|
+
#define HA_SET_READ_ONLY 16
|
66
|
+
#define HA_NF_MSG_OK 17
|
67
|
+
#define HA_NF_MSG_NG 18
|
68
|
+
#define HA_NF_DELAY 19
|
69
|
+
#define HA_NF_BLANK 20
|
70
|
+
|
71
|
+
void failOrver(const failOverParam& pm, haNotify* nf=NULL);
|
72
|
+
void switchOrver(const failOverParam& pm, haNotify* nf=NULL);
|
73
|
+
void demoteToSlave(const failOverParam& pm, haNotify* nf=NULL);
|
74
|
+
void setEnableFailOver(const failOverParam& pm, bool v);
|
75
|
+
void setServerRole(const failOverParam& pm, int v);
|
76
|
+
int healthCheck(const failOverParam& pm, haNotify* nf);
|
77
|
+
|
78
|
+
#endif // GLOBAL_REPLICATION_HACOMMANDH
|
@@ -0,0 +1,321 @@
|
|
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 <global/replication/haCommand.h>
|
21
|
+
#include <locale.h>
|
22
|
+
#include <iostream>
|
23
|
+
#include <vector>
|
24
|
+
#include <boost/program_options.hpp>
|
25
|
+
#include <bzs/rtl/stl_uty.h>
|
26
|
+
#include <bzs/db/protocol/tdap/btrDate.h>
|
27
|
+
|
28
|
+
#ifdef __BCPLUSPLUS__
|
29
|
+
#define BZS_LINK_BOOST_PROGRAM_OPTIONS
|
30
|
+
#include <bzs/env/boost_bcb_link.h>
|
31
|
+
#endif
|
32
|
+
|
33
|
+
using namespace bzs::db::protocol::tdap::client;
|
34
|
+
using namespace bzs::db::protocol::tdap;
|
35
|
+
using namespace boost::program_options;
|
36
|
+
using namespace std;
|
37
|
+
|
38
|
+
static const char* cmds = "switchover,failover,demote_to_slave,"
|
39
|
+
"set_failover_enable,set_server_role,health_check";
|
40
|
+
#define CMD_SWITCHOVER 0
|
41
|
+
#define CMD_FAILOVER 1
|
42
|
+
#define CMD_DEMOTE_TO_SLAVE 2
|
43
|
+
#define CMD_SET_FAILOVER_ENABLE 3
|
44
|
+
#define CMD_SET_SERVER_ROLE 4
|
45
|
+
#define CMD_HEALTH_CHECK 5
|
46
|
+
|
47
|
+
|
48
|
+
_tstring str_conv(std::string& v)
|
49
|
+
{
|
50
|
+
#ifdef _UNICODE
|
51
|
+
wchar_t wbuf[1024];
|
52
|
+
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, v.c_str(), -1, wbuf, 1024);
|
53
|
+
return wbuf;
|
54
|
+
#else
|
55
|
+
return v;
|
56
|
+
#endif //_UNICODE
|
57
|
+
}
|
58
|
+
|
59
|
+
class haMgrNotify : public haNotify
|
60
|
+
{
|
61
|
+
_tstring m_host;
|
62
|
+
public:
|
63
|
+
virtual ~haMgrNotify() {};
|
64
|
+
void onUpdateStaus(int status, const _TCHAR* msg)
|
65
|
+
{
|
66
|
+
const _TCHAR* p=_T("");
|
67
|
+
switch(status)
|
68
|
+
{
|
69
|
+
case HA_NF_ROLE_SLAVE: p = _T(": set role=SLAVE ");break;
|
70
|
+
case HA_NF_CANNELNAME: p = _T(": channel name=");break;
|
71
|
+
case HA_SLAVE_STOP_ALL: p = _T(": stop slave all ");break;
|
72
|
+
case HA_CHANGE_MASTER: p = _T(": change master to new master, pos=");break;
|
73
|
+
case HA_SWITCH_MASTER: p = _T(": change master to new master, pos=");break;
|
74
|
+
case HA_SLAVE_START: p = _T(": start slave ");break;
|
75
|
+
case HA_NF_WAIT_TRX_START: p = _T(": waiting for trx...");break;
|
76
|
+
case HA_NF_WAIT_TRX_COMP: p = _T(": wait is completed, pos=");break;
|
77
|
+
case HA_NF_SLAVE_LIST: p = _T("SLAVE_LIST=");break;
|
78
|
+
case HA_NF_PROMOTE_MASTER: p = _T(": promote to master ");break;
|
79
|
+
case HA_NF_PROMOTE_CHANNEL: p = _T(": channel name=");break;
|
80
|
+
case HA_NF_ROLE_MASTER: p = _T(": set role=MASTER ");break;
|
81
|
+
case HA_NF_WAIT_POS_START: p = _T(": waiting for until...");break;
|
82
|
+
case HA_NF_WAIT_POS_COMP: p = _T(": wait is completed, pos=");break;
|
83
|
+
case HA_SLAVE_STOP: p = _T(": stop slave ");break;
|
84
|
+
case HA_SET_READ_ONLY: p = _T(": set READ_ONLY=1");break;
|
85
|
+
case HA_NF_DELAY: p = _T(": SQL thread delay=");break;
|
86
|
+
case HA_NF_MSG_OK:
|
87
|
+
tcout << " " << m_host << _T(": ") << msg << _T(" OK!") << endl;
|
88
|
+
return;
|
89
|
+
case HA_NF_MSG_NG:
|
90
|
+
tcout << " " << m_host << _T(": ") << msg << _T(" NG!") << endl;
|
91
|
+
return;
|
92
|
+
}
|
93
|
+
tcout << " " << m_host << p << msg << endl;
|
94
|
+
}
|
95
|
+
void setHostName(const _TCHAR* host)
|
96
|
+
{
|
97
|
+
m_host = host;
|
98
|
+
}
|
99
|
+
};
|
100
|
+
|
101
|
+
int checkParam(failOverParam& pm, int cmd, int v)
|
102
|
+
{
|
103
|
+
if (cmd != CMD_FAILOVER)
|
104
|
+
{
|
105
|
+
if (pm.master.host == _T(""))
|
106
|
+
{
|
107
|
+
cout << "--cur_master is requered" << endl;
|
108
|
+
return 1;
|
109
|
+
}
|
110
|
+
}else
|
111
|
+
{
|
112
|
+
if (pm.slaves == _T(""))
|
113
|
+
{
|
114
|
+
cout << "--slaves is requered" << endl;
|
115
|
+
return 1;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
if (cmd == CMD_SWITCHOVER || cmd == CMD_DEMOTE_TO_SLAVE)
|
120
|
+
{
|
121
|
+
if (pm.newMaster.host == _T(""))
|
122
|
+
{
|
123
|
+
cout << "--new_master is requered" << endl;
|
124
|
+
return 1;
|
125
|
+
}
|
126
|
+
if (pm.newMaster.repUser == "")
|
127
|
+
{
|
128
|
+
cout << "--repl_user is requered" << endl;
|
129
|
+
return 1;
|
130
|
+
}
|
131
|
+
if (pm.newMaster.repPasswd == "")
|
132
|
+
{
|
133
|
+
cout << "--repl_passwd is requered" << endl;
|
134
|
+
return 1;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
return 0;
|
138
|
+
}
|
139
|
+
|
140
|
+
int getCommandLineOption(int argc, _TCHAR* argv[], failOverParam& pm, int& cmd, int& v)
|
141
|
+
{
|
142
|
+
std::string c, host, newMaster, user, pwd, slaves;
|
143
|
+
std::string port = "3306";
|
144
|
+
bool readonly = false;
|
145
|
+
bool disable_demote = false;
|
146
|
+
options_description opt("command line option");
|
147
|
+
opt.add_options()("command,c", value<std::string>(&c),
|
148
|
+
"command [switchover | failover | demote_to_slave | set_failover_enable | set_server_role | health_check]")
|
149
|
+
("cur_master,o", value<std::string>(&host), "current master host name")
|
150
|
+
("new_master,n", value<std::string>(&newMaster), "new master host name")
|
151
|
+
("channel,C", value<std::string>(&pm.newMaster.channel), "new master channel name")
|
152
|
+
("repl_port,P", value<std::string>(&pm.newMaster.repPort), "new master port")
|
153
|
+
("repl_user,r", value<std::string>(&pm.newMaster.repUser), "new master repl user ")
|
154
|
+
("repl_passwd,d", value<std::string>(&pm.newMaster.repPasswd), "new master repl password ")
|
155
|
+
("repl_option,O", value<std::string>(&pm.newMaster.repOption), "option params for change master(ex: MASTER_CONNECT_RETRY=30)")
|
156
|
+
("slaves,s", value<std::string>(&slaves), "slave list for failover")
|
157
|
+
("portmap,a", value<std::string>(&pm.portMap), "port map ex:3307:8611")
|
158
|
+
("value,v", value<int>(&v), "value (For set_failover_enable or set_server_role)")
|
159
|
+
("username,u", value<std::string>(&user), "transactd username")
|
160
|
+
("password,p", value<std::string>(&pwd), "transactd password")
|
161
|
+
("readonly,R", value<bool>(&readonly), "0 | 1: When it is 1, the READONLY variable will be set ON to slaves and OFF to a master")
|
162
|
+
("disable_demote,D", value<bool>(&disable_demote), "0 | 1: disable old master demote");
|
163
|
+
variables_map values;
|
164
|
+
store(parse_command_line(argc, argv, opt), values);
|
165
|
+
notify(values);
|
166
|
+
if (!values.count("command"))
|
167
|
+
{
|
168
|
+
cout << opt << endl;
|
169
|
+
return 1;
|
170
|
+
}
|
171
|
+
vector<string> cmdList;
|
172
|
+
split(cmdList, cmds, ",");
|
173
|
+
vector<string>::iterator it = find(cmdList.begin(), cmdList.end(), c);
|
174
|
+
if (it== cmdList.end())
|
175
|
+
{
|
176
|
+
cout << opt << endl;
|
177
|
+
return 1;
|
178
|
+
}
|
179
|
+
cmd = (int)(it - cmdList.begin());
|
180
|
+
if ((cmd == CMD_SET_SERVER_ROLE || cmd == CMD_SET_FAILOVER_ENABLE) &&
|
181
|
+
!values.count("value"))
|
182
|
+
{
|
183
|
+
cout << opt << endl;
|
184
|
+
return 1;
|
185
|
+
}
|
186
|
+
pm.newMaster.host = str_conv(newMaster);
|
187
|
+
pm.master.host = str_conv(host);
|
188
|
+
pm.master.user = str_conv(user);
|
189
|
+
pm.master.passwd = str_conv(pwd);
|
190
|
+
pm.slaves = str_conv(slaves);
|
191
|
+
if (readonly) pm.option |= OPT_READONLY_CONTROL;
|
192
|
+
if (disable_demote) pm.option |= OPT_DISABLE_OLD_TO_SLAVE;
|
193
|
+
return checkParam(pm, cmd, v);
|
194
|
+
}
|
195
|
+
|
196
|
+
void printDateTime()
|
197
|
+
{
|
198
|
+
btrDateTime bt;
|
199
|
+
char tmp[256];
|
200
|
+
bt.time.i = getNowTime();
|
201
|
+
bt.date.i = getNowDate();
|
202
|
+
btrstoa(bt, tmp, true);
|
203
|
+
cout << tmp;
|
204
|
+
}
|
205
|
+
|
206
|
+
void printMessage(const char* msg, const char* msg2="")
|
207
|
+
{
|
208
|
+
printDateTime();
|
209
|
+
cout << " " << msg << msg2 << endl;
|
210
|
+
}
|
211
|
+
|
212
|
+
#ifdef _UNICODE
|
213
|
+
void printMessage(const wchar_t* msg, const wchar_t* msg2=_T(""))
|
214
|
+
{
|
215
|
+
printDateTime();
|
216
|
+
tcout << " " << msg << msg2 << endl;
|
217
|
+
}
|
218
|
+
#endif
|
219
|
+
|
220
|
+
/* Command line paramater
|
221
|
+
command line option:
|
222
|
+
-c [ --command ] command [switchover | failover | demote_to_slave | set_failover_enable | set_server_role | health_check]
|
223
|
+
-o [ --cur_master ] current master host name
|
224
|
+
-n [ --new_master ] new master host name
|
225
|
+
-C [ --channel ] new master channel name
|
226
|
+
-P [ --repl_port ] new master port
|
227
|
+
-r [ --repl_user ] new master repl user
|
228
|
+
-d [ --repl_passwd ] new master repl password
|
229
|
+
-O [ --repl_option ] option params for change master(ex:MASTER_CONNECT_RETRY=30)
|
230
|
+
-s [ --slaves ] slave list for failover
|
231
|
+
-a [ --portmap ] port map ex:3307:8611
|
232
|
+
-v [ --value ] value (For set_failover_enable or set_server_role)
|
233
|
+
-u [ --username ] transactd username
|
234
|
+
-p [ --password ] transactd password
|
235
|
+
-R [ --readonly ] 0 | 1: When it is 1, the READONLY variable will be set ON to slaves and OFF to a master
|
236
|
+
-D [ --disable_demote ] 0 | 1: disable old master demote
|
237
|
+
|
238
|
+
example:
|
239
|
+
haMgr64 -c switchover -o localhost -n localhost:8611 -P 3307 -r replication_user -d xxxx -u root -p xxxx
|
240
|
+
|
241
|
+
haMgr64 -c failover -s localhost:8611,localhost:8612 -a 8610:3306,8611:3307,8612:3308
|
242
|
+
-u root -p
|
243
|
+
|
244
|
+
haMgr64 -c demote_to_slave -o localhost -n localhost:8611 -P 3307 -r replication_user -d xxxx
|
245
|
+
-d abcd -u root -p
|
246
|
+
|
247
|
+
haMgr64 -c set_failover_enable -v 1 -o localhost -u root -p
|
248
|
+
|
249
|
+
haMgr64 -c set_server_role -o localhost -v 1 -u root -p
|
250
|
+
|
251
|
+
haMgr64 -c health_check -o localhost -s localhost:8611,localhost:8612 -u root -p
|
252
|
+
|
253
|
+
*/
|
254
|
+
|
255
|
+
#pragma argsused
|
256
|
+
int _tmain(int argc, _TCHAR* argv[])
|
257
|
+
{
|
258
|
+
#ifdef _WIN32
|
259
|
+
// set locale to current user locale.
|
260
|
+
std::locale::global(std::locale(""));
|
261
|
+
#endif
|
262
|
+
int ret = 1;
|
263
|
+
try
|
264
|
+
{
|
265
|
+
failOverParam pm;
|
266
|
+
int cmd = 0;
|
267
|
+
int v = 0;
|
268
|
+
ret = getCommandLineOption(argc, argv, pm, cmd, v);
|
269
|
+
if (ret == 0)
|
270
|
+
{
|
271
|
+
haMgrNotify nf;
|
272
|
+
switch (cmd)
|
273
|
+
{
|
274
|
+
case CMD_SWITCHOVER:
|
275
|
+
pm.option |= OPT_SO_AUTO_SLVAE_LIST;
|
276
|
+
printMessage("Starting switch over...");
|
277
|
+
switchOrver(pm, &nf);
|
278
|
+
break;
|
279
|
+
case CMD_FAILOVER:
|
280
|
+
printMessage("Starting fail over...");
|
281
|
+
failOrver(pm, &nf);
|
282
|
+
break;
|
283
|
+
case CMD_DEMOTE_TO_SLAVE:
|
284
|
+
printMessage("Starting demote to slave...");
|
285
|
+
demoteToSlave(pm, &nf);
|
286
|
+
break;
|
287
|
+
case CMD_SET_FAILOVER_ENABLE:
|
288
|
+
pm.option |= OPT_SO_AUTO_SLVAE_LIST;
|
289
|
+
setEnableFailOver(pm, v == 1);
|
290
|
+
break;
|
291
|
+
case CMD_SET_SERVER_ROLE:
|
292
|
+
setServerRole(pm, v);
|
293
|
+
break;
|
294
|
+
case CMD_HEALTH_CHECK:
|
295
|
+
printMessage("Starting health check...");
|
296
|
+
int errors = healthCheck(pm, &nf);
|
297
|
+
char tmp[256];
|
298
|
+
if (errors)
|
299
|
+
sprintf_s(tmp, 256, "%d errors detected.", errors);
|
300
|
+
else
|
301
|
+
sprintf_s(tmp, 256, "No errors detected.");
|
302
|
+
cout << endl << " *** " << tmp << endl << endl;
|
303
|
+
ret = errors;
|
304
|
+
break;
|
305
|
+
}
|
306
|
+
printMessage("Done!");
|
307
|
+
}
|
308
|
+
}
|
309
|
+
catch (bzs::rtl::exception& e)
|
310
|
+
{
|
311
|
+
printMessage(_T("Error! "), getMsg(e)->c_str());
|
312
|
+
ret = 1;
|
313
|
+
}
|
314
|
+
catch (std::exception& e)
|
315
|
+
{
|
316
|
+
printMessage("Error! ", e.what());
|
317
|
+
ret = 1;
|
318
|
+
}
|
319
|
+
return ret;
|
320
|
+
}
|
321
|
+
//---------------------------------------------------------------------------
|
@@ -0,0 +1,696 @@
|
|
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 "replCommand.h"
|
21
|
+
#pragma package(smart_init)
|
22
|
+
using namespace std;
|
23
|
+
using namespace bzs::db::protocol::tdap;
|
24
|
+
using namespace bzs::db::protocol::tdap::client;
|
25
|
+
|
26
|
+
#define ER_BAD_SLAVE 26200
|
27
|
+
#define WARN_NO_MASTER_INF 26617
|
28
|
+
#define ER_UNTIL_REQUIRES_USING_GTID 26949
|
29
|
+
#define ER_SLAVE_CHANNEL_DOES_NOT_EXIST 28074
|
30
|
+
|
31
|
+
|
32
|
+
connectParams node::cp(int opt)
|
33
|
+
{
|
34
|
+
bool nodb = (opt & CP_NO_DB) != 0;
|
35
|
+
bool noschem = nodb || ((opt & CP_NO_SCHEMA) != 0);
|
36
|
+
connectParams cp1(_T("tdap"),
|
37
|
+
host.c_str(),
|
38
|
+
nodb ? _T("") : db.c_str(),
|
39
|
+
noschem ? _T("") : schema.c_str(),
|
40
|
+
user.c_str(), passwd.c_str());
|
41
|
+
return cp1;
|
42
|
+
}
|
43
|
+
|
44
|
+
void node::setOption(int op, bool enable)
|
45
|
+
{
|
46
|
+
if (enable)
|
47
|
+
options |= op;
|
48
|
+
else
|
49
|
+
options &= ~op;
|
50
|
+
}
|
51
|
+
|
52
|
+
//------------------------------------------------------------------------------
|
53
|
+
struct replImpl
|
54
|
+
{
|
55
|
+
replicationParam& pm;
|
56
|
+
|
57
|
+
replImpl(replicationParam& p) : pm(p){}
|
58
|
+
|
59
|
+
virtual bool ignoreError(short stat) { return false;}
|
60
|
+
|
61
|
+
virtual void setSlaveSkipError(database_ptr db, const char* /*gtid*/)
|
62
|
+
{
|
63
|
+
execSql(db, "set global sql_slave_skip_counter=1");
|
64
|
+
}
|
65
|
+
|
66
|
+
virtual void setGtidSlavePos(database_ptr db, const binlogPos& bpos,
|
67
|
+
connMgr* mgr){}
|
68
|
+
|
69
|
+
virtual string stopSlaveSql() {return "stop slave";}
|
70
|
+
|
71
|
+
virtual string stopAllSlaveSql() {return "stop slave";}
|
72
|
+
|
73
|
+
virtual string startSlaveSql() {return "start slave";}
|
74
|
+
|
75
|
+
virtual string startAllSlaveSql() {return "start slave";}
|
76
|
+
|
77
|
+
virtual string resetSlaveSql() {return "reset slave";}
|
78
|
+
|
79
|
+
virtual string resetSlaveAllSql() {return "reset slave all";}
|
80
|
+
|
81
|
+
virtual string resetMasterSql() {return "reset master";}
|
82
|
+
|
83
|
+
virtual string changeMasterSql(const binlogPos& bpos, connMgr* /*mgr*/)
|
84
|
+
{
|
85
|
+
char tmp[128];
|
86
|
+
_i64toa_s(bpos.pos, tmp, 128, 10);
|
87
|
+
return changeMasterBaseSql()
|
88
|
+
+ ", master_log_file='" + string(bpos.filename)
|
89
|
+
+ "', master_log_pos=" + tmp;
|
90
|
+
}
|
91
|
+
|
92
|
+
virtual string switchMasterSql(replSlave::autoPosType)
|
93
|
+
{
|
94
|
+
THROW_BZS_ERROR_WITH_MSG(_T("No support switchMaster at this replication type."));
|
95
|
+
}
|
96
|
+
|
97
|
+
virtual string startSlaveUntilSql(const binlogPos& bpos)
|
98
|
+
{
|
99
|
+
char buf[128];
|
100
|
+
_i64toa_s(bpos.pos, buf, 128, 10);
|
101
|
+
return "start slave until master_log_file='"
|
102
|
+
+ string(bpos.filename) + "', master_log_pos="
|
103
|
+
+ string(buf);
|
104
|
+
}
|
105
|
+
protected:
|
106
|
+
std::vector<string> getGtids(char* str)
|
107
|
+
{
|
108
|
+
std::vector<string> gtids;
|
109
|
+
char* en = str + strlen(str);;
|
110
|
+
char* st = str;
|
111
|
+
while (st < en)
|
112
|
+
{
|
113
|
+
char* p = strchr(st, ',');
|
114
|
+
if (p) *p = 0x00;
|
115
|
+
gtids.push_back(st);
|
116
|
+
st = p ? p + 1 : en;
|
117
|
+
if (*st == '\n') ++st;
|
118
|
+
}
|
119
|
+
return gtids;
|
120
|
+
}
|
121
|
+
|
122
|
+
string changeMasterBaseSql()
|
123
|
+
{
|
124
|
+
masterNode& mn = pm.master;
|
125
|
+
string host = toUtf8(mn.host);
|
126
|
+
// remove port number
|
127
|
+
size_t pos = host.find(":");
|
128
|
+
if (pos != std::string::npos)
|
129
|
+
host.erase(host.begin() + pos, host.end());
|
130
|
+
string s = "change master to master_host='" + host + "'";
|
131
|
+
if (mn.repPort != "")
|
132
|
+
s += ", master_port=" + mn.repPort;
|
133
|
+
if (mn.repUser != "")
|
134
|
+
{
|
135
|
+
s += ", master_user='" + mn.repUser + "'";
|
136
|
+
s += ", master_password='" + mn.repPasswd + "'";
|
137
|
+
}
|
138
|
+
if (mn.repOption != "")
|
139
|
+
s += "," + mn.repOption;
|
140
|
+
return s;
|
141
|
+
}
|
142
|
+
};
|
143
|
+
|
144
|
+
struct replImplMaria : public replImpl
|
145
|
+
{
|
146
|
+
replImplMaria(database_ptr db, replicationParam& p) : replImpl(p)
|
147
|
+
{
|
148
|
+
if (pm.master.channel != "")
|
149
|
+
{
|
150
|
+
char tmp[256];
|
151
|
+
sprintf_s(tmp, 256, "set session default_master_connection='%s'",
|
152
|
+
pm.master.channel.c_str());
|
153
|
+
execSql(db, tmp);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
bool ignoreError(short stat) { return stat == WARN_NO_MASTER_INF;}
|
158
|
+
|
159
|
+
string stopAllSlaveSql() {return "stop all slaves";}
|
160
|
+
|
161
|
+
string startAllSlaveSql() {return "start all slaves";}
|
162
|
+
|
163
|
+
string changeMasterSql(const binlogPos& bpos, connMgr* mgr)
|
164
|
+
{
|
165
|
+
if (pm.type == REP_TYPE_REGACY)
|
166
|
+
return replImpl::changeMasterSql(bpos, mgr);
|
167
|
+
return changeMasterBaseSql() + ", master_use_gtid=slave_pos";
|
168
|
+
}
|
169
|
+
|
170
|
+
string switchMasterSql(replSlave::autoPosType v)
|
171
|
+
{
|
172
|
+
if (v == replSlave::slave_pos)
|
173
|
+
return changeMasterBaseSql() + ", master_use_gtid=slave_pos";
|
174
|
+
else
|
175
|
+
return changeMasterBaseSql() + ", master_use_gtid=current_pos";
|
176
|
+
}
|
177
|
+
|
178
|
+
void setGtidSlavePos(database_ptr db, const binlogPos& bpos, connMgr* mgr)
|
179
|
+
{
|
180
|
+
if (pm.type == REP_TYPE_REGACY) return;
|
181
|
+
string gtid = getAllGtids(bpos, mgr);
|
182
|
+
string s = "set global gtid_slave_pos=\"" + gtid + "\"";
|
183
|
+
execSql(db, s.c_str());
|
184
|
+
}
|
185
|
+
private:
|
186
|
+
inline uint_td domainid(const char* gtid) {return strtoul(gtid, NULL, 10);}
|
187
|
+
|
188
|
+
string getAllGtids(const binlogPos& bpos, connMgr* mgr)
|
189
|
+
{
|
190
|
+
string gtid = bpos.gtid;
|
191
|
+
uint_td domain = domainid(gtid.c_str());
|
192
|
+
//const connMgr::records recs = mgr->channels();
|
193
|
+
connRecords_ptr recs_p = createConnRecords(mgr->channels());
|
194
|
+
const connMgr::records& recs = *recs_p.get();
|
195
|
+
|
196
|
+
|
197
|
+
validateStatus(mgr, _T("channels"));
|
198
|
+
if (recs.size())
|
199
|
+
{
|
200
|
+
const connMgr::records& recs2 = mgr->slaveStatus(recs[0].name);
|
201
|
+
validateStatus(mgr, _T("Gtids slaveStatus"));
|
202
|
+
if (recs2.size() > SLAVE_STATUS_MA_GTID_IO_POS)
|
203
|
+
{
|
204
|
+
char tmp[256];
|
205
|
+
recs2[SLAVE_STATUS_MA_GTID_IO_POS].value(tmp, 256);
|
206
|
+
std::vector<string> gtids = getGtids(tmp);
|
207
|
+
|
208
|
+
for (size_t i=0; i < gtids.size(); ++i)
|
209
|
+
{
|
210
|
+
if (domain != domainid(gtids[i].c_str()))
|
211
|
+
gtid += string(",") + gtids[i];
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
return gtid;
|
216
|
+
}
|
217
|
+
};
|
218
|
+
|
219
|
+
//------------------------------------------------------------------------------
|
220
|
+
struct replImplMy : public replImpl
|
221
|
+
{
|
222
|
+
replImplMy(replicationParam& p) : replImpl(p){}
|
223
|
+
|
224
|
+
void setSlaveSkipError(database_ptr db, const char* gtid)
|
225
|
+
{
|
226
|
+
char tmp[256] = "set gtid_next = \"";
|
227
|
+
strcat_s(tmp, 256, gtid);
|
228
|
+
strcat_s(tmp, 256, "\"");
|
229
|
+
execSql(db, tmp);
|
230
|
+
execSql(db, "start transaction");
|
231
|
+
execSql(db, "commit");
|
232
|
+
execSql(db, "set gtid_next = automatic");
|
233
|
+
}
|
234
|
+
|
235
|
+
string changeMasterSql(const binlogPos& bpos, connMgr* mgr)
|
236
|
+
{
|
237
|
+
if (pm.type == REP_TYPE_REGACY)
|
238
|
+
return replImpl::changeMasterSql(bpos, mgr);
|
239
|
+
return changeMasterBaseSql() + ", master_auto_position=1";
|
240
|
+
}
|
241
|
+
|
242
|
+
string switchMasterSql(replSlave::autoPosType /*v*/)
|
243
|
+
{
|
244
|
+
return changeMasterBaseSql() + ", master_auto_position=1";
|
245
|
+
}
|
246
|
+
|
247
|
+
void setGtidSlavePos(database_ptr db, const binlogPos& bpos, connMgr* mgr)
|
248
|
+
{
|
249
|
+
if (pm.type == REP_TYPE_REGACY || !pm.slave.option(OPT_RESET_MASTER))
|
250
|
+
return;
|
251
|
+
string s = "set global gtid_purged=\"" + gtidset(bpos, mgr) + "\"";
|
252
|
+
execSql(db, "reset master");
|
253
|
+
execSql(db, s.c_str());
|
254
|
+
}
|
255
|
+
private:
|
256
|
+
virtual string gtidset(const binlogPos& bpos, connMgr* /*mgr*/)
|
257
|
+
{
|
258
|
+
return bpos.gtid;
|
259
|
+
}
|
260
|
+
};
|
261
|
+
|
262
|
+
//------------------------------------------------------------------------------
|
263
|
+
struct replImplMy57 : public replImplMy
|
264
|
+
{
|
265
|
+
replImplMy57(replicationParam& p) : replImplMy(p){}
|
266
|
+
|
267
|
+
bool ignoreError(short stat)
|
268
|
+
{
|
269
|
+
return (stat == ER_SLAVE_CHANNEL_DOES_NOT_EXIST);
|
270
|
+
}
|
271
|
+
|
272
|
+
string stopSlaveSql() {return "stop slave" + channelSql();}
|
273
|
+
|
274
|
+
string startSlaveSql() {return "start slave" + channelSql();}
|
275
|
+
|
276
|
+
string resetSlaveSql() {return "reset slave" + channelSql();}
|
277
|
+
|
278
|
+
string resetSlaveAllSql() {return "reset slave all" + channelSql();}
|
279
|
+
|
280
|
+
string startSlaveUntilSql(const binlogPos& bpos)
|
281
|
+
{
|
282
|
+
return replImpl::startSlaveUntilSql(bpos) + channelSql();
|
283
|
+
}
|
284
|
+
|
285
|
+
string changeMasterSql(const binlogPos& bpos, connMgr* mgr)
|
286
|
+
{
|
287
|
+
return replImplMy::changeMasterSql(bpos, mgr) + channelSql();
|
288
|
+
}
|
289
|
+
|
290
|
+
string switchMasterSql(replSlave::autoPosType v)
|
291
|
+
{
|
292
|
+
return replImplMy::switchMasterSql(v) + channelSql();
|
293
|
+
}
|
294
|
+
|
295
|
+
private:
|
296
|
+
string channelSql() {return " for channel '" + pm.master.channel + "'";}
|
297
|
+
|
298
|
+
string uuid(string& gtid)
|
299
|
+
{
|
300
|
+
size_t pos = gtid.find(':');
|
301
|
+
if (pos != string::npos)
|
302
|
+
return gtid.substr(0, pos);
|
303
|
+
assert(0);
|
304
|
+
return "";
|
305
|
+
}
|
306
|
+
|
307
|
+
string gtidset(const binlogPos& bpos, connMgr* mgr)
|
308
|
+
{ // all channels
|
309
|
+
char tmp[4096];
|
310
|
+
string gtid = bpos.gtid;
|
311
|
+
strcpy_s(tmp, 4096, gtid.c_str());
|
312
|
+
std::vector<string> gds = getGtids(tmp);
|
313
|
+
std::vector<string> uuids;
|
314
|
+
for (size_t i=0;i<gds.size(); ++i)
|
315
|
+
uuids.push_back(uuid(gds[i]));
|
316
|
+
|
317
|
+
//const connMgr::records recs = mgr->channels();
|
318
|
+
connRecords_ptr recs_p = createConnRecords(mgr->channels());
|
319
|
+
const connMgr::records& recs = *recs_p.get();
|
320
|
+
|
321
|
+
|
322
|
+
validateStatus(mgr, _T("channels"));
|
323
|
+
for (size_t i = 0; i < recs.size(); ++i)
|
324
|
+
{
|
325
|
+
if (pm.master.channel != recs[i].name)
|
326
|
+
{
|
327
|
+
const connMgr::records& recs2 = mgr->slaveStatus(recs[i].name);
|
328
|
+
validateStatus(mgr, _T("Gtids slaveStatus"));
|
329
|
+
if (recs2.size() > SLAVE_STATUS_EXECUTED_GTID_SET)
|
330
|
+
{
|
331
|
+
recs2[SLAVE_STATUS_EXECUTED_GTID_SET].value(tmp, 4096);
|
332
|
+
std::vector<string> gtids = getGtids(tmp);
|
333
|
+
|
334
|
+
for (size_t i=0; i < gtids.size(); ++i)
|
335
|
+
{
|
336
|
+
string uid = uuid(gtids[i]);
|
337
|
+
if (find(uuids.begin(), uuids.end(), uid) == uuids.end())
|
338
|
+
gtid += string(",") + gtids[i];
|
339
|
+
}
|
340
|
+
return gtid;
|
341
|
+
}
|
342
|
+
}
|
343
|
+
}
|
344
|
+
return gtid;
|
345
|
+
}
|
346
|
+
};
|
347
|
+
|
348
|
+
//------------------------------------------------------------------------------
|
349
|
+
// support functions
|
350
|
+
//------------------------------------------------------------------------------
|
351
|
+
bool isMySqlGtidMode(connMgr* mgr)
|
352
|
+
{
|
353
|
+
const connMgr::records& rec = mgr->extendedvars();
|
354
|
+
return (rec.size() && (rec[TD_EXTENDED_VAR_MYSQL_GTID_MODE].longValue != 0));
|
355
|
+
}
|
356
|
+
|
357
|
+
void notyfy(replicationNotify* nf, int v)
|
358
|
+
{
|
359
|
+
if (nf) nf->onUpdateStaus(v);
|
360
|
+
}
|
361
|
+
|
362
|
+
int resolv(replicationNotify* nf, int type, const connMgr::records& recs, int defValue)
|
363
|
+
{
|
364
|
+
if (nf)
|
365
|
+
defValue = nf->onResolvError(type, recs);
|
366
|
+
return defValue;
|
367
|
+
}
|
368
|
+
|
369
|
+
__int64 getSlaveIOPos(const connMgr::records& recs)
|
370
|
+
{
|
371
|
+
if (recs.size() > SLAVE_STATUS_READ_MASTER_LOG_POS)
|
372
|
+
return recs[SLAVE_STATUS_READ_MASTER_LOG_POS].longValue;
|
373
|
+
return 0;
|
374
|
+
}
|
375
|
+
|
376
|
+
std::string getSkipGtid(const connMgr::records& recs)
|
377
|
+
{
|
378
|
+
string s;
|
379
|
+
if (recs.size() <= SLAVE_STATUS_EXECUTED_GTID_SET)
|
380
|
+
return s;
|
381
|
+
const char* uuid = recs[SLAVE_STATUS_MASTER_UUID].name;
|
382
|
+
char buf[1024];
|
383
|
+
char* p = (char*)recs[SLAVE_STATUS_EXECUTED_GTID_SET].name;
|
384
|
+
if (recs[SLAVE_STATUS_EXECUTED_GTID_SET].type == 2)
|
385
|
+
p = (char*)recs[SLAVE_STATUS_EXECUTED_GTID_SET].longValue;
|
386
|
+
|
387
|
+
p = strstr(p, uuid);
|
388
|
+
if (!p)
|
389
|
+
{ // the first transaction error
|
390
|
+
s = uuid;
|
391
|
+
return s + ":1";
|
392
|
+
}
|
393
|
+
strcpy_s(buf, MAX_PATH, p);
|
394
|
+
p = buf;
|
395
|
+
char* pp = strchr(p, ',');
|
396
|
+
if (pp) *pp = 0x00;
|
397
|
+
pp = strrchr(p, ':');
|
398
|
+
if (pp)
|
399
|
+
{
|
400
|
+
*pp = 0x00;
|
401
|
+
s = p;
|
402
|
+
s += ":";
|
403
|
+
p = pp+1;
|
404
|
+
pp = strchr(p, '-');
|
405
|
+
if (pp) p = pp +1;
|
406
|
+
unsigned __int64 v = _atoi64(p);
|
407
|
+
++v;
|
408
|
+
_i64toa_s(v, buf, MAX_PATH, 10);
|
409
|
+
s += buf;
|
410
|
+
}
|
411
|
+
return s;
|
412
|
+
}
|
413
|
+
|
414
|
+
bool isGtidAutoPos(const connMgr::records& recs)
|
415
|
+
{
|
416
|
+
return recs[SLAVE_STATUS_AUTO_POSITION].longValue != 0;
|
417
|
+
}
|
418
|
+
|
419
|
+
__int64 getSlaveExecPos(const connMgr::records& recs)
|
420
|
+
{
|
421
|
+
if (recs.size() > SLAVE_STATUS_EXEC_MASTER_LOG_POS)
|
422
|
+
return recs[SLAVE_STATUS_EXEC_MASTER_LOG_POS].longValue;
|
423
|
+
return 0;
|
424
|
+
}
|
425
|
+
|
426
|
+
bool isPosBrokn(const connMgr::records& recs)
|
427
|
+
{
|
428
|
+
__int64 iop = getSlaveIOPos(recs);
|
429
|
+
__int64 exp = getSlaveExecPos(recs);
|
430
|
+
return exp > iop;
|
431
|
+
}
|
432
|
+
|
433
|
+
bool isSamePosAsSlaveExecPos(const connMgr::records& recs, binlogPos& bpos)
|
434
|
+
{
|
435
|
+
return (strcmp(recs[SLAVE_STATUS_MASTER_LOG_FILE].name, bpos.filename)) == 0 &&
|
436
|
+
(recs[SLAVE_STATUS_EXEC_MASTER_LOG_POS].longValue == bpos.pos);
|
437
|
+
}
|
438
|
+
|
439
|
+
bool isSlaveSqlRunning(const connMgr::records& recs)
|
440
|
+
{
|
441
|
+
return strcmp(recs[SLAVE_STATUS_SLAVE_SQL_RUNNING].name, "Yes") == 0;
|
442
|
+
}
|
443
|
+
|
444
|
+
bool isSlaveIoRunning(const connMgr::records& recs)
|
445
|
+
{
|
446
|
+
return strcmp(recs[SLAVE_STATUS_SLAVE_IO_RUNNING].name, "Yes") == 0;
|
447
|
+
}
|
448
|
+
|
449
|
+
int getSlaveIoErrno(const connMgr::records& recs)
|
450
|
+
{
|
451
|
+
if (recs.size() > SLAVE_STATUS_LAST_IO_ERRNO)
|
452
|
+
return (int)recs[SLAVE_STATUS_LAST_IO_ERRNO].longValue;
|
453
|
+
return 0;
|
454
|
+
}
|
455
|
+
|
456
|
+
bool replSlave::resolvSqlError(const connMgr::records& recs,
|
457
|
+
binlogPos& bpos, replicationNotify* nf)
|
458
|
+
{
|
459
|
+
int ret = resolv(nf, ERROR_SQL_THREAD, recs, RESOLV_RESULT_CANCEL);
|
460
|
+
if (RESOLV_RESULT_CANCEL == ret)
|
461
|
+
THROW_BZS_ERROR_WITH_MSG(
|
462
|
+
_T("SQL thread has error(s).\nPlease retry after remove error(s)."));
|
463
|
+
else if (RESOLV_RESULT_YES == ret)
|
464
|
+
{
|
465
|
+
skipLogEvent(getSkipGtid(recs).c_str());
|
466
|
+
startUntil(bpos);
|
467
|
+
return false;
|
468
|
+
}else
|
469
|
+
stopAndReset();
|
470
|
+
return true;
|
471
|
+
}
|
472
|
+
|
473
|
+
bool replSlave::resolvIOError(const connMgr::records& recs, replicationNotify* nf)
|
474
|
+
{
|
475
|
+
int ret = resolv(nf, ERROR_IO_THREAD, recs, RESOLV_RESULT_CANCEL);
|
476
|
+
if(RESOLV_RESULT_YES != ret)
|
477
|
+
THROW_BZS_ERROR_WITH_MSG(_T("IO thread has error(s).\nPlease retry after remove error(s)."));
|
478
|
+
stopAndReset();
|
479
|
+
|
480
|
+
return true;
|
481
|
+
}
|
482
|
+
|
483
|
+
bool replSlave::resolvBroknError(const connMgr::records& recs, replicationNotify* nf)
|
484
|
+
{
|
485
|
+
int ret = resolv(nf, ERROR_LOG_BROKN, recs, RESOLV_RESULT_CANCEL);
|
486
|
+
if(RESOLV_RESULT_YES !=ret)
|
487
|
+
THROW_BZS_ERROR_WITH_MSG(_T("Log position error.\nRebuild of replication is required."));
|
488
|
+
stopAndReset();
|
489
|
+
return true;
|
490
|
+
}
|
491
|
+
|
492
|
+
string toUtf8(const _tstring& s)
|
493
|
+
{
|
494
|
+
#ifdef _UNICODE
|
495
|
+
char tmp[MAX_PATH]={0};
|
496
|
+
WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, tmp, MAX_PATH, NULL, NULL);
|
497
|
+
return tmp;
|
498
|
+
#else
|
499
|
+
return s;
|
500
|
+
#endif
|
501
|
+
}
|
502
|
+
|
503
|
+
//------------------------------------------------------------------------------
|
504
|
+
// class replSlave
|
505
|
+
//------------------------------------------------------------------------------
|
506
|
+
replSlave::replSlave(database_ptr db, replicationParam& pm, connMgr* mgr)
|
507
|
+
: m_db(db), m_mgr(mgr), m_mysqlGtid(false)
|
508
|
+
{
|
509
|
+
|
510
|
+
if (pm.type == REP_TYPE_GTID_MA)
|
511
|
+
m_impl = new replImplMaria(db, pm); // mariadb gtid
|
512
|
+
else
|
513
|
+
{
|
514
|
+
btrVersions vers;
|
515
|
+
db->getBtrVersion(&vers);
|
516
|
+
validateStatus(db, _T("get slave version"));
|
517
|
+
btrVersion ver = vers.versions[VER_IDX_DB_SERVER];
|
518
|
+
if (ver.majorVersion == 5 && ver.minorVersion < 6)
|
519
|
+
m_impl = new replImpl(pm); // mysql maridb 5.5
|
520
|
+
else if (ver.isMariaDB())
|
521
|
+
m_impl = new replImplMaria(db, pm);// maridb 10.0 10.1
|
522
|
+
else
|
523
|
+
{
|
524
|
+
m_mysqlGtid = isMySqlGtidMode(mgr);
|
525
|
+
if (!m_mysqlGtid)
|
526
|
+
m_impl = new replImpl(pm); // 5.6 5.7 regacy
|
527
|
+
else if (ver.minorVersion > 6)
|
528
|
+
m_impl = new replImplMy57(pm);// 5.7 gtid
|
529
|
+
else
|
530
|
+
m_impl = new replImplMy(pm); // 5.6 gtid
|
531
|
+
}
|
532
|
+
}
|
533
|
+
}
|
534
|
+
|
535
|
+
replSlave::~replSlave()
|
536
|
+
{
|
537
|
+
delete m_impl;
|
538
|
+
}
|
539
|
+
|
540
|
+
void replSlave::validateError(const _TCHAR* msg)
|
541
|
+
{
|
542
|
+
if (m_db->stat() == 0 || m_impl->ignoreError(m_db->stat()))
|
543
|
+
return;
|
544
|
+
validateStatus(m_db, msg);
|
545
|
+
}
|
546
|
+
|
547
|
+
void replSlave::setSkipError(const char* gtid)
|
548
|
+
{
|
549
|
+
m_impl->setSlaveSkipError(m_db, gtid);
|
550
|
+
}
|
551
|
+
|
552
|
+
void replSlave::stop(bool all)
|
553
|
+
{
|
554
|
+
string s;
|
555
|
+
if (all)
|
556
|
+
s = m_impl->stopAllSlaveSql();
|
557
|
+
else
|
558
|
+
s = m_impl->stopSlaveSql();
|
559
|
+
m_db->execSql(s.c_str());
|
560
|
+
validateError(_T("stop slave"));
|
561
|
+
}
|
562
|
+
|
563
|
+
void replSlave::start(bool all)
|
564
|
+
{
|
565
|
+
if (all)
|
566
|
+
execSql(m_db, m_impl->startAllSlaveSql().c_str());
|
567
|
+
else
|
568
|
+
execSql(m_db, m_impl->startSlaveSql().c_str());
|
569
|
+
}
|
570
|
+
|
571
|
+
void replSlave::startNoThrow()
|
572
|
+
{
|
573
|
+
m_db->execSql(m_impl->startSlaveSql().c_str());
|
574
|
+
}
|
575
|
+
|
576
|
+
void replSlave::reset()
|
577
|
+
{
|
578
|
+
string s = m_impl->resetSlaveSql();
|
579
|
+
m_db->execSql(s.c_str());
|
580
|
+
validateError(_T("reset slave"));
|
581
|
+
}
|
582
|
+
|
583
|
+
void replSlave::resetAll()
|
584
|
+
{
|
585
|
+
string s = m_impl->resetSlaveAllSql();
|
586
|
+
m_db->execSql(s.c_str());
|
587
|
+
validateError(_T("reset slave all"));
|
588
|
+
}
|
589
|
+
|
590
|
+
bool replSlave::startUntil(binlogPos& bpos)
|
591
|
+
{
|
592
|
+
m_db->execSql(m_impl->startSlaveUntilSql(bpos).c_str());
|
593
|
+
if ((m_db->stat() == ER_BAD_SLAVE) ||
|
594
|
+
(m_impl->pm.type == REP_TYPE_GTID_MA &&
|
595
|
+
m_db->stat() == ER_UNTIL_REQUIRES_USING_GTID))
|
596
|
+
return false;
|
597
|
+
if (m_db->stat())
|
598
|
+
nstable::throwError(_T("start slave until"), m_db->stat());
|
599
|
+
return true;
|
600
|
+
}
|
601
|
+
|
602
|
+
void replSlave::changeMaster(const binlogPos* bpos)
|
603
|
+
{
|
604
|
+
m_impl->setGtidSlavePos(m_db, *bpos, m_mgr);
|
605
|
+
execSql(m_db, m_impl->changeMasterSql(*bpos, m_mgr).c_str());
|
606
|
+
}
|
607
|
+
|
608
|
+
void replSlave::switchMaster(autoPosType v)
|
609
|
+
{
|
610
|
+
execSql(m_db, m_impl->switchMasterSql(v).c_str());
|
611
|
+
}
|
612
|
+
|
613
|
+
void replSlave::resetMaster()
|
614
|
+
{
|
615
|
+
execSql(m_db, "reset master");
|
616
|
+
}
|
617
|
+
|
618
|
+
void replSlave::skipLogEvent(const char* gtid)
|
619
|
+
{
|
620
|
+
stop(one);
|
621
|
+
setSkipError(gtid);
|
622
|
+
}
|
623
|
+
|
624
|
+
void replSlave::stopAndReset()
|
625
|
+
{
|
626
|
+
stop(one);
|
627
|
+
reset();
|
628
|
+
}
|
629
|
+
|
630
|
+
const replicationParam& replSlave::params() const
|
631
|
+
{
|
632
|
+
return m_impl->pm;
|
633
|
+
}
|
634
|
+
|
635
|
+
bool replSlave::isSlaveSync(binlogPos& bpos, replicationNotify* nf)
|
636
|
+
{
|
637
|
+
while (1)
|
638
|
+
{
|
639
|
+
const connMgr::records& recs = m_mgr->slaveStatus(m_impl->pm.master.channel.c_str());
|
640
|
+
validateStatus(m_mgr, _T("slave status"));
|
641
|
+
/* In the case of first-time replication, size is zero. */
|
642
|
+
if (recs.size() == 0)
|
643
|
+
return true;
|
644
|
+
bool isIgnoreBrokn = isMysqlGtidMode() && isGtidAutoPos(recs);
|
645
|
+
if (!isIgnoreBrokn && isPosBrokn(recs))
|
646
|
+
{
|
647
|
+
if (resolvBroknError(recs, nf))
|
648
|
+
return true;
|
649
|
+
}
|
650
|
+
if (isSamePosAsSlaveExecPos(recs, bpos))
|
651
|
+
return true;
|
652
|
+
|
653
|
+
if ((isSlaveIoRunning(recs) == false) && getSlaveIoErrno(recs))
|
654
|
+
{
|
655
|
+
if (resolvIOError(recs, nf))
|
656
|
+
return true;
|
657
|
+
}
|
658
|
+
else if (isSlaveSqlRunning(recs) == false)
|
659
|
+
{
|
660
|
+
if (resolvSqlError(recs, bpos, nf))
|
661
|
+
return true;
|
662
|
+
}
|
663
|
+
else
|
664
|
+
break;
|
665
|
+
Sleep(10);
|
666
|
+
}
|
667
|
+
return false;
|
668
|
+
}
|
669
|
+
|
670
|
+
void replSlave::waitForSlaveSync(binlogPos& bpos, int waitTime, replicationNotify* nf)
|
671
|
+
{
|
672
|
+
Sleep(100);
|
673
|
+
bool slaveSync = false;
|
674
|
+
int n = waitTime * 100;
|
675
|
+
for (int nn = 0;nn < 10; ++nn)
|
676
|
+
{
|
677
|
+
if (isSlaveSync(bpos, nf))
|
678
|
+
{
|
679
|
+
slaveSync = true;
|
680
|
+
break;
|
681
|
+
}
|
682
|
+
for (int i= 0;i < n; ++i)
|
683
|
+
{
|
684
|
+
notyfy(nf, REP_NF_WAIT);
|
685
|
+
Sleep(10);
|
686
|
+
}
|
687
|
+
}
|
688
|
+
if (!slaveSync)
|
689
|
+
THROW_BZS_ERROR_WITH_MSG(
|
690
|
+
_T("The slave SQL thread could not be executed")
|
691
|
+
_T("until the target of the log position in time"));
|
692
|
+
}
|
693
|
+
|
694
|
+
|
695
|
+
|
696
|
+
|