00001 /* Copyright (C) 2003 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 00018 #include <ndb_global.h> 00019 #include <ndb_opts.h> 00020 00021 #include <mgmapi.h> 00022 #include <NdbMain.h> 00023 #include <NdbOut.hpp> 00024 #include <NdbSleep.h> 00025 #include <kernel/ndb_limits.h> 00026 00027 #include <NDBT.hpp> 00028 00029 int 00030 waitClusterStatus(const char* _addr, ndb_mgm_node_status _status, 00031 unsigned int _timeout); 00032 00033 enum ndb_waiter_options { 00034 OPT_WAIT_STATUS_NOT_STARTED = NDB_STD_OPTIONS_LAST 00035 }; 00036 NDB_STD_OPTS_VARS; 00037 00038 static int _no_contact = 0; 00039 static int _not_started = 0; 00040 static int _timeout = 120; 00041 static struct my_option my_long_options[] = 00042 { 00043 NDB_STD_OPTS("ndb_desc"), 00044 { "no-contact", 'n', "Wait for cluster no contact", 00045 (gptr*) &_no_contact, (gptr*) &_no_contact, 0, 00046 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00047 { "not-started", OPT_WAIT_STATUS_NOT_STARTED, "Wait for cluster not started", 00048 (gptr*) &_not_started, (gptr*) &_not_started, 0, 00049 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00050 { "timeout", 't', "Timeout to wait", 00051 (gptr*) &_timeout, (gptr*) &_timeout, 0, 00052 GET_INT, REQUIRED_ARG, 120, 0, 0, 0, 0, 0 }, 00053 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} 00054 }; 00055 00056 static void usage() 00057 { 00058 ndb_std_print_version(); 00059 my_print_help(my_long_options); 00060 my_print_variables(my_long_options); 00061 } 00062 00063 int main(int argc, char** argv){ 00064 NDB_INIT(argv[0]); 00065 const char *load_default_groups[]= { "mysql_cluster",0 }; 00066 load_defaults("my",load_default_groups,&argc,&argv); 00067 const char* _hostName = NULL; 00068 int ho_error; 00069 #ifndef DBUG_OFF 00070 opt_debug= "d:t:O,/tmp/ndb_waiter.trace"; 00071 #endif 00072 if ((ho_error=handle_options(&argc, &argv, my_long_options, 00073 ndb_std_get_one_option))) 00074 return NDBT_ProgramExit(NDBT_WRONGARGS); 00075 00076 _hostName = argv[0]; 00077 00078 if (_hostName == 0) 00079 _hostName= opt_connect_str; 00080 00081 enum ndb_mgm_node_status wait_status; 00082 if (_no_contact) 00083 { 00084 wait_status= NDB_MGM_NODE_STATUS_NO_CONTACT; 00085 } 00086 else if (_not_started) 00087 { 00088 wait_status= NDB_MGM_NODE_STATUS_NOT_STARTED; 00089 } 00090 else 00091 { 00092 wait_status= NDB_MGM_NODE_STATUS_STARTED; 00093 } 00094 00095 if (waitClusterStatus(_hostName, wait_status, _timeout*10) != 0) 00096 return NDBT_ProgramExit(NDBT_FAILED); 00097 return NDBT_ProgramExit(NDBT_OK); 00098 } 00099 00100 #define MGMERR(h) \ 00101 ndbout << "latest_error="<<ndb_mgm_get_latest_error(h) \ 00102 << ", line="<<ndb_mgm_get_latest_error_line(h) \ 00103 << endl; 00104 00105 NdbMgmHandle handle= NULL; 00106 00107 Vector<ndb_mgm_node_state> ndbNodes; 00108 Vector<ndb_mgm_node_state> mgmNodes; 00109 Vector<ndb_mgm_node_state> apiNodes; 00110 00111 int 00112 getStatus(){ 00113 int retries = 0; 00114 struct ndb_mgm_cluster_state * status; 00115 struct ndb_mgm_node_state * node; 00116 00117 ndbNodes.clear(); 00118 mgmNodes.clear(); 00119 apiNodes.clear(); 00120 00121 while(retries < 10){ 00122 status = ndb_mgm_get_status(handle); 00123 if (status == NULL){ 00124 ndbout << "status==NULL, retries="<<retries<<endl; 00125 MGMERR(handle); 00126 retries++; 00127 ndb_mgm_disconnect(handle); 00128 if (ndb_mgm_connect(handle,0,0,1)) { 00129 MGMERR(handle); 00130 g_err << "Reconnect failed" << endl; 00131 break; 00132 } 00133 continue; 00134 } 00135 int count = status->no_of_nodes; 00136 for (int i = 0; i < count; i++){ 00137 node = &status->node_states[i]; 00138 switch(node->node_type){ 00139 case NDB_MGM_NODE_TYPE_NDB: 00140 ndbNodes.push_back(*node); 00141 break; 00142 case NDB_MGM_NODE_TYPE_MGM: 00143 mgmNodes.push_back(*node); 00144 break; 00145 case NDB_MGM_NODE_TYPE_API: 00146 apiNodes.push_back(*node); 00147 break; 00148 default: 00149 if(node->node_status == NDB_MGM_NODE_STATUS_UNKNOWN || 00150 node->node_status == NDB_MGM_NODE_STATUS_NO_CONTACT){ 00151 retries++; 00152 ndbNodes.clear(); 00153 mgmNodes.clear(); 00154 apiNodes.clear(); 00155 free(status); 00156 status = NULL; 00157 count = 0; 00158 00159 ndbout << "kalle"<< endl; 00160 break; 00161 } 00162 abort(); 00163 break; 00164 } 00165 } 00166 if(status == 0){ 00167 ndbout << "status == 0" << endl; 00168 continue; 00169 } 00170 free(status); 00171 return 0; 00172 } 00173 00174 g_err << "getStatus failed" << endl; 00175 return -1; 00176 } 00177 00178 int 00179 waitClusterStatus(const char* _addr, 00180 ndb_mgm_node_status _status, 00181 unsigned int _timeout) 00182 { 00183 int _startphase = -1; 00184 00185 int _nodes[MAX_NDB_NODES]; 00186 int _num_nodes = 0; 00187 00188 handle = ndb_mgm_create_handle(); 00189 if (handle == NULL){ 00190 g_err << "handle == NULL" << endl; 00191 return -1; 00192 } 00193 g_info << "Connecting to mgmsrv at " << _addr << endl; 00194 if (ndb_mgm_set_connectstring(handle, _addr)) 00195 { 00196 MGMERR(handle); 00197 g_err << "Connectstring " << _addr << " invalid" << endl; 00198 return -1; 00199 } 00200 if (ndb_mgm_connect(handle,0,0,1)) { 00201 MGMERR(handle); 00202 g_err << "Connection to " << _addr << " failed" << endl; 00203 return -1; 00204 } 00205 00206 if (getStatus() != 0) 00207 return -1; 00208 00209 // Collect all nodes into nodes 00210 for (size_t i = 0; i < ndbNodes.size(); i++){ 00211 _nodes[i] = ndbNodes[i].node_id; 00212 _num_nodes++; 00213 } 00214 00215 unsigned int attempts = 0; 00216 unsigned int resetAttempts = 0; 00217 const unsigned int MAX_RESET_ATTEMPTS = 10; 00218 bool allInState = false; 00219 while (allInState == false){ 00220 if (_timeout > 0 && attempts > _timeout){ 00225 bool waitMore = false; 00230 if(_status == NDB_MGM_NODE_STATUS_STARTED){ 00231 waitMore = true; 00236 for (size_t n = 0; n < ndbNodes.size(); n++){ 00237 if (ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTED && 00238 ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTING) 00239 waitMore = false; 00240 00241 } 00242 } 00243 00244 if (!waitMore || resetAttempts > MAX_RESET_ATTEMPTS){ 00245 g_err << "waitNodeState(" 00246 << ndb_mgm_get_node_status_string(_status) 00247 <<", "<<_startphase<<")" 00248 << " timeout after " << attempts <<" attemps" << endl; 00249 return -1; 00250 } 00251 00252 g_err << "waitNodeState(" 00253 << ndb_mgm_get_node_status_string(_status) 00254 <<", "<<_startphase<<")" 00255 << " resetting number of attempts " 00256 << resetAttempts << endl; 00257 attempts = 0; 00258 resetAttempts++; 00259 00260 } 00261 00262 allInState = true; 00263 if (getStatus() != 0){ 00264 g_err << "getStatus != 0" << endl; 00265 return -1; 00266 } 00267 00268 // ndbout << "waitNodeState; _num_nodes = " << _num_nodes << endl; 00269 // for (int i = 0; i < _num_nodes; i++) 00270 // ndbout << " node["<<i<<"] =" <<_nodes[i] << endl; 00271 00272 for (int i = 0; i < _num_nodes; i++){ 00273 ndb_mgm_node_state* ndbNode = NULL; 00274 for (size_t n = 0; n < ndbNodes.size(); n++){ 00275 if (ndbNodes[n].node_id == _nodes[i]) 00276 ndbNode = &ndbNodes[n]; 00277 } 00278 00279 if(ndbNode == NULL){ 00280 allInState = false; 00281 continue; 00282 } 00283 00284 g_info << "State node " << ndbNode->node_id << " " 00285 << ndb_mgm_get_node_status_string(ndbNode->node_status)<< endl; 00286 00287 assert(ndbNode != NULL); 00288 00289 if(_status == NDB_MGM_NODE_STATUS_STARTING && 00290 ((ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTING && 00291 ndbNode->start_phase >= _startphase) || 00292 (ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTED))) 00293 continue; 00294 00295 if (_status == NDB_MGM_NODE_STATUS_STARTING){ 00296 g_info << "status = " 00297 << ndb_mgm_get_node_status_string(ndbNode->node_status) 00298 <<", start_phase="<<ndbNode->start_phase<<endl; 00299 if (ndbNode->node_status != _status) { 00300 if (ndbNode->node_status < _status) 00301 allInState = false; 00302 else 00303 g_info << "node_status(" << (unsigned)ndbNode->node_status 00304 << ") != _status("<< (unsigned)_status << ")" <<endl; 00305 } else if (ndbNode->start_phase < _startphase) 00306 allInState = false; 00307 } else { 00308 if (ndbNode->node_status != _status) 00309 allInState = false; 00310 } 00311 } 00312 g_info << "Waiting for cluster enter state " 00313 << ndb_mgm_get_node_status_string(_status)<< endl; 00314 NdbSleep_MilliSleep(100); 00315 attempts++; 00316 } 00317 return 0; 00318 } 00319 00320 template class Vector<ndb_mgm_node_state>;
1.4.7

