1 /*
2 Copyright (c) 2008, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <AtrtClient.hpp>
26 #include <NDBT_Output.hpp>
27 #include <NdbSleep.h>
28 #include <NdbEnv.h>
29
AtrtClient(const char * _group_suffix)30 AtrtClient::AtrtClient(const char* _group_suffix)
31 : DbUtil("atrt", _group_suffix)
32 {
33 }
34
35
AtrtClient(MYSQL * mysql)36 AtrtClient::AtrtClient(MYSQL* mysql)
37 : DbUtil(mysql)
38 {
39 }
40
41
~AtrtClient()42 AtrtClient::~AtrtClient(){
43 }
44
45
46 int
writeCommand(AtrtCommandType _type,const Properties & args)47 AtrtClient::writeCommand(AtrtCommandType _type,
48 const Properties& args){
49 if (!isConnected())
50 return false;
51
52 BaseString sql;
53 sql.assfmt("INSERT command ( ");
54
55 const char* name;
56 {
57 Properties::Iterator iter(&args);
58 while((name= iter.next())){
59 sql.appfmt("%s, ", name);
60 }
61 }
62
63 sql.appfmt(" state, cmd) VALUES (");
64
65 {
66 Properties::Iterator iter(&args);
67 while((name= iter.next())){
68 PropertiesType t;
69 Uint32 val_i;
70 BaseString val_s;
71 args.getTypeOf(name, &t);
72 switch(t) {
73 case PropertiesType_Uint32:
74 args.get(name, &val_i);
75 sql.appfmt("%d, ", val_i);
76 break;
77 case PropertiesType_char:
78 args.get(name, val_s);
79 sql.appfmt("'%s', ", val_s.c_str());
80 break;
81 default:
82 require(false);
83 break;
84 }
85 }
86 }
87
88 sql.appfmt("'new', %d)", _type);
89 if (!doQuery(sql)){
90 return -1;
91 }
92
93 return (int)mysql_insert_id(m_mysql);
94 }
95
96
97 bool
readCommand(uint command_id,SqlResultSet & result)98 AtrtClient::readCommand(uint command_id,
99 SqlResultSet& result){
100 Properties args;
101 args.put("0", command_id);
102 return runQuery("SELECT * FROM command WHERE id = ?",
103 args,
104 result);
105 }
106
107
108 bool
doCommand(AtrtCommandType type,const Properties & args)109 AtrtClient::doCommand(AtrtCommandType type,
110 const Properties& args){
111
112 int running_timeout= 10;
113 int total_timeout= 120;
114 int commandId= writeCommand(type,
115 args);
116 if (commandId == -1){
117 g_err << "Failed to write command" << endl;
118 return false;
119 }
120
121 while (true){
122
123 SqlResultSet result;
124 if (!readCommand(commandId, result))
125 {
126 result.print();
127 g_err << "Failed to read command "<< commandId << endl;
128 return false;
129 }
130
131 // Get first row
132 result.next();
133
134 // Check if command has completed
135 BaseString state(result.column("state"));
136 if (state == "done") {
137 return true;
138 }
139
140 if (state == "new"){
141 if (!running_timeout--){
142 g_err << "Timeout while waiting for command "
143 << commandId << " to start run" << endl;
144 return false;
145 }
146 }
147 else if (!total_timeout--){
148 g_err << "Timeout while waiting for result of command "
149 << commandId << endl;
150 return false;
151 }
152
153
154 NdbSleep_SecSleep(1);
155 }
156
157 return false;
158 }
159
160
161 bool
changeVersion(int process_id,const char * process_args)162 AtrtClient::changeVersion(int process_id,
163 const char* process_args){
164 Properties args;
165 args.put("process_id", process_id);
166 args.put("process_args", process_args);
167 return doCommand(ATCT_CHANGE_VERSION, args);
168 }
169
170
171 bool
resetProc(int process_id)172 AtrtClient::resetProc(int process_id){
173 Properties args;
174 args.put("process_id", process_id);
175 return doCommand(ATCT_RESET_PROC, args);
176 }
177
178
179 bool
getConnectString(int cluster_id,SqlResultSet & result)180 AtrtClient::getConnectString(int cluster_id, SqlResultSet& result){
181 Properties args;
182 args.put("0", cluster_id);
183 return doQuery("SELECT value as connectstring " \
184 "FROM cluster c, process p, host h, options o " \
185 "WHERE c.id=p.cluster_id AND p.host_id=h.id AND " \
186 "p.id=o.process_id AND c.id=? AND " \
187 "o.name='--ndb-connectstring=' AND type='ndb_mgmd'",
188 args,
189 result);
190 }
191
192
193 bool
getClusters(SqlResultSet & result)194 AtrtClient::getClusters(SqlResultSet& result){
195 Properties args;
196 return runQuery("SELECT id, name FROM cluster WHERE name != '.atrt'",
197 args,
198 result);
199 }
200
201
202 bool
getMgmds(int cluster_id,SqlResultSet & result)203 AtrtClient::getMgmds(int cluster_id, SqlResultSet& result){
204 Properties args;
205 args.put("0", cluster_id);
206 return runQuery("SELECT * FROM process WHERE cluster_id=? and type='ndb_mgmd'",
207 args,
208 result);
209 }
210
211 bool
getNdbds(int cluster_id,SqlResultSet & result)212 AtrtClient::getNdbds(int cluster_id, SqlResultSet& result){
213 Properties args;
214 args.put("0", cluster_id);
215 return runQuery("SELECT * FROM process WHERE cluster_id=? and type='ndbd'",
216 args,
217 result);
218 }
219
220 int
getOwnProcessId()221 AtrtClient::getOwnProcessId()
222 {
223 /**
224 * Put in env for simplicity
225 */
226 char buf[100];
227 if (NdbEnv_GetEnv("ATRT_PID", buf, sizeof(buf)))
228 {
229 return atoi(buf);
230 }
231 return -1;
232 }
233