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
|
@@ -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
|
+
|