mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / tools / waiter.cpp
bloba5e02d1c96cbb3a21ba287fc3b196a093a12be1a
1 /* Copyright (c) 2003-2008 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
17 #include <ndb_global.h>
18 #include <ndb_opts.h>
20 #include <mgmapi.h>
21 #include <NdbMain.h>
22 #include <NdbOut.hpp>
23 #include <NdbSleep.h>
25 #include <NDBT.hpp>
27 static int
28 waitClusterStatus(const char* _addr, ndb_mgm_node_status _status);
30 enum ndb_waiter_options {
31 OPT_WAIT_STATUS_NOT_STARTED = NDB_STD_OPTIONS_LAST,
32 OPT_WAIT_STATUS_SINGLE_USER
34 NDB_STD_OPTS_VARS;
36 static int _no_contact = 0;
37 static int _not_started = 0;
38 static int _single_user = 0;
39 static int _timeout = 120;
41 const char *load_default_groups[]= { "mysql_cluster",0 };
43 static struct my_option my_long_options[] =
45 NDB_STD_OPTS("ndb_desc"),
46 { "no-contact", 'n', "Wait for cluster no contact",
47 (uchar**) &_no_contact, (uchar**) &_no_contact, 0,
48 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
49 { "not-started", OPT_WAIT_STATUS_NOT_STARTED, "Wait for cluster not started",
50 (uchar**) &_not_started, (uchar**) &_not_started, 0,
51 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
52 { "single-user", OPT_WAIT_STATUS_SINGLE_USER,
53 "Wait for cluster to enter single user mode",
54 (uchar**) &_single_user, (uchar**) &_single_user, 0,
55 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
56 { "timeout", 't', "Timeout to wait in seconds",
57 (uchar**) &_timeout, (uchar**) &_timeout, 0,
58 GET_INT, REQUIRED_ARG, 120, 0, 0, 0, 0, 0 },
59 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
63 static void usage()
65 ndb_std_print_version();
66 print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
67 puts("");
68 my_print_help(my_long_options);
69 my_print_variables(my_long_options);
73 int main(int argc, char** argv){
74 NDB_INIT(argv[0]);
75 load_defaults("my",load_default_groups,&argc,&argv);
76 const char* _hostName = NULL;
78 #ifndef DBUG_OFF
79 opt_debug= "d:t:O,/tmp/ndb_waiter.trace";
80 #endif
82 if (handle_options(&argc, &argv, my_long_options,
83 ndb_std_get_one_option))
84 return NDBT_ProgramExit(NDBT_WRONGARGS);
86 _hostName = argv[0];
88 if (_hostName == 0)
89 _hostName= opt_connect_str;
91 enum ndb_mgm_node_status wait_status;
92 if (_no_contact)
94 wait_status= NDB_MGM_NODE_STATUS_NO_CONTACT;
96 else if (_not_started)
98 wait_status= NDB_MGM_NODE_STATUS_NOT_STARTED;
100 else if (_single_user)
102 wait_status= NDB_MGM_NODE_STATUS_SINGLEUSER;
104 else
106 wait_status= NDB_MGM_NODE_STATUS_STARTED;
109 if (waitClusterStatus(_hostName, wait_status) != 0)
110 return NDBT_ProgramExit(NDBT_FAILED);
111 return NDBT_ProgramExit(NDBT_OK);
114 #define MGMERR(h) \
115 ndbout << "latest_error="<<ndb_mgm_get_latest_error(h) \
116 << ", line="<<ndb_mgm_get_latest_error_line(h) \
117 << endl;
119 NdbMgmHandle handle= NULL;
121 Vector<ndb_mgm_node_state> ndbNodes;
123 int
124 getStatus(){
125 int retries = 0;
126 struct ndb_mgm_cluster_state * status;
127 struct ndb_mgm_node_state * node;
129 ndbNodes.clear();
131 while(retries < 10){
132 status = ndb_mgm_get_status(handle);
133 if (status == NULL){
134 ndbout << "status==NULL, retries="<<retries<<endl;
135 MGMERR(handle);
136 retries++;
137 ndb_mgm_disconnect(handle);
138 if (ndb_mgm_connect(handle,0,0,1)) {
139 MGMERR(handle);
140 g_err << "Reconnect failed" << endl;
141 break;
143 continue;
145 int count = status->no_of_nodes;
146 for (int i = 0; i < count; i++){
147 node = &status->node_states[i];
148 switch(node->node_type){
149 case NDB_MGM_NODE_TYPE_NDB:
150 ndbNodes.push_back(*node);
151 break;
152 case NDB_MGM_NODE_TYPE_MGM:
153 /* Don't care about MGM nodes */
154 break;
155 case NDB_MGM_NODE_TYPE_API:
156 /* Don't care about API nodes */
157 break;
158 default:
159 if(node->node_status == NDB_MGM_NODE_STATUS_UNKNOWN ||
160 node->node_status == NDB_MGM_NODE_STATUS_NO_CONTACT){
161 retries++;
162 ndbNodes.clear();
163 free(status);
164 status = NULL;
165 count = 0;
167 ndbout << "kalle"<< endl;
168 break;
170 abort();
171 break;
174 if(status == 0){
175 ndbout << "status == 0" << endl;
176 continue;
178 free(status);
179 return 0;
182 return -1;
185 static int
186 waitClusterStatus(const char* _addr,
187 ndb_mgm_node_status _status)
189 int _startphase = -1;
191 /* Ignore SIGPIPE */
192 signal(SIGPIPE, SIG_IGN);
194 handle = ndb_mgm_create_handle();
195 if (handle == NULL){
196 g_err << "Could not create ndb_mgm handle" << endl;
197 return -1;
199 g_info << "Connecting to mgmsrv at " << _addr << endl;
200 if (ndb_mgm_set_connectstring(handle, _addr))
202 MGMERR(handle);
203 g_err << "Connectstring " << _addr << " invalid" << endl;
204 return -1;
206 if (ndb_mgm_connect(handle,0,0,1)) {
207 MGMERR(handle);
208 g_err << "Connection to " << _addr << " failed" << endl;
209 return -1;
212 int attempts = 0;
213 int resetAttempts = 0;
214 const int MAX_RESET_ATTEMPTS = 10;
215 bool allInState = false;
216 int timeout_ms= _timeout * 10; /* In number of 100 milliseconds */
217 while (allInState == false){
218 if (_timeout > 0 && attempts > _timeout){
220 * Timeout has expired waiting for the nodes to enter
221 * the state we want
223 bool waitMore = false;
225 * Make special check if we are waiting for
226 * cluster to become started
228 if(_status == NDB_MGM_NODE_STATUS_STARTED){
229 waitMore = true;
231 * First check if any node is not starting
232 * then it's no idea to wait anymore
234 for (size_t n = 0; n < ndbNodes.size(); n++){
235 if (ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTED &&
236 ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTING)
237 waitMore = false;
242 if (!waitMore || resetAttempts > MAX_RESET_ATTEMPTS){
243 g_err << "waitNodeState("
244 << ndb_mgm_get_node_status_string(_status)
245 <<", "<<_startphase<<")"
246 << " timeout after " << attempts <<" attemps" << endl;
247 return -1;
250 g_err << "waitNodeState("
251 << ndb_mgm_get_node_status_string(_status)
252 <<", "<<_startphase<<")"
253 << " resetting number of attempts "
254 << resetAttempts << endl;
255 attempts = 0;
256 resetAttempts++;
259 if (getStatus() != 0){
260 return -1;
263 /* Assume all nodes are in state(if there is any) */
264 allInState = (ndbNodes.size() > 0);
266 /* Loop through all nodes and check their state */
267 for (size_t n = 0; n < ndbNodes.size(); n++) {
268 ndb_mgm_node_state* ndbNode = &ndbNodes[n];
270 assert(ndbNode != NULL);
272 g_info << "Node " << ndbNode->node_id << ": "
273 << ndb_mgm_get_node_status_string(ndbNode->node_status)<< endl;
275 if (ndbNode->node_status != _status)
276 allInState = false;
279 if (!allInState) {
280 g_info << "Waiting for cluster enter state "
281 << ndb_mgm_get_node_status_string(_status)<< endl;
282 NdbSleep_MilliSleep(100);
285 attempts++;
287 return 0;
290 template class Vector<ndb_mgm_node_state>;