1 /* Copyright (c) 2003-2007 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 <NDBT_Test.hpp>
18 #include <HugoTransactions.hpp>
19 #include <UtilTransactions.hpp>
20 #include <NdbRestarter.hpp>
24 #include <mgmapi_debug.h>
25 #include <ndb_logevent.h>
26 #include <InputStream.hpp>
27 #include <signaldata/EventReport.hpp>
29 int runLoadTable(NDBT_Context
* ctx
, NDBT_Step
* step
){
31 int records
= ctx
->getNumRecords();
32 HugoTransactions
hugoTrans(*ctx
->getTab());
33 if (hugoTrans
.loadTable(GETNDB(step
), records
) != 0){
39 int runClearTable(NDBT_Context
* ctx
, NDBT_Step
* step
){
40 int records
= ctx
->getNumRecords();
42 UtilTransactions
utilTrans(*ctx
->getTab());
43 if (utilTrans
.clearTable2(GETNDB(step
), records
) != 0){
50 int create_index_on_pk(Ndb
* pNdb
, const char* tabName
){
53 const NdbDictionary::Table
* tab
= NDBT_Table::discoverTableFromDb(pNdb
,
57 const char* idxName
= "IDX_ON_PK";
58 ndbout
<< "Create: " <<idxName
<< "( ";
59 NdbDictionary::Index
pIdx(idxName
);
60 pIdx
.setTable(tabName
);
61 pIdx
.setType(NdbDictionary::Index::UniqueHashIndex
);
62 for (int c
= 0; c
< tab
->getNoOfPrimaryKeys(); c
++){
63 pIdx
.addIndexColumn(tab
->getPrimaryKey(c
));
64 ndbout
<< tab
->getPrimaryKey(c
)<<" ";
68 if (pNdb
->getDictionary()->createIndex(pIdx
) != 0){
69 ndbout
<< "FAILED!" << endl
;
70 const NdbError err
= pNdb
->getDictionary()->getNdbError();
74 ndbout
<< "OK!" << endl
;
79 int drop_index_on_pk(Ndb
* pNdb
, const char* tabName
){
81 const char* idxName
= "IDX_ON_PK";
82 ndbout
<< "Drop: " << idxName
;
83 if (pNdb
->getDictionary()->dropIndex(idxName
, tabName
) != 0){
84 ndbout
<< "FAILED!" << endl
;
85 const NdbError err
= pNdb
->getDictionary()->getNdbError();
89 ndbout
<< "OK!" << endl
;
95 #define CHECK(b) if (!(b)) { \
96 g_err << "ERR: "<< step->getName() \
97 << " failed on line " << __LINE__ << endl; \
98 result = NDBT_FAILED; \
101 int runTestSingleUserMode(NDBT_Context
* ctx
, NDBT_Step
* step
){
102 int result
= NDBT_OK
;
103 int loops
= ctx
->getNumLoops();
104 int records
= ctx
->getNumRecords();
105 Ndb
* pNdb
= GETNDB(step
);
106 NdbRestarter restarter
;
108 strncpy(tabName
, ctx
->getTab()->getName(), 255);
109 ndbout
<< "tabName="<<tabName
<<endl
;
113 HugoTransactions
hugoTrans(*ctx
->getTab());
114 UtilTransactions
utilTrans(*ctx
->getTab());
115 while (i
<loops
&& result
== NDBT_OK
) {
118 // Test that the single user mode api can do everything
119 CHECK(restarter
.enterSingleUserMode(pNdb
->getNodeId()) == 0);
120 CHECK(restarter
.waitClusterSingleUser(timeout
) == 0);
121 CHECK(hugoTrans
.loadTable(pNdb
, records
, 128) == 0);
122 CHECK(hugoTrans
.pkReadRecords(pNdb
, records
) == 0);
123 CHECK(hugoTrans
.pkUpdateRecords(pNdb
, records
) == 0);
124 CHECK(utilTrans
.selectCount(pNdb
, 64, &count
) == 0);
125 CHECK(count
== records
);
126 CHECK(hugoTrans
.pkDelRecords(pNdb
, records
/2) == 0);
127 CHECK(hugoTrans
.scanReadRecords(pNdb
, records
/2, 0, 64) == 0);
128 CHECK(utilTrans
.selectCount(pNdb
, 64, &count
) == 0);
129 CHECK(count
== (records
/2));
130 CHECK(utilTrans
.clearTable(pNdb
, records
/2) == 0);
131 CHECK(restarter
.exitSingleUserMode() == 0);
132 CHECK(restarter
.waitClusterStarted(timeout
) == 0);
134 // Test create index in single user mode
135 CHECK(restarter
.enterSingleUserMode(pNdb
->getNodeId()) == 0);
136 CHECK(restarter
.waitClusterSingleUser(timeout
) == 0);
137 CHECK(create_index_on_pk(pNdb
, tabName
) == 0);
138 CHECK(hugoTrans
.loadTable(pNdb
, records
, 128) == 0);
139 CHECK(hugoTrans
.pkReadRecords(pNdb
, records
) == 0);
140 CHECK(hugoTrans
.pkUpdateRecords(pNdb
, records
) == 0);
141 CHECK(utilTrans
.selectCount(pNdb
, 64, &count
) == 0);
142 CHECK(count
== records
);
143 CHECK(hugoTrans
.pkDelRecords(pNdb
, records
/2) == 0);
144 CHECK(drop_index_on_pk(pNdb
, tabName
) == 0);
145 CHECK(restarter
.exitSingleUserMode() == 0);
146 CHECK(restarter
.waitClusterStarted(timeout
) == 0);
148 // Test recreate index in single user mode
149 CHECK(create_index_on_pk(pNdb
, tabName
) == 0);
150 CHECK(hugoTrans
.loadTable(pNdb
, records
, 128) == 0);
151 CHECK(utilTrans
.selectCount(pNdb
, 64, &count
) == 0);
152 CHECK(restarter
.enterSingleUserMode(pNdb
->getNodeId()) == 0);
153 CHECK(restarter
.waitClusterSingleUser(timeout
) == 0);
154 CHECK(drop_index_on_pk(pNdb
, tabName
) == 0);
155 CHECK(utilTrans
.selectCount(pNdb
, 64, &count
) == 0);
156 CHECK(create_index_on_pk(pNdb
, tabName
) == 0);
157 CHECK(restarter
.exitSingleUserMode() == 0);
158 CHECK(restarter
.waitClusterStarted(timeout
) == 0);
159 CHECK(drop_index_on_pk(pNdb
, tabName
) == 0);
161 CHECK(utilTrans
.clearTable(GETNDB(step
), records
) == 0);
163 ndbout
<< "Restarting cluster" << endl
;
164 CHECK(restarter
.restartAll() == 0);
165 CHECK(restarter
.waitClusterStarted(timeout
) == 0);
166 CHECK(pNdb
->waitUntilReady(timeout
) == 0);
174 int runTestApiSession(NDBT_Context
* ctx
, NDBT_Step
* step
)
176 char *mgm
= ctx
->getRemoteMgm();
177 Uint64 session_id
= 0;
180 h
= ndb_mgm_create_handle();
181 ndb_mgm_set_connectstring(h
, mgm
);
182 ndb_mgm_connect(h
,0,0,0);
183 int s
= ndb_mgm_get_fd(h
);
184 session_id
= ndb_mgm_get_session_id(h
);
185 ndbout
<< "MGM Session id: " << session_id
<< endl
;
187 ndb_mgm_disconnect(h
);
188 ndb_mgm_destroy_handle(&h
);
190 struct NdbMgmSession sess
;
191 int slen
= sizeof(struct NdbMgmSession
);
193 h
= ndb_mgm_create_handle();
194 ndb_mgm_set_connectstring(h
, mgm
);
195 ndb_mgm_connect(h
,0,0,0);
197 NdbSleep_SecSleep(1);
199 if(ndb_mgm_get_session(h
,session_id
,&sess
,&slen
))
201 ndbout
<< "Failed, session still exists" << endl
;
202 ndb_mgm_disconnect(h
);
203 ndb_mgm_destroy_handle(&h
);
208 ndbout
<< "SUCCESS: session is gone" << endl
;
209 ndb_mgm_disconnect(h
);
210 ndb_mgm_destroy_handle(&h
);
215 int runTestApiConnectTimeout(NDBT_Context
* ctx
, NDBT_Step
* step
)
217 char *mgm
= ctx
->getRemoteMgm();
218 int result
= NDBT_FAILED
;
224 h
= ndb_mgm_create_handle();
225 ndb_mgm_set_connectstring(h
, mgm
);
227 ndbout
<< "TEST connect timeout" << endl
;
229 ndb_mgm_set_timeout(h
, 3000);
231 struct timeval tstart
, tend
;
235 gettimeofday(&tstart
,NULL
);
237 ndb_mgm_connect(h
,0,0,0);
239 gettimeofday(&tend
,NULL
);
241 secs
= tend
.tv_sec
- tstart
.tv_sec
;
242 ndbout
<< "Took about: " << secs
<<" seconds"<<endl
;
249 ndb_mgm_set_connectstring(h
, mgm
);
251 ndbout
<< "TEST connect timeout" << endl
;
253 ndb_mgm_destroy_handle(&h
);
255 h
= ndb_mgm_create_handle();
256 ndb_mgm_set_connectstring(h
, "1.1.1.1");
258 ndbout
<< "TEST connect timeout (invalid host)" << endl
;
260 ndb_mgm_set_timeout(h
, 3000);
264 gettimeofday(&tstart
,NULL
);
266 ndb_mgm_connect(h
,0,0,0);
268 gettimeofday(&tend
,NULL
);
270 secs
= tend
.tv_sec
- tstart
.tv_sec
;
271 ndbout
<< "Took about: " << secs
<<" seconds"<<endl
;
279 ndb_mgm_disconnect(h
);
280 ndb_mgm_destroy_handle(&h
);
285 int runTestApiTimeoutBasic(NDBT_Context
* ctx
, NDBT_Step
* step
)
287 char *mgm
= ctx
->getRemoteMgm();
288 int result
= NDBT_FAILED
;
294 h
= ndb_mgm_create_handle();
295 ndb_mgm_set_connectstring(h
, mgm
);
297 ndbout
<< "TEST timout check_connection" << endl
;
298 int errs
[] = { 1, 2, 3, -1};
300 for(int error_ins_no
=0; errs
[error_ins_no
]!=-1; error_ins_no
++)
302 int error_ins
= errs
[error_ins_no
];
303 ndbout
<< "trying error " << error_ins
<< endl
;
304 ndb_mgm_connect(h
,0,0,0);
306 if(ndb_mgm_check_connection(h
) < 0)
312 mgmd_nodeid
= ndb_mgm_get_mgmd_nodeid(h
);
315 ndbout
<< "Failed to get mgmd node id to insert error" << endl
;
320 reply
.return_code
= 0;
322 if(ndb_mgm_insert_error(h
, mgmd_nodeid
, error_ins
, &reply
)< 0)
324 ndbout
<< "failed to insert error " << endl
;
329 ndb_mgm_set_timeout(h
,2500);
331 cc
= ndb_mgm_check_connection(h
);
337 if(ndb_mgm_is_connected(h
))
339 ndbout
<< "FAILED: still connected" << endl
;
344 ndbout
<< "TEST get_mgmd_nodeid" << endl
;
345 ndb_mgm_connect(h
,0,0,0);
347 if(ndb_mgm_insert_error(h
, mgmd_nodeid
, 0, &reply
)< 0)
349 ndbout
<< "failed to remove inserted error " << endl
;
354 cc
= ndb_mgm_get_mgmd_nodeid(h
);
355 ndbout
<< "got node id: " << cc
<< endl
;
358 ndbout
<< "FAILED: didn't get node id" << endl
;
364 ndbout
<< "TEST end_session" << endl
;
365 ndb_mgm_connect(h
,0,0,0);
367 if(ndb_mgm_insert_error(h
, mgmd_nodeid
, 4, &reply
)< 0)
369 ndbout
<< "FAILED: insert error 1" << endl
;
374 cc
= ndb_mgm_end_session(h
);
377 ndbout
<< "FAILED: success in calling end_session" << endl
;
380 else if(ndb_mgm_get_latest_error(h
)!=ETIMEDOUT
)
382 ndbout
<< "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h
)
383 << " != expected " << ETIMEDOUT
<< ") desc: "
384 << ndb_mgm_get_latest_error_desc(h
)
385 << " line: " << ndb_mgm_get_latest_error_line(h
)
386 << " msg: " << ndb_mgm_get_latest_error_msg(h
)
393 if(ndb_mgm_is_connected(h
))
395 ndbout
<< "FAILED: is still connected after error" << endl
;
399 ndb_mgm_disconnect(h
);
400 ndb_mgm_destroy_handle(&h
);
405 int runTestApiGetStatusTimeout(NDBT_Context
* ctx
, NDBT_Step
* step
)
407 char *mgm
= ctx
->getRemoteMgm();
413 h
= ndb_mgm_create_handle();
414 ndb_mgm_set_connectstring(h
, mgm
);
416 int errs
[] = { 0, 5, 6, 7, 8, 9, -1 };
418 for(int error_ins_no
=0; errs
[error_ins_no
]!=-1; error_ins_no
++)
420 int error_ins
= errs
[error_ins_no
];
421 ndb_mgm_connect(h
,0,0,0);
423 if(ndb_mgm_check_connection(h
) < 0)
429 mgmd_nodeid
= ndb_mgm_get_mgmd_nodeid(h
);
432 ndbout
<< "Failed to get mgmd node id to insert error" << endl
;
438 reply
.return_code
= 0;
440 if(ndb_mgm_insert_error(h
, mgmd_nodeid
, error_ins
, &reply
)< 0)
442 ndbout
<< "failed to insert error " << error_ins
<< endl
;
446 ndbout
<< "trying error: " << error_ins
<< endl
;
448 ndb_mgm_set_timeout(h
,2500);
450 struct ndb_mgm_cluster_state
*cl
= ndb_mgm_get_status(h
);
456 * For whatever strange reason,
457 * get_status is okay with not having the last enter there.
458 * instead of "fixing" the api, let's have a special case
459 * so we don't break any behaviour
462 if(error_ins
!=0 && error_ins
!=9 && cl
!=NULL
)
464 ndbout
<< "FAILED: got a ndb_mgm_cluster_state back" << endl
;
468 if(error_ins
!=0 && error_ins
!=9 && ndb_mgm_is_connected(h
))
470 ndbout
<< "FAILED: is still connected after error" << endl
;
474 if(error_ins
!=0 && error_ins
!=9 && ndb_mgm_get_latest_error(h
)!=ETIMEDOUT
)
476 ndbout
<< "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h
)
477 << " != expected " << ETIMEDOUT
<< ") desc: "
478 << ndb_mgm_get_latest_error_desc(h
)
479 << " line: " << ndb_mgm_get_latest_error_line(h
)
480 << " msg: " << ndb_mgm_get_latest_error_msg(h
)
487 ndb_mgm_disconnect(h
);
488 ndb_mgm_destroy_handle(&h
);
493 int runTestMgmApiGetConfigTimeout(NDBT_Context
* ctx
, NDBT_Step
* step
)
495 char *mgm
= ctx
->getRemoteMgm();
500 h
= ndb_mgm_create_handle();
501 ndb_mgm_set_connectstring(h
, mgm
);
503 int errs
[] = { 0, 1, 2, 3, -1 };
505 for(int error_ins_no
=0; errs
[error_ins_no
]!=-1; error_ins_no
++)
507 int error_ins
= errs
[error_ins_no
];
508 ndb_mgm_connect(h
,0,0,0);
510 if(ndb_mgm_check_connection(h
) < 0)
516 mgmd_nodeid
= ndb_mgm_get_mgmd_nodeid(h
);
519 ndbout
<< "Failed to get mgmd node id to insert error" << endl
;
525 reply
.return_code
= 0;
527 if(ndb_mgm_insert_error(h
, mgmd_nodeid
, error_ins
, &reply
)< 0)
529 ndbout
<< "failed to insert error " << error_ins
<< endl
;
533 ndbout
<< "trying error: " << error_ins
<< endl
;
535 ndb_mgm_set_timeout(h
,2500);
537 struct ndb_mgm_configuration
*c
= ndb_mgm_get_configuration(h
,0);
542 if(error_ins
!=0 && c
!=NULL
)
544 ndbout
<< "FAILED: got a ndb_mgm_configuration back" << endl
;
548 if(error_ins
!=0 && ndb_mgm_is_connected(h
))
550 ndbout
<< "FAILED: is still connected after error" << endl
;
554 if(error_ins
!=0 && ndb_mgm_get_latest_error(h
)!=ETIMEDOUT
)
556 ndbout
<< "FAILED: Incorrect error code (" << ndb_mgm_get_latest_error(h
)
557 << " != expected " << ETIMEDOUT
<< ") desc: "
558 << ndb_mgm_get_latest_error_desc(h
)
559 << " line: " << ndb_mgm_get_latest_error_line(h
)
560 << " msg: " << ndb_mgm_get_latest_error_msg(h
)
567 ndb_mgm_disconnect(h
);
568 ndb_mgm_destroy_handle(&h
);
573 int runTestMgmApiEventTimeout(NDBT_Context
* ctx
, NDBT_Step
* step
)
575 char *mgm
= ctx
->getRemoteMgm();
580 h
= ndb_mgm_create_handle();
581 ndb_mgm_set_connectstring(h
, mgm
);
583 int errs
[] = { 10000, 0, -1 };
585 for(int error_ins_no
=0; errs
[error_ins_no
]!=-1; error_ins_no
++)
587 int error_ins
= errs
[error_ins_no
];
588 ndb_mgm_connect(h
,0,0,0);
590 if(ndb_mgm_check_connection(h
) < 0)
596 mgmd_nodeid
= ndb_mgm_get_mgmd_nodeid(h
);
599 ndbout
<< "Failed to get mgmd node id to insert error" << endl
;
605 reply
.return_code
= 0;
607 if(ndb_mgm_insert_error(h
, mgmd_nodeid
, error_ins
, &reply
)< 0)
609 ndbout
<< "failed to insert error " << error_ins
<< endl
;
613 ndbout
<< "trying error: " << error_ins
<< endl
;
615 ndb_mgm_set_timeout(h
,2500);
617 int filter
[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP
,
618 1, NDB_MGM_EVENT_CATEGORY_STARTUP
,
620 int fd
= ndb_mgm_listen_event(h
, filter
);
622 if(fd
==NDB_INVALID_SOCKET
)
624 ndbout
<< "FAILED: could not listen to event" << endl
;
629 EventReport
*fake_event
= (EventReport
*)theData
;
630 fake_event
->setEventType(NDB_LE_NDBStopForced
);
631 fake_event
->setNodeId(42);
637 ndb_mgm_report_event(h
, theData
, 6);
641 SocketInputStream
in(fd
,2000);
642 for(int i
=0; i
<20; i
++)
644 if((tmp
= in
.gets(buf
, sizeof(buf
))))
646 // const char ping_token[]="<PING>";
647 // if(memcmp(ping_token,tmp,sizeof(ping_token)-1))
648 if(tmp
&& strlen(tmp
))
655 ndbout
<< "TIMED OUT READING EVENT at iteration " << i
<< endl
;
662 * events go through a *DIFFERENT* socket than the NdbMgmHandle
663 * so we should still be connected (and be able to check_connection)
667 if(ndb_mgm_check_connection(h
) && !ndb_mgm_is_connected(h
))
669 ndbout
<< "FAILED: is still connected after error" << endl
;
673 ndb_mgm_disconnect(h
);
677 ndb_mgm_disconnect(h
);
678 ndb_mgm_destroy_handle(&h
);
683 int runTestMgmApiStructEventTimeout(NDBT_Context
* ctx
, NDBT_Step
* step
)
685 char *mgm
= ctx
->getRemoteMgm();
690 h
= ndb_mgm_create_handle();
691 ndb_mgm_set_connectstring(h
, mgm
);
693 int errs
[] = { 10000, 0, -1 };
695 for(int error_ins_no
=0; errs
[error_ins_no
]!=-1; error_ins_no
++)
697 int error_ins
= errs
[error_ins_no
];
698 ndb_mgm_connect(h
,0,0,0);
700 if(ndb_mgm_check_connection(h
) < 0)
706 mgmd_nodeid
= ndb_mgm_get_mgmd_nodeid(h
);
709 ndbout
<< "Failed to get mgmd node id to insert error" << endl
;
715 reply
.return_code
= 0;
717 if(ndb_mgm_insert_error(h
, mgmd_nodeid
, error_ins
, &reply
)< 0)
719 ndbout
<< "failed to insert error " << error_ins
<< endl
;
723 ndbout
<< "trying error: " << error_ins
<< endl
;
725 ndb_mgm_set_timeout(h
,2500);
727 int filter
[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP
,
728 1, NDB_MGM_EVENT_CATEGORY_STARTUP
,
730 NdbLogEventHandle le_handle
= ndb_mgm_create_logevent_handle(h
, filter
);
732 struct ndb_logevent le
;
733 for(int i
=0; i
<20; i
++)
735 if(error_ins
==0 || (error_ins
!=0 && i
<5))
738 EventReport
*fake_event
= (EventReport
*)theData
;
739 fake_event
->setEventType(NDB_LE_NDBStopForced
);
740 fake_event
->setNodeId(42);
746 ndb_mgm_report_event(h
, theData
, 6);
748 int r
= ndb_logevent_get_next(le_handle
, &le
, 2500);
751 ndbout
<< "Receieved event" << endl
;
755 ndbout
<< "ERROR" << endl
;
759 ndbout
<< "TIMED OUT READING EVENT at iteration " << i
<< endl
;
769 * events go through a *DIFFERENT* socket than the NdbMgmHandle
770 * so we should still be connected (and be able to check_connection)
774 if(ndb_mgm_check_connection(h
) && !ndb_mgm_is_connected(h
))
776 ndbout
<< "FAILED: is still connected after error" << endl
;
780 ndb_mgm_disconnect(h
);
784 ndb_mgm_disconnect(h
);
785 ndb_mgm_destroy_handle(&h
);
790 NDBT_TESTSUITE(testMgm
);
791 TESTCASE("SingleUserMode",
792 "Test single user mode"){
793 INITIALIZER(runTestSingleUserMode
);
794 FINALIZER(runClearTable
);
796 TESTCASE("ApiSessionFailure",
797 "Test failures in MGMAPI session"){
798 INITIALIZER(runTestApiSession
);
801 TESTCASE("ApiConnectTimeout",
802 "Connect timeout tests for MGMAPI"){
803 INITIALIZER(runTestApiConnectTimeout
);
806 TESTCASE("ApiTimeoutBasic",
807 "Basic timeout tests for MGMAPI"){
808 INITIALIZER(runTestApiTimeoutBasic
);
811 TESTCASE("ApiGetStatusTimeout",
812 "Test timeout for MGMAPI getStatus"){
813 INITIALIZER(runTestApiGetStatusTimeout
);
816 TESTCASE("ApiGetConfigTimeout",
817 "Test timeouts for mgmapi get_configuration"){
818 INITIALIZER(runTestMgmApiGetConfigTimeout
);
821 TESTCASE("ApiMgmEventTimeout",
822 "Test timeouts for mgmapi get_configuration"){
823 INITIALIZER(runTestMgmApiEventTimeout
);
826 TESTCASE("ApiMgmStructEventTimeout",
827 "Test timeouts for mgmapi get_configuration"){
828 INITIALIZER(runTestMgmApiStructEventTimeout
);
831 NDBT_TESTSUITE_END(testMgm
);
833 int main(int argc
, const char** argv
){
835 myRandom48Init(NdbTick_CurrentMillisecond());
836 return testMgm
.execute(argc
, argv
);