1
/* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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);