1 /*
2 Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
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 <NDBT.hpp>
26 #include <NDBT_Test.hpp>
27 #include <HugoTransactions.hpp>
28 #include <UtilTransactions.hpp>
29 #include <NdbRestarter.hpp>
30 #include <Vector.hpp>
31 #include <signaldata/DumpStateOrd.hpp>
32 #include <../../include/kernel/ndb_limits.h>
33 #include <../../include/kernel/trigger_definitions.h>
34 #include <signaldata/DictTabInfo.hpp>
35 #include <random.h>
36 #include <NdbAutoPtr.hpp>
37 #include <NdbMixRestarter.hpp>
38 #include <NdbSqlUtil.hpp>
39 #include <NdbEnv.h>
40 #include <ndb_rand.h>
41 #include <Bitmask.hpp>
42
43 #define ERR_INSERT_MASTER_FAILURE1 6013
44 #define ERR_INSERT_MASTER_FAILURE2 6014
45 #define ERR_INSERT_MASTER_FAILURE3 6015
46
47 #define ERR_INSERT_PARTIAL_START_FAIL 6140
48 #define ERR_INSERT_PARTIAL_PARSE_FAIL 6141
49 #define ERR_INSERT_PARTIAL_FLUSH_PREPARE_FAIL 6142
50 #define ERR_INSERT_PARTIAL_PREPARE_FAIL 6143
51 #define ERR_INSERT_PARTIAL_ABORT_PARSE_FAIL 6144
52 #define ERR_INSERT_PARTIAL_ABORT_PREPARE_FAIL 6145
53 #define ERR_INSERT_PARTIAL_FLUSH_COMMIT_FAIL 6146
54 #define ERR_INSERT_PARTIAL_COMMIT_FAIL 6147
55 #define ERR_INSERT_PARTIAL_FLUSH_COMPLETE_FAIL 6148
56 #define ERR_INSERT_PARTIAL_COMPLETE_FAIL 6149
57 #define ERR_INSERT_PARTIAL_END_FAIL 6150
58
59 #define FAIL_BEGIN 0
60 #define FAIL_CREATE 1
61 #define FAIL_END 2
62 #define SUCCEED_COMMIT 3
63 #define SUCCEED_ABORT 4
64
65 #define ndb_master_failure 1
66
67 char f_tablename[256];
68
69 #define CHECK(b) if (!(b)) { \
70 g_err << "ERR: "<< step->getName() \
71 << " failed on line " << __LINE__ << endl; \
72 result = NDBT_FAILED; \
73 break; }
74
75 #define CHECK2(b, c) if (!(b)) { \
76 g_err << "ERR: "<< step->getName() \
77 << " failed on line " << __LINE__ << ": " << c << endl; \
78 result = NDBT_FAILED; \
79 goto end; }
80
runLoadTable(NDBT_Context * ctx,NDBT_Step * step)81 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
82 Ndb* pNdb = GETNDB(step);
83 int records = ctx->getNumRecords();
84 HugoTransactions hugoTrans(*ctx->getTab());
85 if (hugoTrans.loadTable(pNdb, records) != 0){
86 return NDBT_FAILED;
87 }
88 return NDBT_OK;
89 }
90
runCreateInvalidTables(NDBT_Context * ctx,NDBT_Step * step)91 int runCreateInvalidTables(NDBT_Context* ctx, NDBT_Step* step){
92 Ndb* pNdb = GETNDB(step);
93 int result = NDBT_OK;
94
95 char failTabName[256];
96
97 const int expectedDictErrors[6]= {720,
98 4317,
99 737,
100 739,
101 736,
102 740 };
103
104 for (int i = 0; i < 10; i++){
105 BaseString::snprintf(failTabName, 256, "F%d", i);
106
107 const NdbDictionary::Table* pFailTab = NDBT_Tables::getTable(failTabName);
108 if (pFailTab != NULL){
109 ndbout << "|- " << failTabName << endl;
110
111 // Try to create table in db
112 if (pFailTab->createTableInDb(pNdb) == 0){
113 ndbout << failTabName << " created, this was not expected"<< endl;
114 result = NDBT_FAILED;
115 }
116
117 // Ensure any error is roughly as expected
118 int errorCode=pNdb->getDictionary()->getNdbError().code;
119 bool errorOk= false;
120 for (int e=0; e < 6; e++)
121 errorOk |= (errorCode == expectedDictErrors[e]);
122
123 if (!errorOk)
124 {
125 ndbout << "Failure, got dict error : " << pNdb->getDictionary()->
126 getNdbError().code << endl;
127 return NDBT_FAILED;
128 }
129
130 // Verify that table is not in db
131 const NdbDictionary::Table* pTab2 =
132 NDBT_Table::discoverTableFromDb(pNdb, failTabName) ;
133 if (pTab2 != NULL){
134 ndbout << failTabName << " was found in DB, this was not expected"<< endl;
135 result = NDBT_FAILED;
136 if (pFailTab->equal(*pTab2) == true){
137 ndbout << "It was equal" << endl;
138 } else {
139 ndbout << "It was not equal" << endl;
140 }
141 int records = 1000;
142 HugoTransactions hugoTrans(*pTab2);
143 if (hugoTrans.loadTable(pNdb, records) != 0){
144 ndbout << "It can NOT be loaded" << endl;
145 } else{
146 ndbout << "It can be loaded" << endl;
147
148 UtilTransactions utilTrans(*pTab2);
149 if (utilTrans.clearTable(pNdb, records, 64) != 0){
150 ndbout << "It can NOT be cleared" << endl;
151 } else{
152 ndbout << "It can be cleared" << endl;
153 }
154 }
155
156 if (pNdb->getDictionary()->dropTable(pTab2->getName()) == -1){
157 ndbout << "It can NOT be dropped" << endl;
158 } else {
159 ndbout << "It can be dropped" << endl;
160 }
161 }
162 }
163 }
164 return result;
165 }
166
runCreateTheTable(NDBT_Context * ctx,NDBT_Step * step)167 int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
168 Ndb* pNdb = GETNDB(step);
169 const NdbDictionary::Table* pTab = ctx->getTab();
170
171 // Try to create table in db
172 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
173 return NDBT_FAILED;
174 }
175
176 // Verify that table is in db
177 const NdbDictionary::Table* pTab2 =
178 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
179 if (pTab2 == NULL){
180 ndbout << pTab->getName() << " was not found in DB"<< endl;
181 return NDBT_FAILED;
182 }
183 ctx->setTab(pTab2);
184
185 BaseString::snprintf(f_tablename, sizeof(f_tablename),
186 "%s", pTab->getName());
187
188 return NDBT_OK;
189 }
190
runDropTheTable(NDBT_Context * ctx,NDBT_Step * step)191 int runDropTheTable(NDBT_Context* ctx, NDBT_Step* step){
192 Ndb* pNdb = GETNDB(step);
193 //const NdbDictionary::Table* pTab = ctx->getTab();
194
195 // Try to create table in db
196 pNdb->getDictionary()->dropTable(f_tablename);
197
198 return NDBT_OK;
199 }
200
runCreateTableWhenDbIsFull(NDBT_Context * ctx,NDBT_Step * step)201 int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
202 Ndb* pNdb = GETNDB(step);
203 int result = NDBT_OK;
204 const char* tabName = "TRANSACTION"; //Use a util table
205
206 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
207 if (pTab != NULL){
208 ndbout << "|- " << tabName << endl;
209
210 // Verify that table is not in db
211 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
212 ndbout << tabName << " was found in DB"<< endl;
213 return NDBT_FAILED;
214 }
215
216 // Try to create table in db
217 if (NDBT_Tables::createTable(pNdb, pTab->getName()) == 0){
218 result = NDBT_FAILED;
219 }
220
221 // Verify that table is in db
222 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
223 ndbout << tabName << " was found in DB"<< endl;
224 result = NDBT_FAILED;
225 }
226 }
227
228 return result;
229 }
230
runDropTableWhenDbIsFull(NDBT_Context * ctx,NDBT_Step * step)231 int runDropTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
232 Ndb* pNdb = GETNDB(step);
233 int result = NDBT_OK;
234 const char* tabName = "TRANSACTION"; //Use a util table
235
236 const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(pNdb, tabName);
237 if (pTab != NULL){
238 ndbout << "|- TRANSACTION" << endl;
239
240 // Try to drop table in db
241 if (pNdb->getDictionary()->dropTable(pTab->getName()) == -1){
242 result = NDBT_FAILED;
243 }
244
245 // Verify that table is not in db
246 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
247 ndbout << tabName << " was found in DB"<< endl;
248 result = NDBT_FAILED;
249 }
250 }
251
252 return result;
253
254 }
255
256
runCreateAndDrop(NDBT_Context * ctx,NDBT_Step * step)257 int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
258 Ndb* pNdb = GETNDB(step);
259 int loops = ctx->getNumLoops();
260 int i = 0;
261
262 const NdbDictionary::Table* pTab = ctx->getTab();
263 ndbout << "|- " << pTab->getName() << endl;
264
265 while (i < loops){
266
267 ndbout << i << ": ";
268 // Try to create table in db
269 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
270 return NDBT_FAILED;
271 }
272
273 // Verify that table is in db
274 const NdbDictionary::Table* pTab2 =
275 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
276 if (pTab2 == NULL){
277 ndbout << pTab->getName() << " was not found in DB"<< endl;
278 return NDBT_FAILED;
279 }
280
281 if (pNdb->getDictionary()->dropTable(pTab2->getName())){
282 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
283 return NDBT_FAILED;
284 }
285
286 // Verify that table is not in db
287 const NdbDictionary::Table* pTab3 =
288 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
289 if (pTab3 != NULL){
290 ndbout << pTab3->getName() << " was found in DB"<< endl;
291 return NDBT_FAILED;
292 }
293 i++;
294 }
295
296 return NDBT_OK;
297 }
298
runCreateAndDropAtRandom(NDBT_Context * ctx,NDBT_Step * step)299 int runCreateAndDropAtRandom(NDBT_Context* ctx, NDBT_Step* step)
300 {
301 myRandom48Init((long)NdbTick_CurrentMillisecond());
302 Ndb* pNdb = GETNDB(step);
303 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
304 int loops = ctx->getNumLoops();
305 int records = ctx->getNumRecords();
306
307 int numAllTables = NDBT_Tables::getNumTables();
308 struct TabList {
309 int exists; // -1 = skip, 0 = no, 1 = yes
310 const NdbDictionary::Table* pTab; // retrieved
311 TabList() { exists = -1; pTab = 0; }
312 };
313 TabList* tabList = new TabList [ numAllTables ];
314 int numTables = 0;
315 int num;
316 for (num = 0; num < numAllTables; num++) {
317 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num);
318 if (pTab->checkColumns(0, 0) & 2) // skip disk
319 continue;
320 tabList[num].exists = 0;
321 (void)pDic->dropTable(pTab->getName());
322 numTables++;
323 }
324 int numExists = 0;
325
326 const bool createIndexes = ctx->getProperty("CreateIndexes");
327 const bool loadData = ctx->getProperty("LoadData");
328
329 NdbRestarter restarter;
330 int result = NDBT_OK;
331 int bias = 1; // 0-less 1-more
332 int i = 0;
333
334 while (i < loops && result == NDBT_OK) {
335 num = myRandom48(numAllTables);
336 if (tabList[num].exists == -1)
337 continue;
338 g_info << "loop " << i << " tabs " << numExists << "/" << numTables << endl;
339 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num);
340 char tabName[200];
341 strcpy(tabName, pTab->getName());
342
343 if (tabList[num].exists == 0) {
344 if (bias == 0 && myRandom48(100) < 80)
345 continue;
346 g_info << tabName << ": create" << endl;
347 if (pDic->createTable(*pTab) != 0) {
348 const NdbError err = pDic->getNdbError();
349 g_err << tabName << ": create failed: " << err << endl;
350 result = NDBT_FAILED;
351 break;
352 }
353 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
354 if (pTab2 == NULL) {
355 const NdbError err = pDic->getNdbError();
356 g_err << tabName << ": verify create failed: " << err << endl;
357 result = NDBT_FAILED;
358 break;
359 }
360 tabList[num].pTab = pTab2;
361 if (loadData) {
362 g_info << tabName << ": load data" << endl;
363 HugoTransactions hugoTrans(*pTab2);
364 if (hugoTrans.loadTable(pNdb, records) != 0) {
365 g_err << tabName << ": loadTable failed" << endl;
366 result = NDBT_FAILED;
367 break;
368 }
369 }
370 if (createIndexes) {
371 int icount = myRandom48(10);
372 int inum;
373 for (inum = 0; inum < icount; inum++) {
374 const int tcols = pTab2->getNoOfColumns();
375 assert(tcols != 0);
376 int icols = 1 + myRandom48(tcols);
377 if (icols > NDB_MAX_ATTRIBUTES_IN_INDEX)
378 icols = NDB_MAX_ATTRIBUTES_IN_INDEX;
379 char indName[200];
380 sprintf(indName, "%s_X%d", tabName, inum);
381 NdbDictionary::Index ind(indName);
382 ind.setTable(tabName);
383 ind.setType(NdbDictionary::Index::OrderedIndex);
384 ind.setLogging(false);
385 Bitmask<MAX_ATTRIBUTES_IN_TABLE> mask;
386 char ilist[200];
387 ilist[0] = 0;
388 int ic;
389 for (ic = 0; ic < icols; ic++) {
390 int tc = myRandom48(tcols);
391 const NdbDictionary::Column* c = pTab2->getColumn(tc);
392 assert(c != 0);
393 if (mask.get(tc) ||
394 c->getType() == NdbDictionary::Column::Blob ||
395 c->getType() == NdbDictionary::Column::Text ||
396 c->getType() == NdbDictionary::Column::Bit ||
397 c->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
398 continue;
399 ind.addColumn(*c);
400 mask.set(tc);
401 sprintf(ilist + strlen(ilist), " %d", tc);
402 }
403 if (mask.isclear())
404 continue;
405 g_info << indName << ": columns:" << ilist << endl;
406 if (pDic->createIndex(ind) == 0) {
407 g_info << indName << ": created" << endl;
408 } else {
409 const NdbError err = pDic->getNdbError();
410 g_err << indName << ": create index failed: " << err << endl;
411 if (err.code != 826 && // Too many tables and attributes..
412 err.code != 903 && // Too many ordered indexes..
413 err.code != 904 && // Out of fragment records..
414 err.code != 905 && // Out of attribute records..
415 err.code != 707 && // No more table metadata records..
416 err.code != 708) // No more attribute metadata records..
417 {
418 result = NDBT_FAILED;
419 break;
420 }
421 }
422 }
423 }
424 if (loadData) {
425 // first update a random table to flush global variables
426 int num3 = 0;
427 while (1) {
428 num3 = myRandom48(numAllTables);
429 if (num == num3 || tabList[num3].exists == 1)
430 break;
431 }
432 const NdbDictionary::Table* pTab3 = tabList[num3].pTab;
433 assert(pTab3 != 0);
434 char tabName3[200];
435 strcpy(tabName3, pTab3->getName());
436 HugoTransactions hugoTrans(*pTab3);
437 g_info << tabName3 << ": update data" << endl;
438 if (hugoTrans.pkUpdateRecords(pNdb, records) != 0) {
439 g_err << tabName3 << ": pkUpdateRecords failed" << endl;
440 result = NDBT_FAILED;
441 break;
442 }
443 }
444 if (loadData) {
445 HugoTransactions hugoTrans(*pTab2);
446 g_info << tabName << ": update data" << endl;
447 if (hugoTrans.pkUpdateRecords(pNdb, records) != 0) {
448 g_err << "pkUpdateRecords failed" << endl;
449 result = NDBT_FAILED;
450 break;
451 }
452 }
453 tabList[num].exists = 1;
454 assert(numExists < numTables);
455 numExists++;
456 if (numExists == numTables)
457 bias = 0;
458 }
459 else if (tabList[num].exists == 1) {
460 if (bias == 1 && myRandom48(100) < 80)
461 continue;
462 g_info << tabName << ": drop" << endl;
463 if (restarter.insertErrorInAllNodes(4013) != 0) {
464 g_err << "error insert failed" << endl;
465 result = NDBT_FAILED;
466 break;
467 }
468 if (pDic->dropTable(tabName) != 0) {
469 const NdbError err = pDic->getNdbError();
470 g_err << tabName << ": drop failed: " << err << endl;
471 result = NDBT_FAILED;
472 break;
473 }
474 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
475 if (pTab2 != NULL) {
476 g_err << tabName << ": verify drop: table exists" << endl;
477 result = NDBT_FAILED;
478 break;
479 }
480 if (pDic->getNdbError().code != 709 &&
481 pDic->getNdbError().code != 723) {
482 const NdbError err = pDic->getNdbError();
483 g_err << tabName << ": verify drop: " << err << endl;
484 result = NDBT_FAILED;
485 break;
486 }
487 tabList[num].exists = 0;
488 assert(numExists > 0);
489 numExists--;
490 if (numExists == 0)
491 bias = 1;
492 }
493 i++;
494 }
495
496 for (num = 0; num < numAllTables; num++)
497 if (tabList[num].exists == 1)
498 pDic->dropTable(NDBT_Tables::getTable(num)->getName());
499
500 delete [] tabList;
501 return result;
502 }
503
504
runCreateAndDropWithData(NDBT_Context * ctx,NDBT_Step * step)505 int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
506 Ndb* pNdb = GETNDB(step);
507 int loops = ctx->getNumLoops();
508 int records = ctx->getNumRecords();
509 int i = 0;
510
511 NdbRestarter restarter;
512 int val = DumpStateOrd::DihMinTimeBetweenLCP;
513 if(restarter.dumpStateAllNodes(&val, 1) != 0){
514 int result;
515 do { CHECK(0); } while (0);
516 g_err << "Unable to change timebetween LCP" << endl;
517 return NDBT_FAILED;
518 }
519
520 const NdbDictionary::Table* pTab = ctx->getTab();
521 ndbout << "|- " << pTab->getName() << endl;
522
523 while (i < loops){
524 ndbout << i << ": ";
525 // Try to create table in db
526
527 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
528 return NDBT_FAILED;
529 }
530
531 // Verify that table is in db
532 const NdbDictionary::Table* pTab2 =
533 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
534 if (pTab2 == NULL){
535 ndbout << pTab->getName() << " was not found in DB"<< endl;
536 return NDBT_FAILED;
537 }
538
539 HugoTransactions hugoTrans(*pTab2);
540 if (hugoTrans.loadTable(pNdb, records) != 0){
541 return NDBT_FAILED;
542 }
543
544 int count = 0;
545 UtilTransactions utilTrans(*pTab2);
546 if (utilTrans.selectCount(pNdb, 64, &count) != 0){
547 return NDBT_FAILED;
548 }
549 if (count != records){
550 ndbout << count <<" != "<<records << endl;
551 return NDBT_FAILED;
552 }
553
554 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
555 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
556 return NDBT_FAILED;
557 }
558
559 // Verify that table is not in db
560 const NdbDictionary::Table* pTab3 =
561 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
562 if (pTab3 != NULL){
563 ndbout << pTab3->getName() << " was found in DB"<< endl;
564 return NDBT_FAILED;
565 }
566
567
568 i++;
569 }
570
571 return NDBT_OK;
572 }
573
runFillTable(NDBT_Context * ctx,NDBT_Step * step)574 int runFillTable(NDBT_Context* ctx, NDBT_Step* step){
575 Ndb* pNdb = GETNDB(step);
576 HugoTransactions hugoTrans(*ctx->getTab());
577 if (hugoTrans.fillTable(pNdb) != 0){
578 return NDBT_FAILED;
579 }
580 return NDBT_OK;
581 }
582
runClearTable(NDBT_Context * ctx,NDBT_Step * step)583 int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
584 Ndb* pNdb = GETNDB(step);
585 int records = ctx->getNumRecords();
586
587 UtilTransactions utilTrans(*ctx->getTab());
588 if (utilTrans.clearTable(pNdb, records) != 0){
589 return NDBT_FAILED;
590 }
591 return NDBT_OK;
592 }
593
runCreateAndDropDuring(NDBT_Context * ctx,NDBT_Step * step)594 int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
595 int result = NDBT_OK;
596 int loops = ctx->getNumLoops();
597 int i = 0;
598
599 const NdbDictionary::Table* pTab = ctx->getTab();
600 ndbout << "|- " << pTab->getName() << endl;
601
602 while (i < loops && result == NDBT_OK){
603 ndbout << i << ": " << endl;
604 // Try to create table in db
605
606 Ndb* pNdb = GETNDB(step);
607 g_debug << "Creating table" << endl;
608
609 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
610 g_err << "createTableInDb failed" << endl;
611 result = NDBT_FAILED;
612 continue;
613 }
614
615 g_debug << "Verifying creation of table" << endl;
616
617 // Verify that table is in db
618 const NdbDictionary::Table* pTab2 =
619 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
620 if (pTab2 == NULL){
621 g_err << pTab->getName() << " was not found in DB"<< endl;
622 result = NDBT_FAILED;
623 continue;
624 }
625
626 NdbSleep_MilliSleep(3000);
627
628 g_debug << "Dropping table" << endl;
629
630 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
631 g_err << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
632 result = NDBT_FAILED;
633 continue;
634 }
635
636 g_debug << "Verifying dropping of table" << endl;
637
638 // Verify that table is not in db
639 const NdbDictionary::Table* pTab3 =
640 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
641 if (pTab3 != NULL){
642 g_err << pTab3->getName() << " was found in DB"<< endl;
643 result = NDBT_FAILED;
644 continue;
645 }
646 i++;
647 }
648 ctx->stopTest();
649
650 return result;
651 }
652
653
runUseTableUntilStopped(NDBT_Context * ctx,NDBT_Step * step)654 int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
655 int records = ctx->getNumRecords();
656
657 const NdbDictionary::Table* pTab = ctx->getTab();
658
659 while (ctx->isTestStopped() == false) {
660 // g_info << i++ << ": ";
661
662
663 // Delete and recreate Ndb object
664 // Otherwise you always get Invalid Schema Version
665 // It would be a nice feature to remove this two lines
666 //step->tearDown();
667 //step->setUp();
668
669 Ndb* pNdb = GETNDB(step);
670
671 const NdbDictionary::Table* pTab2 =
672 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
673 if (pTab2 == NULL)
674 continue;
675
676 int res;
677 HugoTransactions hugoTrans(*pTab2);
678 if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
679 NdbError err = pNdb->getNdbError(res);
680 if(err.classification == NdbError::SchemaError){
681 pNdb->getDictionary()->invalidateTable(pTab->getName());
682 }
683 continue;
684 }
685
686 if ((res = hugoTrans.clearTable(pNdb, records)) != 0){
687 NdbError err = pNdb->getNdbError(res);
688 if(err.classification == NdbError::SchemaError){
689 pNdb->getDictionary()->invalidateTable(pTab->getName());
690 }
691 continue;
692 }
693 }
694 g_info << endl;
695 return NDBT_OK;
696 }
697
runUseTableUntilStopped2(NDBT_Context * ctx,NDBT_Step * step)698 int runUseTableUntilStopped2(NDBT_Context* ctx, NDBT_Step* step){
699 int records = ctx->getNumRecords();
700
701 Ndb* pNdb = GETNDB(step);
702 const NdbDictionary::Table* pTab = ctx->getTab();
703 const NdbDictionary::Table* pTab2 =
704 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
705 HugoTransactions hugoTrans(*pTab2);
706
707 int i = 0;
708 while (ctx->isTestStopped() == false)
709 {
710 ndbout_c("loop: %u", i++);
711
712
713 // Delete and recreate Ndb object
714 // Otherwise you always get Invalid Schema Version
715 // It would be a nice feature to remove this two lines
716 //step->tearDown();
717 //step->setUp();
718
719
720 int res;
721 if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
722 NdbError err = pNdb->getNdbError(res);
723 if(err.classification == NdbError::SchemaError){
724 pNdb->getDictionary()->invalidateTable(pTab->getName());
725 }
726 continue;
727 }
728
729 if ((res = hugoTrans.scanUpdateRecords(pNdb, records)) != 0)
730 {
731 NdbError err = pNdb->getNdbError(res);
732 if(err.classification == NdbError::SchemaError){
733 pNdb->getDictionary()->invalidateTable(pTab->getName());
734 }
735 continue;
736 }
737
738 if ((res = hugoTrans.clearTable(pNdb, records)) != 0){
739 NdbError err = pNdb->getNdbError(res);
740 if(err.classification == NdbError::SchemaError){
741 pNdb->getDictionary()->invalidateTable(pTab->getName());
742 }
743 continue;
744 }
745 }
746 g_info << endl;
747 return NDBT_OK;
748 }
749
runUseTableUntilStopped3(NDBT_Context * ctx,NDBT_Step * step)750 int runUseTableUntilStopped3(NDBT_Context* ctx, NDBT_Step* step){
751 int records = ctx->getNumRecords();
752
753 Ndb* pNdb = GETNDB(step);
754 const NdbDictionary::Table* pTab = ctx->getTab();
755 const NdbDictionary::Table* pTab2 =
756 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
757 HugoTransactions hugoTrans(*pTab2);
758
759 int i = 0;
760 while (ctx->isTestStopped() == false)
761 {
762 ndbout_c("loop: %u", i++);
763
764
765 // Delete and recreate Ndb object
766 // Otherwise you always get Invalid Schema Version
767 // It would be a nice feature to remove this two lines
768 //step->tearDown();
769 //step->setUp();
770
771
772 int res;
773 if ((res = hugoTrans.scanUpdateRecords(pNdb, records)) != 0)
774 {
775 NdbError err = pNdb->getNdbError(res);
776 if(err.classification == NdbError::SchemaError){
777 pNdb->getDictionary()->invalidateTable(pTab->getName());
778 }
779 continue;
780 }
781 }
782 g_info << endl;
783 return NDBT_OK;
784 }
785
786
787 int
runCreateMaxTables(NDBT_Context * ctx,NDBT_Step * step)788 runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step)
789 {
790 char tabName[256];
791 int numTables = ctx->getProperty("tables", 1000);
792 Ndb* pNdb = GETNDB(step);
793 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
794 int i = 0;
795 for (i = 0; i < numTables; i++) {
796 BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
797 if (pNdb->waitUntilReady(30) != 0) {
798 // Db is not ready, return with failure
799 return NDBT_FAILED;
800 }
801 const NdbDictionary::Table* pTab = ctx->getTab();
802 //ndbout << "|- " << tabName << endl;
803 // Set new name for T1
804 NdbDictionary::Table newTab(* pTab);
805 newTab.setName(tabName);
806 // Drop any old (or try to)
807 (void)pDic->dropTable(newTab.getName());
808 // Try to create table in db
809 if (newTab.createTableInDb(pNdb) != 0) {
810 ndbout << tabName << " could not be created: "
811 << pDic->getNdbError() << endl;
812 if (pDic->getNdbError().code == 707 ||
813 pDic->getNdbError().code == 708 ||
814 pDic->getNdbError().code == 826 ||
815 pDic->getNdbError().code == 827)
816 break;
817 return NDBT_FAILED;
818 }
819 // Verify that table exists in db
820 const NdbDictionary::Table* pTab3 =
821 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
822 if (pTab3 == NULL){
823 ndbout << tabName << " was not found in DB: "
824 << pDic->getNdbError() << endl;
825 return NDBT_FAILED;
826 }
827 if (! newTab.equal(*pTab3)) {
828 ndbout << "It was not equal" << endl; abort();
829 return NDBT_FAILED;
830 }
831 int records = ctx->getNumRecords();
832 HugoTransactions hugoTrans(*pTab3);
833 if (hugoTrans.loadTable(pNdb, records) != 0) {
834 ndbout << "It can NOT be loaded" << endl;
835 return NDBT_FAILED;
836 }
837 UtilTransactions utilTrans(*pTab3);
838 if (utilTrans.clearTable(pNdb, records, 64) != 0) {
839 ndbout << "It can NOT be cleared" << endl;
840 return NDBT_FAILED;
841 }
842 }
843 if (pNdb->waitUntilReady(30) != 0) {
844 // Db is not ready, return with failure
845 return NDBT_FAILED;
846 }
847 ctx->setProperty("maxtables", i);
848 // HURRAAA!
849 return NDBT_OK;
850 }
851
runDropMaxTables(NDBT_Context * ctx,NDBT_Step * step)852 int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step)
853 {
854 char tabName[256];
855 int numTables = ctx->getProperty("maxtables", (Uint32)0);
856 Ndb* pNdb = GETNDB(step);
857 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
858 for (int i = 0; i < numTables; i++) {
859 BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
860 if (pNdb->waitUntilReady(30) != 0) {
861 // Db is not ready, return with failure
862 return NDBT_FAILED;
863 }
864 // Verify that table exists in db
865 const NdbDictionary::Table* pTab3 =
866 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
867 if (pTab3 == NULL) {
868 ndbout << tabName << " was not found in DB: "
869 << pDic->getNdbError() << endl;
870 return NDBT_FAILED;
871 }
872 // Try to drop table in db
873 if (pDic->dropTable(pTab3->getName()) != 0) {
874 ndbout << tabName << " could not be dropped: "
875 << pDic->getNdbError() << endl;
876 return NDBT_FAILED;
877 }
878 }
879 return NDBT_OK;
880 }
881
runTestFragmentTypes(NDBT_Context * ctx,NDBT_Step * step)882 int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
883 int records = ctx->getNumRecords();
884 int fragTtype = ctx->getProperty("FragmentType");
885 Ndb* pNdb = GETNDB(step);
886 int result = NDBT_OK;
887 NdbRestarter restarter;
888
889 if (pNdb->waitUntilReady(30) != 0){
890 // Db is not ready, return with failure
891 return NDBT_FAILED;
892 }
893
894 const NdbDictionary::Table* pTab = ctx->getTab();
895 pNdb->getDictionary()->dropTable(pTab->getName());
896
897 NdbDictionary::Table newTab(* pTab);
898 // Set fragment type for table
899 newTab.setFragmentType((NdbDictionary::Object::FragmentType)fragTtype);
900
901 // Try to create table in db
902 if (newTab.createTableInDb(pNdb) != 0){
903 ndbout << newTab.getName() << " could not be created"
904 << ", fragmentType = "<<fragTtype <<endl;
905 ndbout << pNdb->getDictionary()->getNdbError() << endl;
906 return NDBT_FAILED;
907 }
908
909 // Verify that table exists in db
910 const NdbDictionary::Table* pTab3 =
911 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName()) ;
912 if (pTab3 == NULL){
913 ndbout << pTab->getName() << " was not found in DB"<< endl;
914 return NDBT_FAILED;
915
916 }
917
918 if (pTab3->getFragmentType() != fragTtype){
919 ndbout << pTab->getName() << " fragmentType error "<< endl;
920 result = NDBT_FAILED;
921 goto drop_the_tab;
922 }
923 /**
924 This test does not work since fragmentation is
925 decided by the kernel, hence the fragementation
926 attribute on the column will differ
927
928 if (newTab.equal(*pTab3) == false){
929 ndbout << "It was not equal" << endl;
930 result = NDBT_FAILED;
931 goto drop_the_tab;
932 }
933 */
934 do {
935
936 HugoTransactions hugoTrans(*pTab3);
937 UtilTransactions utilTrans(*pTab3);
938 int count;
939 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
940 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
941 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
942 CHECK(count == records);
943 CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
944 CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
945 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
946 CHECK(count == (records/2));
947
948 // restart all
949 ndbout << "Restarting cluster" << endl;
950 CHECK(restarter.restartAll() == 0);
951 int timeout = 120;
952 CHECK(restarter.waitClusterStarted(timeout) == 0);
953 CHECK(pNdb->waitUntilReady(timeout) == 0);
954
955 // Verify content
956 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
957 CHECK(count == (records/2));
958
959 CHECK(utilTrans.clearTable(pNdb, records) == 0);
960 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
961 CHECK(utilTrans.clearTable(pNdb, records) == 0);
962 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
963 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
964 CHECK(utilTrans.clearTable(pNdb, records, 64) == 0);
965
966 } while(false);
967
968 drop_the_tab:
969
970 // Try to drop table in db
971 if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
972 ndbout << pTab3->getName() << " could not be dropped"<< endl;
973 result = NDBT_FAILED;
974 }
975
976 return result;
977 }
978
979
runTestTemporaryTables(NDBT_Context * ctx,NDBT_Step * step)980 int runTestTemporaryTables(NDBT_Context* ctx, NDBT_Step* step){
981 int result = NDBT_OK;
982 int loops = ctx->getNumLoops();
983 int records = ctx->getNumRecords();
984 Ndb* pNdb = GETNDB(step);
985 int i = 0;
986 NdbRestarter restarter;
987
988 const NdbDictionary::Table* pTab = ctx->getTab();
989 ndbout << "|- " << pTab->getName() << endl;
990
991 NdbDictionary::Table newTab(* pTab);
992 // Set table as temporary
993 newTab.setStoredTable(false);
994
995 // Try to create table in db
996 if (newTab.createTableInDb(pNdb) != 0){
997 return NDBT_FAILED;
998 }
999
1000 // Verify that table is in db
1001 const NdbDictionary::Table* pTab2 =
1002 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1003 if (pTab2 == NULL){
1004 ndbout << pTab->getName() << " was not found in DB"<< endl;
1005 return NDBT_FAILED;
1006 }
1007
1008 if (pTab2->getStoredTable() != false){
1009 ndbout << pTab->getName() << " was not temporary in DB"<< endl;
1010 result = NDBT_FAILED;
1011 goto drop_the_tab;
1012 }
1013
1014
1015 while (i < loops && result == NDBT_OK){
1016 ndbout << i << ": ";
1017
1018 HugoTransactions hugoTrans(*pTab2);
1019 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1020
1021 int count = 0;
1022 UtilTransactions utilTrans(*pTab2);
1023 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1024 CHECK(count == records);
1025
1026 // restart all
1027 ndbout << "Restarting cluster" << endl;
1028 CHECK(restarter.restartAll() == 0);
1029 int timeout = 120;
1030 CHECK(restarter.waitClusterStarted(timeout) == 0);
1031 CHECK(pNdb->waitUntilReady(timeout) == 0);
1032
1033 ndbout << "Verifying records..." << endl;
1034 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1035 CHECK(count == 0);
1036
1037 i++;
1038 }
1039
1040 drop_the_tab:
1041
1042
1043 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1044 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
1045 result = NDBT_FAILED;
1046 }
1047
1048 // Verify that table is not in db
1049 const NdbDictionary::Table* pTab3 =
1050 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1051 if (pTab3 != NULL){
1052 ndbout << pTab3->getName() << " was found in DB"<< endl;
1053 result = NDBT_FAILED;
1054 }
1055
1056 return result;
1057 }
1058
runPkSizes(NDBT_Context * ctx,NDBT_Step * step)1059 int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){
1060 int result = NDBT_OK;
1061 char tabName[256];
1062 int minPkSize = 1;
1063 ndbout << "minPkSize=" <<minPkSize<<endl;
1064 int maxPkSize = MAX_KEY_SIZE_IN_WORDS * 4;
1065 ndbout << "maxPkSize=" <<maxPkSize<<endl;
1066 Ndb* pNdb = GETNDB(step);
1067 int numRecords = ctx->getNumRecords();
1068
1069 for (int i = minPkSize; i < maxPkSize; i++){
1070 BaseString::snprintf(tabName, 256, "TPK_%d", i);
1071
1072 int records = numRecords;
1073 int max = ~0;
1074 // Limit num records for small PKs
1075 if (i == 1)
1076 max = 99;
1077 if (i == 2)
1078 max = 999;
1079 if (i == 3)
1080 max = 9999;
1081 if (records > max)
1082 records = max;
1083 ndbout << "records =" << records << endl;
1084
1085 if (pNdb->waitUntilReady(30) != 0){
1086 // Db is not ready, return with failure
1087 return NDBT_FAILED;
1088 }
1089
1090 ndbout << "|- " << tabName << endl;
1091
1092 if (NDBT_Tables::createTable(pNdb, tabName) != 0){
1093 ndbout << tabName << " could not be created"<< endl;
1094 return NDBT_FAILED;
1095 }
1096
1097 // Verify that table exists in db
1098 const NdbDictionary::Table* pTab3 =
1099 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
1100 if (pTab3 == NULL){
1101 g_err << tabName << " was not found in DB"<< endl;
1102 return NDBT_FAILED;
1103 }
1104
1105 // ndbout << *pTab3 << endl;
1106
1107 if (pTab3->equal(*NDBT_Tables::getTable(tabName)) == false){
1108 g_err << "It was not equal" << endl;
1109 return NDBT_FAILED;
1110 }
1111
1112 do {
1113 // Do it all
1114 HugoTransactions hugoTrans(*pTab3);
1115 UtilTransactions utilTrans(*pTab3);
1116 int count;
1117 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1118 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1119 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1120 CHECK(count == records);
1121 CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1122 CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
1123 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1124 CHECK(count == (records/2));
1125 CHECK(utilTrans.clearTable(pNdb, records) == 0);
1126
1127 #if 0
1128 // Fill table
1129 CHECK(hugoTrans.fillTable(pNdb) == 0);
1130 CHECK(utilTrans.clearTable2(pNdb, records) == 0);
1131 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1132 CHECK(count == 0);
1133 #endif
1134 } while(false);
1135
1136 // Drop table
1137 if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
1138 ndbout << "Failed to drop "<<pTab3->getName()<<" in db" << endl;
1139 return NDBT_FAILED;
1140 }
1141 }
1142 return result;
1143 }
1144
runStoreFrm(NDBT_Context * ctx,NDBT_Step * step)1145 int runStoreFrm(NDBT_Context* ctx, NDBT_Step* step){
1146 Ndb* pNdb = GETNDB(step);
1147 const NdbDictionary::Table* pTab = ctx->getTab();
1148 int result = NDBT_OK;
1149 int loops = ctx->getNumLoops();
1150
1151 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1152
1153 Uint32 dataLen = (Uint32)myRandom48(MAX_FRM_DATA_SIZE);
1154 // size_t dataLen = 10;
1155 unsigned char data[MAX_FRM_DATA_SIZE];
1156
1157 char start = l + 248;
1158 for(Uint32 i = 0; i < dataLen; i++){
1159 data[i] = start;
1160 start++;
1161 }
1162 #if 0
1163 ndbout << "dataLen="<<dataLen<<endl;
1164 for (Uint32 i = 0; i < dataLen; i++){
1165 unsigned char c = data[i];
1166 ndbout << hex << c << ", ";
1167 }
1168 ndbout << endl;
1169 #endif
1170
1171 NdbDictionary::Table newTab(* pTab);
1172 void* pData = &data;
1173 newTab.setFrm(pData, dataLen);
1174
1175 // Try to create table in db
1176 if (newTab.createTableInDb(pNdb) != 0){
1177 result = NDBT_FAILED;
1178 continue;
1179 }
1180
1181 // Verify that table is in db
1182 const NdbDictionary::Table* pTab2 =
1183 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1184 if (pTab2 == NULL){
1185 g_err << pTab->getName() << " was not found in DB"<< endl;
1186 result = NDBT_FAILED;
1187 continue;
1188 }
1189
1190 const void* pData2 = pTab2->getFrmData();
1191 Uint32 resultLen = pTab2->getFrmLength();
1192 if (dataLen != resultLen){
1193 g_err << "Length of data failure" << endl
1194 << " expected = " << dataLen << endl
1195 << " got = " << resultLen << endl;
1196 result = NDBT_FAILED;
1197 }
1198
1199 // Verfiy the frm data
1200 if (memcmp(pData, pData2, resultLen) != 0){
1201 g_err << "Wrong data recieved" << endl;
1202 for (size_t i = 0; i < dataLen; i++){
1203 unsigned char c = ((unsigned char*)pData2)[i];
1204 g_err << hex << c << ", ";
1205 }
1206 g_err << endl;
1207 result = NDBT_FAILED;
1208 }
1209
1210 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1211 g_err << "It can NOT be dropped" << endl;
1212 result = NDBT_FAILED;
1213 }
1214 }
1215
1216 return result;
1217 }
1218
runStoreFrmError(NDBT_Context * ctx,NDBT_Step * step)1219 int runStoreFrmError(NDBT_Context* ctx, NDBT_Step* step){
1220 Ndb* pNdb = GETNDB(step);
1221 const NdbDictionary::Table* pTab = ctx->getTab();
1222 int result = NDBT_OK;
1223 int loops = ctx->getNumLoops();
1224
1225 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1226
1227 const Uint32 dataLen = MAX_FRM_DATA_SIZE + 10;
1228 unsigned char data[dataLen];
1229
1230 char start = l + 248;
1231 for(Uint32 i = 0; i < dataLen; i++){
1232 data[i] = start;
1233 start++;
1234 }
1235 #if 0
1236 ndbout << "dataLen="<<dataLen<<endl;
1237 for (Uint32 i = 0; i < dataLen; i++){
1238 unsigned char c = data[i];
1239 ndbout << hex << c << ", ";
1240 }
1241 ndbout << endl;
1242 #endif
1243
1244 NdbDictionary::Table newTab(* pTab);
1245
1246 void* pData = &data;
1247 newTab.setFrm(pData, dataLen);
1248
1249 // Try to create table in db
1250 if (newTab.createTableInDb(pNdb) == 0){
1251 result = NDBT_FAILED;
1252 continue;
1253 }
1254
1255 const NdbDictionary::Table* pTab2 =
1256 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1257 if (pTab2 != NULL){
1258 g_err << pTab->getName() << " was found in DB"<< endl;
1259 result = NDBT_FAILED;
1260 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1261 g_err << "It can NOT be dropped" << endl;
1262 result = NDBT_FAILED;
1263 }
1264
1265 continue;
1266 }
1267
1268 }
1269
1270 return result;
1271 }
1272
verifyTablesAreEqual(const NdbDictionary::Table * pTab,const NdbDictionary::Table * pTab2)1273 int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary::Table* pTab2){
1274 // Verify that getPrimaryKey only returned true for primary keys
1275 for (int i = 0; i < pTab2->getNoOfColumns(); i++){
1276 const NdbDictionary::Column* col = pTab->getColumn(i);
1277 const NdbDictionary::Column* col2 = pTab2->getColumn(i);
1278 if (col->getPrimaryKey() != col2->getPrimaryKey()){
1279 g_err << "col->getPrimaryKey() != col2->getPrimaryKey()" << endl;
1280 return NDBT_FAILED;
1281 }
1282 }
1283
1284 if (!pTab->equal(*pTab2)){
1285 g_err << "equal failed" << endl;
1286 g_info << *(NDBT_Table*)pTab; // gcc-4.1.2
1287 g_info << *(NDBT_Table*)pTab2;
1288 return NDBT_FAILED;
1289 }
1290 return NDBT_OK;
1291 }
1292
runGetPrimaryKey(NDBT_Context * ctx,NDBT_Step * step)1293 int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
1294 Ndb* pNdb = GETNDB(step);
1295 const NdbDictionary::Table* pTab = ctx->getTab();
1296 ndbout << "|- " << pTab->getName() << endl;
1297 g_info << *(NDBT_Table*)pTab;
1298 // Try to create table in db
1299 if (pTab->createTableInDb(pNdb) != 0){
1300 return NDBT_FAILED;
1301 }
1302
1303 const NdbDictionary::Table* pTab2 =
1304 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1305 if (pTab2 == NULL){
1306 ndbout << pTab->getName() << " was not found in DB"<< endl;
1307 return NDBT_FAILED;
1308 }
1309
1310 int result = NDBT_OK;
1311 if (verifyTablesAreEqual(pTab, pTab2) != NDBT_OK)
1312 result = NDBT_FAILED;
1313
1314
1315 #if 0
1316 // Create an index on the table and see what
1317 // the function returns now
1318 char name[200];
1319 sprintf(name, "%s_X007", pTab->getName());
1320 NDBT_Index* pInd = new NDBT_Index(name);
1321 pInd->setTable(pTab->getName());
1322 pInd->setType(NdbDictionary::Index::UniqueHashIndex);
1323 // pInd->setLogging(false);
1324 for (int i = 0; i < 2; i++){
1325 const NDBT_Attribute* pAttr = pTab->getAttribute(i);
1326 pInd->addAttribute(*pAttr);
1327 }
1328 g_info << "Create index:" << endl << *pInd;
1329 if (pInd->createIndexInDb(pNdb, false) != 0){
1330 result = NDBT_FAILED;
1331 }
1332 delete pInd;
1333
1334 const NdbDictionary::Table* pTab3 =
1335 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1336 if (pTab3 == NULL){
1337 ndbout << pTab->getName() << " was not found in DB"<< endl;
1338 return NDBT_FAILED;
1339 }
1340
1341 if (verifyTablesAreEqual(pTab, pTab3) != NDBT_OK)
1342 result = NDBT_FAILED;
1343 if (verifyTablesAreEqual(pTab2, pTab3) != NDBT_OK)
1344 result = NDBT_FAILED;
1345 #endif
1346
1347 #if 0
1348 if (pTab2->getDictionary()->dropTable(pNdb) != 0){
1349 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
1350 return NDBT_FAILED;
1351 }
1352
1353 // Verify that table is not in db
1354 const NdbDictionary::Table* pTab4 =
1355 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1356 if (pTab4 != NULL){
1357 ndbout << pTab4->getName() << " was found in DB"<< endl;
1358 return NDBT_FAILED;
1359 }
1360 #endif
1361
1362 return result;
1363 }
1364
1365 #define APIERROR(error) \
1366 { g_err << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
1367 << error.code << ", msg: " << error.message << "." << endl; \
1368 }
1369
1370 int
runCreateAutoincrementTable(NDBT_Context * ctx,NDBT_Step * step)1371 runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){
1372
1373 Uint32 startvalues[5] = {256-2, 0, 256*256-2, ~Uint32(0), 256*256*256-2};
1374
1375 int ret = NDBT_OK;
1376
1377 for (int jj = 0; jj < 5 && ret == NDBT_OK; jj++) {
1378 char tabname[] = "AUTOINCTAB";
1379 Uint32 startvalue = startvalues[jj];
1380
1381 NdbDictionary::Table myTable;
1382 NdbDictionary::Column myColumn;
1383
1384 Ndb* myNdb = GETNDB(step);
1385 NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
1386
1387
1388 if (myDict->getTable(tabname) != NULL) {
1389 g_err << "NDB already has example table: " << tabname << endl;
1390 APIERROR(myNdb->getNdbError());
1391 return NDBT_FAILED;
1392 }
1393
1394 myTable.setName(tabname);
1395
1396 myColumn.setName("ATTR1");
1397 myColumn.setType(NdbDictionary::Column::Unsigned);
1398 myColumn.setLength(1);
1399 myColumn.setPrimaryKey(true);
1400 myColumn.setNullable(false);
1401 myColumn.setAutoIncrement(true);
1402 if (startvalue != ~Uint32(0)) // check that default value starts with 1
1403 myColumn.setAutoIncrementInitialValue(startvalue);
1404 myTable.addColumn(myColumn);
1405
1406 if (myDict->createTable(myTable) == -1) {
1407 g_err << "Failed to create table " << tabname << endl;
1408 APIERROR(myNdb->getNdbError());
1409 return NDBT_FAILED;
1410 }
1411
1412
1413 if (startvalue == ~Uint32(0)) // check that default value starts with 1
1414 startvalue = 1;
1415
1416 for (int i = 0; i < 16; i++) {
1417
1418 Uint64 value;
1419 if (myNdb->getAutoIncrementValue(tabname, value, 1) == -1) {
1420 g_err << "getAutoIncrementValue failed on " << tabname << endl;
1421 APIERROR(myNdb->getNdbError());
1422 return NDBT_FAILED;
1423 }
1424 else if (value != (startvalue+i)) {
1425 g_err << "value = " << value << " expected " << startvalue+i << endl;;
1426 APIERROR(myNdb->getNdbError());
1427 // ret = NDBT_FAILED;
1428 // break;
1429 }
1430 }
1431
1432 if (myDict->dropTable(tabname) == -1) {
1433 g_err << "Failed to drop table " << tabname << endl;
1434 APIERROR(myNdb->getNdbError());
1435 ret = NDBT_FAILED;
1436 }
1437 }
1438
1439 return ret;
1440 }
1441
1442 int
runTableRename(NDBT_Context * ctx,NDBT_Step * step)1443 runTableRename(NDBT_Context* ctx, NDBT_Step* step){
1444
1445 int result = NDBT_OK;
1446
1447 Ndb* pNdb = GETNDB(step);
1448 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1449 int records = ctx->getNumRecords();
1450 const int loops = ctx->getNumLoops();
1451
1452 ndbout << "|- " << ctx->getTab()->getName() << endl;
1453
1454 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1455 const NdbDictionary::Table* pTab = ctx->getTab();
1456
1457 // Try to create table in db
1458 if (pTab->createTableInDb(pNdb) != 0){
1459 return NDBT_FAILED;
1460 }
1461
1462 // Verify that table is in db
1463 const NdbDictionary::Table* pTab2 =
1464 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1465 if (pTab2 == NULL){
1466 ndbout << pTab->getName() << " was not found in DB"<< endl;
1467 return NDBT_FAILED;
1468 }
1469 ctx->setTab(pTab2);
1470
1471 // Load table
1472 HugoTransactions hugoTrans(*ctx->getTab());
1473 if (hugoTrans.loadTable(pNdb, records) != 0){
1474 return NDBT_FAILED;
1475 }
1476
1477 // Rename table
1478 BaseString pTabName(pTab->getName());
1479 BaseString pTabNewName(pTabName);
1480 pTabNewName.append("xx");
1481
1482 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
1483 if (oldTable) {
1484 NdbDictionary::Table newTable = *oldTable;
1485 newTable.setName(pTabNewName.c_str());
1486 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1487 "TableRename failed");
1488 }
1489 else {
1490 result = NDBT_FAILED;
1491 }
1492
1493 // Verify table contents
1494 NdbDictionary::Table pNewTab(pTabNewName.c_str());
1495
1496 UtilTransactions utilTrans(pNewTab);
1497 if (utilTrans.clearTable(pNdb, records) != 0){
1498 continue;
1499 }
1500
1501 // Drop table
1502 dict->dropTable(pNewTab.getName());
1503 }
1504 end:
1505
1506 return result;
1507 }
1508
1509 int
runTableRenameSR(NDBT_Context * ctx,NDBT_Step * step)1510 runTableRenameSR(NDBT_Context* ctx, NDBT_Step* step){
1511 NdbRestarter restarter;
1512 if(restarter.getNumDbNodes() < 2)
1513 return NDBT_OK;
1514
1515 int result = NDBT_OK;
1516
1517 Ndb* pNdb = GETNDB(step);
1518 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1519 int records = ctx->getNumRecords();
1520 const int loops = ctx->getNumLoops();
1521
1522 ndbout << "|- " << ctx->getTab()->getName() << endl;
1523
1524 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1525 // Rename table
1526 const NdbDictionary::Table* pTab = ctx->getTab();
1527
1528 // Try to create table in db
1529 if (pTab->createTableInDb(pNdb) != 0){
1530 return NDBT_FAILED;
1531 }
1532
1533 // Verify that table is in db
1534 const NdbDictionary::Table* pTab2 =
1535 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1536 if (pTab2 == NULL){
1537 ndbout << pTab->getName() << " was not found in DB"<< endl;
1538 return NDBT_FAILED;
1539 }
1540 ctx->setTab(pTab2);
1541
1542 // Load table
1543 HugoTransactions hugoTrans(*ctx->getTab());
1544 if (hugoTrans.loadTable(pNdb, records) != 0){
1545 return NDBT_FAILED;
1546 }
1547
1548 BaseString pTabName(pTab->getName());
1549 BaseString pTabNewName(pTabName);
1550 pTabNewName.append("xx");
1551
1552 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
1553 if (oldTable) {
1554 NdbDictionary::Table newTable = *oldTable;
1555 newTable.setName(pTabNewName.c_str());
1556 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1557 "TableRename failed");
1558 }
1559 else {
1560 result = NDBT_FAILED;
1561 }
1562
1563 // Restart cluster
1564
1565 /**
1566 * Need to run LCP at high rate otherwise
1567 * packed replicas become "to many"
1568 */
1569 int val = DumpStateOrd::DihMinTimeBetweenLCP;
1570 if(restarter.dumpStateAllNodes(&val, 1) != 0){
1571 do { CHECK(0); } while(0);
1572 g_err << "Failed to set LCP to min value" << endl;
1573 return NDBT_FAILED;
1574 }
1575
1576 CHECK2(restarter.restartAll() == 0,
1577 "failed to set restartOneDbNode");
1578
1579 CHECK2(restarter.waitClusterStarted() == 0,
1580 "waitClusterStarted failed");
1581
1582 // Verify table contents
1583 NdbDictionary::Table pNewTab(pTabNewName.c_str());
1584
1585 UtilTransactions utilTrans(pNewTab);
1586 if (utilTrans.clearTable(pNdb, records) != 0){
1587 continue;
1588 }
1589
1590 // Drop table
1591 dict->dropTable(pTabNewName.c_str());
1592 }
1593 end:
1594 return result;
1595 }
1596
1597 /*
1598 Run online alter table add attributes.
1599 */
1600 int
runTableAddAttrs(NDBT_Context * ctx,NDBT_Step * step)1601 runTableAddAttrs(NDBT_Context* ctx, NDBT_Step* step){
1602
1603 int result = NDBT_OK;
1604
1605 Ndb* pNdb = GETNDB(step);
1606 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1607 int records = ctx->getNumRecords();
1608 const int loops = ctx->getNumLoops();
1609
1610 ndbout << "|- " << ctx->getTab()->getName() << endl;
1611
1612 NdbDictionary::Table myTab= *(ctx->getTab());
1613
1614 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1615 // Try to create table in db
1616
1617 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
1618 return NDBT_FAILED;
1619 }
1620
1621 // Verify that table is in db
1622 const NdbDictionary::Table* pTab2 =
1623 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
1624 if (pTab2 == NULL){
1625 ndbout << myTab.getName() << " was not found in DB"<< endl;
1626 return NDBT_FAILED;
1627 }
1628 ctx->setTab(pTab2);
1629
1630 /*
1631 Check that table already has a varpart, otherwise add attr is
1632 not possible.
1633 */
1634 if (pTab2->getForceVarPart() == false)
1635 {
1636 const NdbDictionary::Column *col;
1637 for (Uint32 i= 0; (col= pTab2->getColumn(i)) != 0; i++)
1638 {
1639 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
1640 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
1641 break;
1642 }
1643 if (col == 0)
1644 {
1645 /* Alter table add attribute not applicable, just mark success. */
1646 dict->dropTable(pTab2->getName());
1647 break;
1648 }
1649 }
1650
1651 // Load table
1652 HugoTransactions beforeTrans(*ctx->getTab());
1653 if (beforeTrans.loadTable(pNdb, records) != 0){
1654 return NDBT_FAILED;
1655 }
1656
1657 // Add attributes to table.
1658 BaseString pTabName(pTab2->getName());
1659
1660 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
1661 if (oldTable) {
1662 NdbDictionary::Table newTable= *oldTable;
1663
1664 NDBT_Attribute newcol1("NEWKOL1", NdbDictionary::Column::Unsigned, 1,
1665 false, true, 0,
1666 NdbDictionary::Column::StorageTypeMemory, true);
1667 newTable.addColumn(newcol1);
1668 NDBT_Attribute newcol2("NEWKOL2", NdbDictionary::Column::Char, 14,
1669 false, true, 0,
1670 NdbDictionary::Column::StorageTypeMemory, true);
1671 newTable.addColumn(newcol2);
1672 NDBT_Attribute newcol3("NEWKOL3", NdbDictionary::Column::Bit, 20,
1673 false, true, 0,
1674 NdbDictionary::Column::StorageTypeMemory, true);
1675 newTable.addColumn(newcol3);
1676 NDBT_Attribute newcol4("NEWKOL4", NdbDictionary::Column::Varbinary, 42,
1677 false, true, 0,
1678 NdbDictionary::Column::StorageTypeMemory, true);
1679 newTable.addColumn(newcol4);
1680
1681 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1682 "TableAddAttrs failed");
1683 /* Need to purge old version and reload new version after alter table. */
1684 dict->invalidateTable(pTabName.c_str());
1685 }
1686 else {
1687 result = NDBT_FAILED;
1688 }
1689
1690 {
1691 HugoTransactions afterTrans(* dict->getTable(pTabName.c_str()));
1692
1693 ndbout << "delete...";
1694 if (afterTrans.clearTable(pNdb) != 0)
1695 {
1696 return NDBT_FAILED;
1697 }
1698 ndbout << endl;
1699
1700 ndbout << "insert...";
1701 if (afterTrans.loadTable(pNdb, records) != 0){
1702 return NDBT_FAILED;
1703 }
1704 ndbout << endl;
1705
1706 ndbout << "update...";
1707 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
1708 {
1709 return NDBT_FAILED;
1710 }
1711 ndbout << endl;
1712
1713 ndbout << "delete...";
1714 if (afterTrans.clearTable(pNdb) != 0)
1715 {
1716 return NDBT_FAILED;
1717 }
1718 ndbout << endl;
1719 }
1720
1721 // Drop table.
1722 dict->dropTable(pTabName.c_str());
1723 }
1724 end:
1725
1726 return result;
1727 }
1728
1729 /*
1730 Run online alter table add attributes while running simultaneous
1731 transactions on it in separate thread.
1732 */
1733 int
runTableAddAttrsDuring(NDBT_Context * ctx,NDBT_Step * step)1734 runTableAddAttrsDuring(NDBT_Context* ctx, NDBT_Step* step){
1735
1736 int result = NDBT_OK;
1737 int abortAlter = ctx->getProperty("AbortAlter", Uint32(0));
1738
1739 int records = ctx->getNumRecords();
1740 const int loops = ctx->getNumLoops();
1741 NdbRestarter res;
1742
1743 ndbout << "|- " << ctx->getTab()->getName() << endl;
1744
1745 NdbDictionary::Table myTab= *(ctx->getTab());
1746
1747 if (myTab.getForceVarPart() == false)
1748 {
1749 const NdbDictionary::Column *col;
1750 for (Uint32 i= 0; (col= myTab.getColumn(i)) != 0; i++)
1751 {
1752 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
1753 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
1754 break;
1755 }
1756 if (col == 0)
1757 {
1758 ctx->stopTest();
1759 return NDBT_OK;
1760 }
1761 }
1762
1763 //if
1764
1765 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1766 ndbout << l << ": " << endl;
1767
1768 Ndb* pNdb = GETNDB(step);
1769 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1770
1771 /*
1772 Check that table already has a varpart, otherwise add attr is
1773 not possible.
1774 */
1775
1776 // Add attributes to table.
1777 ndbout << "Altering table" << endl;
1778
1779 const NdbDictionary::Table * oldTable = dict->getTable(myTab.getName());
1780 if (oldTable) {
1781 NdbDictionary::Table newTable= *oldTable;
1782
1783 char name[256];
1784 BaseString::snprintf(name, sizeof(name), "NEWCOL%d", l);
1785 NDBT_Attribute newcol1(name, NdbDictionary::Column::Unsigned, 1,
1786 false, true, 0,
1787 NdbDictionary::Column::StorageTypeMemory, true);
1788 newTable.addColumn(newcol1);
1789 //ToDo: check #loops, how many columns l
1790
1791 if (abortAlter == 0)
1792 {
1793 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1794 "TableAddAttrsDuring failed");
1795 }
1796 else
1797 {
1798 int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
1799 res.insertErrorInNode(nodeId, 4029);
1800 CHECK2(dict->alterTable(*oldTable, newTable) != 0,
1801 "TableAddAttrsDuring failed");
1802 }
1803
1804 dict->invalidateTable(myTab.getName());
1805 const NdbDictionary::Table * newTab = dict->getTable(myTab.getName());
1806 HugoTransactions hugoTrans(* newTab);
1807 hugoTrans.scanUpdateRecords(pNdb, records);
1808 }
1809 else {
1810 result= NDBT_FAILED;
1811 break;
1812 }
1813 }
1814 end:
1815
1816 ctx->stopTest();
1817
1818 return result;
1819 }
1820
1821 static void
f(const NdbDictionary::Column * col)1822 f(const NdbDictionary::Column * col){
1823 if(col == 0){
1824 abort();
1825 }
1826 }
1827
1828 int
runTestDictionaryPerf(NDBT_Context * ctx,NDBT_Step * step)1829 runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
1830 Vector<char*> cols;
1831 Vector<const NdbDictionary::Table*> tabs;
1832 int i;
1833
1834 Ndb* pNdb = GETNDB(step);
1835
1836 const Uint32 count = NDBT_Tables::getNumTables();
1837 for (i=0; i < (int)count; i++){
1838 const NdbDictionary::Table * tab = NDBT_Tables::getTable(i);
1839 pNdb->getDictionary()->createTable(* tab);
1840
1841 const NdbDictionary::Table * tab2 = pNdb->getDictionary()->getTable(tab->getName());
1842
1843 for(size_t j = 0; j<(size_t)tab->getNoOfColumns(); j++){
1844 cols.push_back((char*)tab2);
1845 cols.push_back(strdup(tab->getColumn(j)->getName()));
1846 }
1847 }
1848
1849 const Uint32 times = 10000000;
1850
1851 ndbout_c("%d tables and %d columns",
1852 NDBT_Tables::getNumTables(), cols.size()/2);
1853
1854 char ** tcols = cols.getBase();
1855
1856 srand((unsigned int)time(0));
1857 Uint32 size = cols.size() / 2;
1858 //char ** columns = &cols[0];
1859 Uint64 start = NdbTick_CurrentMillisecond();
1860 for(i = 0; i<(int)times; i++){
1861 int j = 2 * (rand() % size);
1862 const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j];
1863 const char * col = tcols[j+1];
1864 const NdbDictionary::Column* column = tab->getColumn(col);
1865 f(column);
1866 }
1867 Uint64 stop = NdbTick_CurrentMillisecond();
1868 stop -= start;
1869
1870 Uint64 per = stop;
1871 per *= 1000;
1872 per /= times;
1873
1874 ndbout_c("%d random getColumn(name) in %Ld ms -> %u us/get",
1875 times, stop, Uint32(per));
1876
1877 return NDBT_OK;
1878 }
1879
1880 int
runCreateLogfileGroup(NDBT_Context * ctx,NDBT_Step * step)1881 runCreateLogfileGroup(NDBT_Context* ctx, NDBT_Step* step){
1882 Ndb* pNdb = GETNDB(step);
1883 NdbDictionary::LogfileGroup lg;
1884 lg.setName("DEFAULT-LG");
1885 lg.setUndoBufferSize(8*1024*1024);
1886
1887 int res;
1888 res = pNdb->getDictionary()->createLogfileGroup(lg);
1889 if(res != 0){
1890 g_err << "Failed to create logfilegroup:"
1891 << endl << pNdb->getDictionary()->getNdbError() << endl;
1892 return NDBT_FAILED;
1893 }
1894
1895 NdbDictionary::Undofile uf;
1896 uf.setPath("undofile01.dat");
1897 uf.setSize(5*1024*1024);
1898 uf.setLogfileGroup("DEFAULT-LG");
1899
1900 res = pNdb->getDictionary()->createUndofile(uf);
1901 if(res != 0){
1902 g_err << "Failed to create undofile:"
1903 << endl << pNdb->getDictionary()->getNdbError() << endl;
1904 return NDBT_FAILED;
1905 }
1906
1907 uf.setPath("undofile02.dat");
1908 uf.setSize(5*1024*1024);
1909 uf.setLogfileGroup("DEFAULT-LG");
1910
1911 res = pNdb->getDictionary()->createUndofile(uf);
1912 if(res != 0){
1913 g_err << "Failed to create undofile:"
1914 << endl << pNdb->getDictionary()->getNdbError() << endl;
1915 return NDBT_FAILED;
1916 }
1917
1918 return NDBT_OK;
1919 }
1920
1921 int
runCreateTablespace(NDBT_Context * ctx,NDBT_Step * step)1922 runCreateTablespace(NDBT_Context* ctx, NDBT_Step* step){
1923 Ndb* pNdb = GETNDB(step);
1924 NdbDictionary::Tablespace lg;
1925 lg.setName("DEFAULT-TS");
1926 lg.setExtentSize(1024*1024);
1927 lg.setDefaultLogfileGroup("DEFAULT-LG");
1928
1929 int res;
1930 res = pNdb->getDictionary()->createTablespace(lg);
1931 if(res != 0){
1932 g_err << "Failed to create tablespace:"
1933 << endl << pNdb->getDictionary()->getNdbError() << endl;
1934 return NDBT_FAILED;
1935 }
1936
1937 NdbDictionary::Datafile uf;
1938 uf.setPath("datafile01.dat");
1939 uf.setSize(10*1024*1024);
1940 uf.setTablespace("DEFAULT-TS");
1941
1942 res = pNdb->getDictionary()->createDatafile(uf);
1943 if(res != 0){
1944 g_err << "Failed to create datafile:"
1945 << endl << pNdb->getDictionary()->getNdbError() << endl;
1946 return NDBT_FAILED;
1947 }
1948
1949 return NDBT_OK;
1950 }
1951 int
runCreateDiskTable(NDBT_Context * ctx,NDBT_Step * step)1952 runCreateDiskTable(NDBT_Context* ctx, NDBT_Step* step){
1953 Ndb* pNdb = GETNDB(step);
1954
1955 NdbDictionary::Table tab = *ctx->getTab();
1956 tab.setTablespaceName("DEFAULT-TS");
1957
1958 for(Uint32 i = 0; i<(Uint32)tab.getNoOfColumns(); i++)
1959 if(!tab.getColumn(i)->getPrimaryKey())
1960 tab.getColumn(i)->setStorageType(NdbDictionary::Column::StorageTypeDisk);
1961
1962 int res;
1963 res = pNdb->getDictionary()->createTable(tab);
1964 if(res != 0){
1965 g_err << "Failed to create table:"
1966 << endl << pNdb->getDictionary()->getNdbError() << endl;
1967 return NDBT_FAILED;
1968 }
1969
1970 return NDBT_OK;
1971 }
1972
getColumnMaxLength(const NdbDictionary::Column * c)1973 int getColumnMaxLength(const NdbDictionary::Column* c)
1974 {
1975 int length= c->getLength();
1976 if (c->getArrayType() == NDB_ARRAYTYPE_FIXED)
1977 {
1978 /* Not yet set - need to calculate from type etc. */
1979 DictTabInfo::Attribute attrDesc;
1980
1981 attrDesc.init();
1982 attrDesc.AttributeExtType= c->getType();
1983 attrDesc.AttributeExtLength= c->getLength();
1984 attrDesc.AttributeExtPrecision= c->getPrecision();
1985 attrDesc.AttributeExtScale= c->getScale();
1986
1987 if (!attrDesc.translateExtType())
1988 {
1989 return 0;
1990 }
1991
1992 if (attrDesc.AttributeSize == 0)
1993 {
1994 // bits...
1995 length = 4 * ((c->getLength() + 31) / 32);
1996 }
1997 else
1998 {
1999 length = ((1 << attrDesc.AttributeSize) * c->getLength()) >> 3;
2000 }
2001 }
2002
2003 return length;
2004 }
2005
2006 #include <NDBT_Tables.hpp>
2007
2008 #define SAFTY 300
2009
runFailAddFragment(NDBT_Context * ctx,NDBT_Step * step)2010 int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
2011 static int acclst[] = { 3001, 6200, 6202 };
2012 static int tuplst[] = { 4007, 4008, 4009, 4010, 4032, 4033, 4034 };
2013 static int tuxlst[] = { 12001, 12002, 12003, 12004,
2014 6201, 6203 };
2015 static unsigned acccnt = sizeof(acclst)/sizeof(acclst[0]);
2016 static unsigned tupcnt = sizeof(tuplst)/sizeof(tuplst[0]);
2017 static unsigned tuxcnt = sizeof(tuxlst)/sizeof(tuxlst[0]);
2018
2019 NdbRestarter restarter;
2020 int nodeId = restarter.getMasterNodeId();
2021 Ndb* pNdb = GETNDB(step);
2022 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2023 NdbDictionary::Table tab(*ctx->getTab());
2024 tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
2025
2026 int errNo = 0;
2027 char buf[100];
2028 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
2029 {
2030 errNo = atoi(buf);
2031 ndbout_c("Using errno: %u", errNo);
2032 }
2033
2034 const NdbDictionary::Table* origTab= ctx->getTab();
2035 HugoCalculator calc(*origTab);
2036
2037 // Add defaults to some columns
2038 for (int colNum= 0; colNum < tab.getNoOfColumns(); colNum++)
2039 {
2040 const NdbDictionary::Column* origCol= origTab->getColumn(colNum);
2041 NdbDictionary::Column* col= tab.getColumn(colNum);
2042 if (!origCol->getPrimaryKey())
2043 {
2044 if (myRandom48(2) == 0)
2045 {
2046 char defaultBuf[ NDB_MAX_TUPLE_SIZE ];
2047 Uint32 real_len;
2048 Uint32 updatesVal = myRandom48(1 << 16);
2049 const char* def= calc.calcValue(0, colNum, updatesVal,
2050 defaultBuf,
2051 getColumnMaxLength(origCol),
2052 &real_len);
2053 if (col->setDefaultValue(def, real_len) != 0)
2054 {
2055 ndbout_c("Error setting default value\n");
2056 return NDBT_FAILED;
2057 }
2058 NdbDictionary::NdbDataPrintFormat dpf;
2059 ndbout << "Set default for column " << origCol->getName()
2060 << " to ";
2061
2062 NdbDictionary::printFormattedValue(ndbout,
2063 dpf,
2064 col,
2065 def);
2066 ndbout << endl;
2067 }
2068 }
2069 }
2070
2071 // ordered index on first few columns
2072 NdbDictionary::Index idx("X");
2073 idx.setTable(tab.getName());
2074 idx.setType(NdbDictionary::Index::OrderedIndex);
2075 idx.setLogging(false);
2076 for (int cnt = 0, i_hate_broken_compilers = 0;
2077 cnt < 3 &&
2078 i_hate_broken_compilers < tab.getNoOfColumns();
2079 i_hate_broken_compilers++) {
2080 if (NdbSqlUtil::check_column_for_ordered_index
2081 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
2082 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
2083 NdbDictionary::Column::StorageTypeDisk)
2084 {
2085 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
2086 cnt++;
2087 }
2088 }
2089
2090 for (Uint32 i = 0; i<(Uint32)tab.getNoOfColumns(); i++)
2091 {
2092 if (tab.getColumn(i)->getStorageType() ==
2093 NdbDictionary::Column::StorageTypeDisk)
2094 {
2095 NDBT_Tables::create_default_tablespace(pNdb);
2096 break;
2097 }
2098 }
2099
2100 const int loops = ctx->getNumLoops();
2101 int result = NDBT_OK;
2102 (void)pDic->dropTable(tab.getName());
2103
2104 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
2105 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
2106
2107 for (int l = 0; l < loops; l++) {
2108 for (unsigned i0 = 0; i0 < acccnt; i0++) {
2109 unsigned j = (l == 0 ? i0 : myRandom48(acccnt));
2110 int errval = acclst[j];
2111 if (errNo != 0 && errNo != errval)
2112 continue;
2113 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
2114 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
2115 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
2116 "failed to set error insert");
2117 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2118 CHECK2(pDic->createTable(tab) != 0,
2119 "failed to fail after error insert " << errval);
2120 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
2121 "failed to clean error insert value");
2122 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
2123 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2124 CHECK2(pDic->createTable(tab) == 0,
2125 pDic->getNdbError());
2126 CHECK2(pDic->dropTable(tab.getName()) == 0,
2127 pDic->getNdbError());
2128 }
2129 for (unsigned i1 = 0; i1 < tupcnt; i1++) {
2130 unsigned j = (l == 0 ? i1 : myRandom48(tupcnt));
2131 int errval = tuplst[j];
2132 if (errNo != 0 && errNo != errval)
2133 continue;
2134 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
2135 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
2136 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
2137 "failed to set error insert");
2138 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2139 CHECK2(pDic->createTable(tab) != 0,
2140 "failed to fail after error insert " << errval);
2141 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
2142 "failed to clean error insert value");
2143 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
2144 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2145 CHECK2(pDic->createTable(tab) == 0,
2146 pDic->getNdbError());
2147 CHECK2(pDic->dropTable(tab.getName()) == 0,
2148 pDic->getNdbError());
2149 }
2150 for (unsigned i2 = 0; i2 < tuxcnt; i2++) {
2151 unsigned j = (l == 0 ? i2 : myRandom48(tuxcnt));
2152 int errval = tuxlst[j];
2153 if (errNo != 0 && errNo != errval)
2154 continue;
2155 CHECK2(pDic->createTable(tab) == 0,
2156 pDic->getNdbError());
2157
2158 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
2159 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
2160 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
2161 "failed to set error insert");
2162 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2163
2164 CHECK2(pDic->createIndex(idx) != 0,
2165 "failed to fail after error insert " << errval);
2166 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
2167 "failed to clean error insert value");
2168 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
2169 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2170 CHECK2(pDic->createIndex(idx) == 0,
2171 pDic->getNdbError());
2172 CHECK2(pDic->dropTable(tab.getName()) == 0,
2173 pDic->getNdbError());
2174 }
2175 }
2176 end:
2177 return result;
2178 }
2179
2180 // NFNR
2181
2182 // Restarter controls dict ops : 1-run 2-pause 3-stop
2183 // synced by polling...
2184
2185 static bool
send_dict_ops_cmd(NDBT_Context * ctx,Uint32 cmd)2186 send_dict_ops_cmd(NDBT_Context* ctx, Uint32 cmd)
2187 {
2188 ctx->setProperty("DictOps_CMD", cmd);
2189 while (1) {
2190 if (ctx->isTestStopped())
2191 return false;
2192 if (ctx->getProperty("DictOps_ACK") == cmd)
2193 break;
2194 NdbSleep_MilliSleep(100);
2195 }
2196 return true;
2197 }
2198
2199 static bool
recv_dict_ops_run(NDBT_Context * ctx)2200 recv_dict_ops_run(NDBT_Context* ctx)
2201 {
2202 while (1) {
2203 if (ctx->isTestStopped())
2204 return false;
2205 Uint32 cmd = ctx->getProperty("DictOps_CMD");
2206 ctx->setProperty("DictOps_ACK", cmd);
2207 if (cmd == 1)
2208 break;
2209 if (cmd == 3)
2210 return false;
2211 NdbSleep_MilliSleep(100);
2212 }
2213 return true;
2214 }
2215
2216 int
runRestarts(NDBT_Context * ctx,NDBT_Step * step)2217 runRestarts(NDBT_Context* ctx, NDBT_Step* step)
2218 {
2219 static int errlst_master[] = { // non-crashing
2220 7175, // send one fake START_PERMREF
2221 0
2222 };
2223 static int errlst_node[] = {
2224 7174, // crash before sending DICT_LOCK_REQ
2225 7176, // pretend master does not support DICT lock
2226 7121, // crash at receive START_PERMCONF
2227 0
2228 };
2229 const uint errcnt_master = sizeof(errlst_master)/sizeof(errlst_master[0]);
2230 const uint errcnt_node = sizeof(errlst_node)/sizeof(errlst_node[0]);
2231
2232 myRandom48Init((long)NdbTick_CurrentMillisecond());
2233 NdbRestarter restarter;
2234 int result = NDBT_OK;
2235 const int loops = ctx->getNumLoops();
2236
2237 for (int l = 0; l < loops && result == NDBT_OK; l++) {
2238 g_info << "1: === loop " << l << " ===" << endl;
2239
2240 // assuming 2-way replicated
2241
2242 int numnodes = restarter.getNumDbNodes();
2243 CHECK(numnodes >= 1);
2244 if (numnodes == 1)
2245 break;
2246
2247 int masterNodeId = restarter.getMasterNodeId();
2248 CHECK(masterNodeId != -1);
2249
2250 // for more complex cases need more restarter support methods
2251
2252 int nodeIdList[2] = { 0, 0 };
2253 int nodeIdCnt = 0;
2254
2255 if (numnodes >= 2) {
2256 int rand = myRandom48(numnodes);
2257 int nodeId = restarter.getRandomNotMasterNodeId(rand);
2258 CHECK(nodeId != -1);
2259 nodeIdList[nodeIdCnt++] = nodeId;
2260 }
2261
2262 if (numnodes >= 4 && myRandom48(2) == 0) {
2263 int rand = myRandom48(numnodes);
2264 int nodeId = restarter.getRandomNodeOtherNodeGroup(nodeIdList[0], rand);
2265 CHECK(nodeId != -1);
2266 if (nodeId != masterNodeId)
2267 nodeIdList[nodeIdCnt++] = nodeId;
2268 }
2269
2270 g_info << "1: master=" << masterNodeId << " nodes=" << nodeIdList[0] << "," << nodeIdList[1] << endl;
2271
2272 const uint timeout = 60; //secs for node wait
2273 const unsigned maxsleep = 2000; //ms
2274
2275 bool NF_ops = ctx->getProperty("Restart_NF_ops");
2276 uint NF_type = ctx->getProperty("Restart_NF_type");
2277 bool NR_ops = ctx->getProperty("Restart_NR_ops");
2278 bool NR_error = ctx->getProperty("Restart_NR_error");
2279
2280 g_info << "1: " << (NF_ops ? "run" : "pause") << " dict ops" << endl;
2281 if (! send_dict_ops_cmd(ctx, NF_ops ? 1 : 2))
2282 break;
2283 NdbSleep_MilliSleep(myRandom48(maxsleep));
2284
2285 {
2286 for (int i = 0; i < nodeIdCnt; i++) {
2287 int nodeId = nodeIdList[i];
2288
2289 bool nostart = true;
2290 bool abort = NF_type == 0 ? myRandom48(2) : (NF_type == 2);
2291 bool initial = myRandom48(2);
2292
2293 char flags[40];
2294 strcpy(flags, "flags: nostart");
2295 if (abort)
2296 strcat(flags, ",abort");
2297 if (initial)
2298 strcat(flags, ",initial");
2299
2300 g_info << "1: restart " << nodeId << " " << flags << endl;
2301 CHECK(restarter.restartOneDbNode(nodeId, initial, nostart, abort) == 0);
2302 }
2303 }
2304
2305 g_info << "1: wait for nostart" << endl;
2306 CHECK(restarter.waitNodesNoStart(nodeIdList, nodeIdCnt, timeout) == 0);
2307 NdbSleep_MilliSleep(myRandom48(maxsleep));
2308
2309 int err_master = 0;
2310 int err_node[2] = { 0, 0 };
2311
2312 if (NR_error) {
2313 err_master = errlst_master[l % errcnt_master];
2314
2315 // limitation: cannot have 2 node restarts and crash_insert
2316 // one node may die for real (NF during startup)
2317
2318 for (int i = 0; i < nodeIdCnt && nodeIdCnt == 1; i++) {
2319 err_node[i] = errlst_node[l % errcnt_node];
2320
2321 // 7176 - no DICT lock protection
2322
2323 if (err_node[i] == 7176) {
2324 g_info << "1: no dict ops due to error insert "
2325 << err_node[i] << endl;
2326 NR_ops = false;
2327 }
2328 }
2329 }
2330
2331 g_info << "1: " << (NR_ops ? "run" : "pause") << " dict ops" << endl;
2332 if (! send_dict_ops_cmd(ctx, NR_ops ? 1 : 2))
2333 break;
2334 NdbSleep_MilliSleep(myRandom48(maxsleep));
2335
2336 g_info << "1: start nodes" << endl;
2337 CHECK(restarter.startNodes(nodeIdList, nodeIdCnt) == 0);
2338
2339 if (NR_error) {
2340 {
2341 int err = err_master;
2342 if (err != 0) {
2343 g_info << "1: insert master error " << err << endl;
2344 CHECK(restarter.insertErrorInNode(masterNodeId, err) == 0);
2345 }
2346 }
2347
2348 for (int i = 0; i < nodeIdCnt; i++) {
2349 int nodeId = nodeIdList[i];
2350
2351 int err = err_node[i];
2352 if (err != 0) {
2353 g_info << "1: insert node " << nodeId << " error " << err << endl;
2354 CHECK(restarter.insertErrorInNode(nodeId, err) == 0);
2355 }
2356 }
2357 }
2358 NdbSleep_MilliSleep(myRandom48(maxsleep));
2359
2360 g_info << "1: wait cluster started" << endl;
2361 CHECK(restarter.waitClusterStarted(timeout) == 0);
2362 NdbSleep_MilliSleep(myRandom48(maxsleep));
2363
2364 g_info << "1: restart done" << endl;
2365 }
2366
2367 g_info << "1: stop dict ops" << endl;
2368 send_dict_ops_cmd(ctx, 3);
2369
2370 return result;
2371 }
2372
2373 int
runDictOps(NDBT_Context * ctx,NDBT_Step * step)2374 runDictOps(NDBT_Context* ctx, NDBT_Step* step)
2375 {
2376 myRandom48Init((long)NdbTick_CurrentMillisecond());
2377 int result = NDBT_OK;
2378
2379 for (int l = 0; result == NDBT_OK; l++) {
2380 if (! recv_dict_ops_run(ctx))
2381 break;
2382
2383 g_info << "2: === loop " << l << " ===" << endl;
2384
2385 Ndb* pNdb = GETNDB(step);
2386 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2387 const NdbDictionary::Table* pTab = ctx->getTab();
2388 //const char* tabName = pTab->getName(); //XXX what goes on?
2389 char tabName[40];
2390 strcpy(tabName, pTab->getName());
2391
2392 const unsigned long maxsleep = 100; //ms
2393
2394 g_info << "2: create table" << endl;
2395 {
2396 uint count = 0;
2397 try_create:
2398 count++;
2399 if (pDic->createTable(*pTab) != 0) {
2400 const NdbError err = pDic->getNdbError();
2401 if (count == 1)
2402 g_err << "2: " << tabName << ": create failed: " << err << endl;
2403 if (err.code != 711) {
2404 result = NDBT_FAILED;
2405 break;
2406 }
2407 NdbSleep_MilliSleep(myRandom48(maxsleep));
2408 goto try_create;
2409 }
2410 }
2411 NdbSleep_MilliSleep(myRandom48(maxsleep));
2412
2413 g_info << "2: verify create" << endl;
2414 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
2415 if (pTab2 == NULL) {
2416 const NdbError err = pDic->getNdbError();
2417 g_err << "2: " << tabName << ": verify create: " << err << endl;
2418 result = NDBT_FAILED;
2419 break;
2420 }
2421 NdbSleep_MilliSleep(myRandom48(maxsleep));
2422
2423 // replace by the Retrieved table
2424 pTab = pTab2;
2425
2426 // create indexes
2427 const char** indlist = NDBT_Tables::getIndexes(tabName);
2428 uint indnum = 0;
2429 while (indlist != 0 && *indlist != 0) {
2430 uint count = 0;
2431 try_create_index:
2432 count++;
2433 if (count == 1)
2434 g_info << "2: create index " << indnum << " " << *indlist << endl;
2435 NdbDictionary::Index ind;
2436 char indName[200];
2437 sprintf(indName, "%s_X%u", tabName, indnum);
2438 ind.setName(indName);
2439 ind.setTable(tabName);
2440 if (strcmp(*indlist, "UNIQUE") == 0) {
2441 ind.setType(NdbDictionary::Index::UniqueHashIndex);
2442 ind.setLogging(pTab->getLogging());
2443 } else if (strcmp(*indlist, "ORDERED") == 0) {
2444 ind.setType(NdbDictionary::Index::OrderedIndex);
2445 ind.setLogging(false);
2446 } else {
2447 assert(false);
2448 }
2449 const char** indtemp = indlist;
2450 while (*++indtemp != 0) {
2451 ind.addColumn(*indtemp);
2452 }
2453 if (pDic->createIndex(ind) != 0) {
2454 const NdbError err = pDic->getNdbError();
2455 if (count == 1)
2456 g_err << "2: " << indName << ": create failed: " << err << endl;
2457 if (err.code != 711) {
2458 result = NDBT_FAILED;
2459 break;
2460 }
2461 NdbSleep_MilliSleep(myRandom48(maxsleep));
2462 goto try_create_index;
2463 }
2464 indlist = ++indtemp;
2465 indnum++;
2466 }
2467 if (result == NDBT_FAILED)
2468 break;
2469
2470 uint indcount = indnum;
2471
2472 int records = myRandom48(ctx->getNumRecords());
2473 g_info << "2: load " << records << " records" << endl;
2474 HugoTransactions hugoTrans(*pTab);
2475 if (hugoTrans.loadTable(pNdb, records) != 0) {
2476 // XXX get error code from hugo
2477 g_err << "2: " << tabName << ": load failed" << endl;
2478 result = NDBT_FAILED;
2479 break;
2480 }
2481 NdbSleep_MilliSleep(myRandom48(maxsleep));
2482
2483 // drop indexes
2484 indnum = 0;
2485 while (indnum < indcount) {
2486 uint count = 0;
2487 try_drop_index:
2488 count++;
2489 if (count == 1)
2490 g_info << "2: drop index " << indnum << endl;
2491 char indName[200];
2492 sprintf(indName, "%s_X%u", tabName, indnum);
2493 if (pDic->dropIndex(indName, tabName) != 0) {
2494 const NdbError err = pDic->getNdbError();
2495 if (count == 1)
2496 g_err << "2: " << indName << ": drop failed: " << err << endl;
2497 if (err.code != 711) {
2498 result = NDBT_FAILED;
2499 break;
2500 }
2501 NdbSleep_MilliSleep(myRandom48(maxsleep));
2502 goto try_drop_index;
2503 }
2504 indnum++;
2505 }
2506 if (result == NDBT_FAILED)
2507 break;
2508
2509 g_info << "2: drop" << endl;
2510 {
2511 uint count = 0;
2512 try_drop:
2513 count++;
2514 if (pDic->dropTable(tabName) != 0) {
2515 const NdbError err = pDic->getNdbError();
2516 if (count == 1)
2517 g_err << "2: " << tabName << ": drop failed: " << err << endl;
2518 if (err.code != 711) {
2519 result = NDBT_FAILED;
2520 break;
2521 }
2522 NdbSleep_MilliSleep(myRandom48(maxsleep));
2523 goto try_drop;
2524 }
2525 }
2526 NdbSleep_MilliSleep(myRandom48(maxsleep));
2527
2528 g_info << "2: verify drop" << endl;
2529 const NdbDictionary::Table* pTab3 = pDic->getTable(tabName);
2530 if (pTab3 != NULL) {
2531 g_err << "2: " << tabName << ": verify drop: table exists" << endl;
2532 result = NDBT_FAILED;
2533 break;
2534 }
2535 if (pDic->getNdbError().code != 709 &&
2536 pDic->getNdbError().code != 723) {
2537 const NdbError err = pDic->getNdbError();
2538 g_err << "2: " << tabName << ": verify drop: " << err << endl;
2539 result = NDBT_FAILED;
2540 break;
2541 }
2542 NdbSleep_MilliSleep(myRandom48(maxsleep));
2543 }
2544
2545 return result;
2546 }
2547
2548 int
runBug21755(NDBT_Context * ctx,NDBT_Step * step)2549 runBug21755(NDBT_Context* ctx, NDBT_Step* step)
2550 {
2551 char buf[256];
2552 NdbRestarter res;
2553 NdbDictionary::Table pTab0 = * ctx->getTab();
2554 NdbDictionary::Table pTab1 = pTab0;
2555
2556 if (res.getNumDbNodes() < 2)
2557 return NDBT_OK;
2558
2559 Ndb* pNdb = GETNDB(step);
2560 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2561
2562 if (pDic->createTable(pTab0))
2563 {
2564 ndbout << pDic->getNdbError() << endl;
2565 return NDBT_FAILED;
2566 }
2567
2568 NdbDictionary::Index idx0;
2569 BaseString::snprintf(buf, sizeof(buf), "%s-idx", pTab0.getName());
2570 idx0.setName(buf);
2571 idx0.setType(NdbDictionary::Index::OrderedIndex);
2572 idx0.setTable(pTab0.getName());
2573 idx0.setStoredIndex(false);
2574 for (Uint32 i = 0; i<(Uint32)pTab0.getNoOfColumns(); i++)
2575 {
2576 const NdbDictionary::Column * col = pTab0.getColumn(i);
2577 if(col->getPrimaryKey()){
2578 idx0.addIndexColumn(col->getName());
2579 }
2580 }
2581
2582 if (pDic->createIndex(idx0))
2583 {
2584 ndbout << pDic->getNdbError() << endl;
2585 return NDBT_FAILED;
2586 }
2587
2588 BaseString::snprintf(buf, sizeof(buf), "%s-2", pTab1.getName());
2589 pTab1.setName(buf);
2590
2591 if (pDic->createTable(pTab1))
2592 {
2593 ndbout << pDic->getNdbError() << endl;
2594 return NDBT_FAILED;
2595 }
2596
2597 {
2598 HugoTransactions t0 (*pDic->getTable(pTab0.getName()));
2599 t0.loadTable(pNdb, 1000);
2600 }
2601
2602 {
2603 HugoTransactions t1 (*pDic->getTable(pTab1.getName()));
2604 t1.loadTable(pNdb, 1000);
2605 }
2606
2607 int node = res.getRandomNotMasterNodeId(rand());
2608 res.restartOneDbNode(node, false, true, true);
2609
2610 if (pDic->dropTable(pTab1.getName()))
2611 {
2612 ndbout << pDic->getNdbError() << endl;
2613 return NDBT_FAILED;
2614 }
2615
2616 BaseString::snprintf(buf, sizeof(buf), "%s-idx2", pTab0.getName());
2617 idx0.setName(buf);
2618 if (pDic->createIndex(idx0))
2619 {
2620 ndbout << pDic->getNdbError() << endl;
2621 return NDBT_FAILED;
2622 }
2623
2624 res.waitNodesNoStart(&node, 1);
2625 res.startNodes(&node, 1);
2626
2627 if (res.waitClusterStarted())
2628 {
2629 return NDBT_FAILED;
2630 }
2631
2632 if (pDic->dropTable(pTab0.getName()))
2633 {
2634 ndbout << pDic->getNdbError() << endl;
2635 return NDBT_FAILED;
2636 }
2637
2638 return NDBT_OK;
2639 }
2640
2641 static
2642 int
create_tablespace(NdbDictionary::Dictionary * pDict,const char * lgname,const char * tsname,const char * dfname)2643 create_tablespace(NdbDictionary::Dictionary* pDict,
2644 const char * lgname,
2645 const char * tsname,
2646 const char * dfname)
2647 {
2648 NdbDictionary::Tablespace ts;
2649 ts.setName(tsname);
2650 ts.setExtentSize(1024*1024);
2651 ts.setDefaultLogfileGroup(lgname);
2652
2653 if(pDict->createTablespace(ts) != 0)
2654 {
2655 g_err << "Failed to create tablespace:"
2656 << endl << pDict->getNdbError() << endl;
2657 return NDBT_FAILED;
2658 }
2659
2660 NdbDictionary::Datafile df;
2661 df.setPath(dfname);
2662 df.setSize(1*1024*1024);
2663 df.setTablespace(tsname);
2664
2665 if(pDict->createDatafile(df) != 0)
2666 {
2667 g_err << "Failed to create datafile:"
2668 << endl << pDict->getNdbError() << endl;
2669 return NDBT_FAILED;
2670 }
2671 return 0;
2672 }
2673
2674 int
runBug24631(NDBT_Context * ctx,NDBT_Step * step)2675 runBug24631(NDBT_Context* ctx, NDBT_Step* step)
2676 {
2677 char tsname[256];
2678 char dfname[256];
2679 char lgname[256];
2680 char ufname[256];
2681 NdbRestarter res;
2682
2683 if (res.getNumDbNodes() < 2)
2684 return NDBT_OK;
2685
2686 Ndb* pNdb = GETNDB(step);
2687 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
2688
2689 NdbDictionary::Dictionary::List list;
2690 if (pDict->listObjects(list) == -1)
2691 return NDBT_FAILED;
2692
2693 const char * lgfound = 0;
2694
2695 for (Uint32 i = 0; i<list.count; i++)
2696 {
2697 switch(list.elements[i].type){
2698 case NdbDictionary::Object::LogfileGroup:
2699 lgfound = list.elements[i].name;
2700 break;
2701 default:
2702 break;
2703 }
2704 if (lgfound)
2705 break;
2706 }
2707
2708 if (lgfound == 0)
2709 {
2710 BaseString::snprintf(lgname, sizeof(lgname), "LG-%u", rand());
2711 NdbDictionary::LogfileGroup lg;
2712
2713 lg.setName(lgname);
2714 lg.setUndoBufferSize(8*1024*1024);
2715 if(pDict->createLogfileGroup(lg) != 0)
2716 {
2717 g_err << "Failed to create logfilegroup:"
2718 << endl << pDict->getNdbError() << endl;
2719 return NDBT_FAILED;
2720 }
2721
2722 NdbDictionary::Undofile uf;
2723 BaseString::snprintf(ufname, sizeof(ufname), "%s-%u", lgname, rand());
2724 uf.setPath(ufname);
2725 uf.setSize(2*1024*1024);
2726 uf.setLogfileGroup(lgname);
2727
2728 if(pDict->createUndofile(uf) != 0)
2729 {
2730 g_err << "Failed to create undofile:"
2731 << endl << pDict->getNdbError() << endl;
2732 return NDBT_FAILED;
2733 }
2734 }
2735 else
2736 {
2737 BaseString::snprintf(lgname, sizeof(lgname), "%s", lgfound);
2738 }
2739
2740 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
2741 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u.dat", tsname, rand());
2742
2743 if (create_tablespace(pDict, lgname, tsname, dfname))
2744 return NDBT_FAILED;
2745
2746
2747 int node = res.getRandomNotMasterNodeId(rand());
2748 res.restartOneDbNode(node, false, true, true);
2749 NdbSleep_SecSleep(3);
2750
2751 if (pDict->dropDatafile(pDict->getDatafile(0, dfname)) != 0)
2752 {
2753 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
2754 return NDBT_FAILED;
2755 }
2756
2757 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
2758 {
2759 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
2760 return NDBT_FAILED;
2761 }
2762
2763 if (res.waitNodesNoStart(&node, 1))
2764 return NDBT_FAILED;
2765
2766 res.startNodes(&node, 1);
2767 if (res.waitClusterStarted())
2768 return NDBT_FAILED;
2769
2770 if (create_tablespace(pDict, lgname, tsname, dfname))
2771 return NDBT_FAILED;
2772
2773 if (pDict->dropDatafile(pDict->getDatafile(0, dfname)) != 0)
2774 {
2775 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
2776 return NDBT_FAILED;
2777 }
2778
2779 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
2780 {
2781 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
2782 return NDBT_FAILED;
2783 }
2784
2785 if (lgfound == 0)
2786 {
2787 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgname)) != 0)
2788 return NDBT_FAILED;
2789 }
2790
2791 return NDBT_OK;
2792 }
2793
2794 int
runBug29186(NDBT_Context * ctx,NDBT_Step * step)2795 runBug29186(NDBT_Context* ctx, NDBT_Step* step)
2796 {
2797 int lgError = 15000;
2798 int tsError = 16000;
2799 char lgname[256];
2800 char ufname[256];
2801 char tsname[256];
2802 char dfname[256];
2803
2804 NdbRestarter restarter;
2805
2806 if (restarter.getNumDbNodes() < 2){
2807 ctx->stopTest();
2808 return NDBT_OK;
2809 }
2810
2811 Ndb* pNdb = GETNDB(step);
2812 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
2813 NdbDictionary::Dictionary::List list;
2814
2815 if (pDict->listObjects(list) == -1)
2816 return NDBT_FAILED;
2817
2818 // 1.create logfile group
2819 const char * lgfound = 0;
2820
2821 for (Uint32 i = 0; i<list.count; i++)
2822 {
2823 switch(list.elements[i].type){
2824 case NdbDictionary::Object::LogfileGroup:
2825 lgfound = list.elements[i].name;
2826 break;
2827 default:
2828 break;
2829 }
2830 if (lgfound)
2831 break;
2832 }
2833
2834 if (lgfound == 0)
2835 {
2836 BaseString::snprintf(lgname, sizeof(lgname), "LG-%u", rand());
2837 NdbDictionary::LogfileGroup lg;
2838
2839 lg.setName(lgname);
2840 lg.setUndoBufferSize(8*1024*1024);
2841 if(pDict->createLogfileGroup(lg) != 0)
2842 {
2843 g_err << "Failed to create logfilegroup:"
2844 << endl << pDict->getNdbError() << endl;
2845 return NDBT_FAILED;
2846 }
2847 }
2848 else
2849 {
2850 BaseString::snprintf(lgname, sizeof(lgname), "%s", lgfound);
2851 }
2852
2853 if(restarter.waitClusterStarted(60)){
2854 g_err << "waitClusterStarted failed"<< endl;
2855 return NDBT_FAILED;
2856 }
2857
2858 if(restarter.insertErrorInAllNodes(lgError) != 0){
2859 g_err << "failed to set error insert"<< endl;
2860 return NDBT_FAILED;
2861 }
2862
2863 g_info << "error inserted" << endl;
2864 g_info << "waiting some before add log file" << endl;
2865 g_info << "starting create log file group" << endl;
2866
2867 NdbDictionary::Undofile uf;
2868 BaseString::snprintf(ufname, sizeof(ufname), "%s-%u", lgname, rand());
2869 uf.setPath(ufname);
2870 uf.setSize(2*1024*1024);
2871 uf.setLogfileGroup(lgname);
2872
2873 if(pDict->createUndofile(uf) == 0)
2874 {
2875 g_err << "Create log file group should fail on error_insertion " << lgError << endl;
2876 return NDBT_FAILED;
2877 }
2878
2879 //clear lg error
2880 if(restarter.insertErrorInAllNodes(15099) != 0){
2881 g_err << "failed to set error insert"<< endl;
2882 return NDBT_FAILED;
2883 }
2884 NdbSleep_SecSleep(5);
2885
2886 //lg error has been cleared, so we can add undo file
2887 if(pDict->createUndofile(uf) != 0)
2888 {
2889 g_err << "Failed to create undofile:"
2890 << endl << pDict->getNdbError() << endl;
2891 return NDBT_FAILED;
2892 }
2893
2894 if(restarter.waitClusterStarted(60)){
2895 g_err << "waitClusterStarted failed"<< endl;
2896 return NDBT_FAILED;
2897 }
2898
2899 if(restarter.insertErrorInAllNodes(tsError) != 0){
2900 g_err << "failed to set error insert"<< endl;
2901 return NDBT_FAILED;
2902 }
2903 g_info << "error inserted" << endl;
2904 g_info << "waiting some before create table space" << endl;
2905 g_info << "starting create table space" << endl;
2906
2907 //r = runCreateTablespace(ctx, step);
2908 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
2909 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u-1.dat", tsname, rand());
2910
2911 NdbDictionary::Tablespace ts;
2912 ts.setName(tsname);
2913 ts.setExtentSize(1024*1024);
2914 ts.setDefaultLogfileGroup(lgname);
2915
2916 if(pDict->createTablespace(ts) != 0)
2917 {
2918 g_err << "Failed to create tablespace:"
2919 << endl << pDict->getNdbError() << endl;
2920 return NDBT_FAILED;
2921 }
2922
2923 NdbDictionary::Datafile df;
2924 df.setPath(dfname);
2925 df.setSize(1*1024*1024);
2926 df.setTablespace(tsname);
2927
2928 if(pDict->createDatafile(df) == 0)
2929 {
2930 g_err << "Create table space should fail on error_insertion " << tsError << endl;
2931 return NDBT_FAILED;
2932 }
2933 //Clear the inserted error
2934 if(restarter.insertErrorInAllNodes(16099) != 0){
2935 g_err << "failed to set error insert"<< endl;
2936 return NDBT_FAILED;
2937 }
2938 NdbSleep_SecSleep(5);
2939
2940 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
2941 {
2942 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
2943 return NDBT_FAILED;
2944 }
2945
2946 if (lgfound == 0)
2947 {
2948 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgname)) != 0)
2949 return NDBT_FAILED;
2950 }
2951
2952 return NDBT_OK;
2953 }
2954
2955 struct RandSchemaOp
2956 {
RandSchemaOpRandSchemaOp2957 RandSchemaOp(unsigned * randseed = 0) {
2958 if (randseed == 0)
2959 {
2960 ownseed = (unsigned)NdbTick_CurrentMillisecond();
2961 seed = &ownseed;
2962 }
2963 else
2964 {
2965 seed = randseed;
2966 }
2967 }
2968 struct Obj
2969 {
2970 BaseString m_name;
2971 Uint32 m_type;
2972 struct Obj* m_parent;
2973 Vector<Obj*> m_dependant;
2974 };
2975
2976 Vector<Obj*> m_objects;
2977
2978 int schema_op(Ndb*);
2979 int validate(Ndb*);
2980 int cleanup(Ndb*);
2981
2982 Obj* get_obj(Uint32 mask);
2983 int create_table(Ndb*);
2984 int create_index(Ndb*, Obj*);
2985 int alter_table(Ndb*, Obj*);
2986 int drop_obj(Ndb*, Obj*);
2987
2988 void remove_obj(Obj*);
2989 private:
2990 unsigned * seed;
2991 unsigned ownseed;
2992 };
2993
2994 template class Vector<RandSchemaOp::Obj*>;
2995
2996 int
schema_op(Ndb * ndb)2997 RandSchemaOp::schema_op(Ndb* ndb)
2998 {
2999 struct Obj* obj = 0;
3000 Uint32 type = 0;
3001 loop:
3002 switch(ndb_rand_r(seed) % 5){
3003 case 0:
3004 return create_table(ndb);
3005 case 1:
3006 if ((obj = get_obj(1 << NdbDictionary::Object::UserTable)) == 0)
3007 goto loop;
3008 return create_index(ndb, obj);
3009 case 2:
3010 type = (1 << NdbDictionary::Object::UserTable);
3011 goto drop_object;
3012 case 3:
3013 type =
3014 (1 << NdbDictionary::Object::UniqueHashIndex) |
3015 (1 << NdbDictionary::Object::OrderedIndex);
3016 goto drop_object;
3017 case 4:
3018 if ((obj = get_obj(1 << NdbDictionary::Object::UserTable)) == 0)
3019 goto loop;
3020 return alter_table(ndb, obj);
3021 default:
3022 goto loop;
3023 }
3024
3025 drop_object:
3026 if ((obj = get_obj(type)) == 0)
3027 goto loop;
3028 return drop_obj(ndb, obj);
3029 }
3030
3031 RandSchemaOp::Obj*
get_obj(Uint32 mask)3032 RandSchemaOp::get_obj(Uint32 mask)
3033 {
3034 Vector<Obj*> tmp;
3035 for (Uint32 i = 0; i<m_objects.size(); i++)
3036 {
3037 if ((1 << m_objects[i]->m_type) & mask)
3038 tmp.push_back(m_objects[i]);
3039 }
3040
3041 if (tmp.size())
3042 {
3043 return tmp[ndb_rand_r(seed)%tmp.size()];
3044 }
3045 return 0;
3046 }
3047
3048 int
create_table(Ndb * ndb)3049 RandSchemaOp::create_table(Ndb* ndb)
3050 {
3051 int numTables = NDBT_Tables::getNumTables();
3052 int num = ndb_rand_r(seed) % numTables;
3053 NdbDictionary::Table pTab = * NDBT_Tables::getTable(num);
3054
3055 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3056 pTab.setForceVarPart(true);
3057
3058 if (pDict->getTable(pTab.getName()))
3059 {
3060 char buf[100];
3061 BaseString::snprintf(buf, sizeof(buf), "%s-%d",
3062 pTab.getName(), ndb_rand_r(seed));
3063 pTab.setName(buf);
3064 if (pDict->createTable(pTab))
3065 return NDBT_FAILED;
3066 }
3067 else
3068 {
3069 if (NDBT_Tables::createTable(ndb, pTab.getName()))
3070 {
3071 return NDBT_FAILED;
3072 }
3073 }
3074
3075 ndbout_c("create table %s", pTab.getName());
3076 const NdbDictionary::Table* tab2 = pDict->getTable(pTab.getName());
3077 HugoTransactions trans(*tab2);
3078 trans.loadTable(ndb, 1000);
3079
3080 Obj *obj = new Obj;
3081 obj->m_name.assign(pTab.getName());
3082 obj->m_type = NdbDictionary::Object::UserTable;
3083 obj->m_parent = 0;
3084 m_objects.push_back(obj);
3085
3086 return NDBT_OK;
3087 }
3088
3089 int
create_index(Ndb * ndb,Obj * tab)3090 RandSchemaOp::create_index(Ndb* ndb, Obj* tab)
3091 {
3092 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3093 const NdbDictionary::Table * pTab = pDict->getTable(tab->m_name.c_str());
3094
3095 if (pTab == 0)
3096 {
3097 return NDBT_FAILED;
3098 }
3099
3100 bool ordered = ndb_rand_r(seed) & 1;
3101 bool stored = ndb_rand_r(seed) & 1;
3102
3103 Uint32 type = ordered ?
3104 NdbDictionary::Index::OrderedIndex :
3105 NdbDictionary::Index::UniqueHashIndex;
3106
3107 char buf[255];
3108 BaseString::snprintf(buf, sizeof(buf), "%s-%s",
3109 pTab->getName(),
3110 ordered ? "OI" : "UI");
3111
3112 if (pDict->getIndex(buf, pTab->getName()))
3113 {
3114 // Index exists...let it be ok
3115 return NDBT_OK;
3116 }
3117
3118 ndbout_c("create index %s", buf);
3119 NdbDictionary::Index idx0;
3120 idx0.setName(buf);
3121 idx0.setType((NdbDictionary::Index::Type)type);
3122 idx0.setTable(pTab->getName());
3123 idx0.setStoredIndex(ordered ? false : stored);
3124
3125 for (Uint32 i = 0; i<(Uint32)pTab->getNoOfColumns(); i++)
3126 {
3127 if (pTab->getColumn(i)->getPrimaryKey())
3128 idx0.addColumn(pTab->getColumn(i)->getName());
3129 }
3130 if (pDict->createIndex(idx0))
3131 {
3132 ndbout << pDict->getNdbError() << endl;
3133 return NDBT_FAILED;
3134 }
3135 Obj *obj = new Obj;
3136 obj->m_name.assign(buf);
3137 obj->m_type = type;
3138 obj->m_parent = tab;
3139 m_objects.push_back(obj);
3140
3141 tab->m_dependant.push_back(obj);
3142 return NDBT_OK;
3143 }
3144
3145 int
drop_obj(Ndb * ndb,Obj * obj)3146 RandSchemaOp::drop_obj(Ndb* ndb, Obj* obj)
3147 {
3148 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3149
3150 if (obj->m_type == NdbDictionary::Object::UserTable)
3151 {
3152 ndbout_c("drop table %s", obj->m_name.c_str());
3153 /**
3154 * Drop of table automatically drops all indexes
3155 */
3156 if (pDict->dropTable(obj->m_name.c_str()))
3157 {
3158 return NDBT_FAILED;
3159 }
3160 while(obj->m_dependant.size())
3161 {
3162 remove_obj(obj->m_dependant[0]);
3163 }
3164 remove_obj(obj);
3165 }
3166 else if (obj->m_type == NdbDictionary::Object::UniqueHashIndex ||
3167 obj->m_type == NdbDictionary::Object::OrderedIndex)
3168 {
3169 ndbout_c("drop index %s", obj->m_name.c_str());
3170 if (pDict->dropIndex(obj->m_name.c_str(),
3171 obj->m_parent->m_name.c_str()))
3172 {
3173 return NDBT_FAILED;
3174 }
3175 remove_obj(obj);
3176 }
3177 return NDBT_OK;
3178 }
3179
3180 void
remove_obj(Obj * obj)3181 RandSchemaOp::remove_obj(Obj* obj)
3182 {
3183 Uint32 i;
3184 if (obj->m_parent)
3185 {
3186 bool found = false;
3187 for (i = 0; i<obj->m_parent->m_dependant.size(); i++)
3188 {
3189 if (obj->m_parent->m_dependant[i] == obj)
3190 {
3191 found = true;
3192 obj->m_parent->m_dependant.erase(i);
3193 break;
3194 }
3195 }
3196 assert(found);
3197 }
3198
3199 {
3200 bool found = false;
3201 for (i = 0; i<m_objects.size(); i++)
3202 {
3203 if (m_objects[i] == obj)
3204 {
3205 found = true;
3206 m_objects.erase(i);
3207 break;
3208 }
3209 }
3210 assert(found);
3211 }
3212 delete obj;
3213 }
3214
3215 int
alter_table(Ndb * ndb,Obj * obj)3216 RandSchemaOp::alter_table(Ndb* ndb, Obj* obj)
3217 {
3218 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3219 const NdbDictionary::Table * pOld = pDict->getTable(obj->m_name.c_str());
3220 NdbDictionary::Table tNew = * pOld;
3221
3222 BaseString ops;
3223 unsigned mask = 3;
3224
3225 unsigned type;
3226 while (ops.length() == 0 && (mask != 0))
3227 {
3228 switch((type = (ndb_rand_r(seed) & 1))){
3229 default:
3230 case 0:{
3231 if ((mask & (1 << type)) == 0)
3232 break;
3233 BaseString name;
3234 name.assfmt("newcol_%d", tNew.getNoOfColumns());
3235 NdbDictionary::Column col(name.c_str());
3236 col.setType(NdbDictionary::Column::Unsigned);
3237 col.setDynamic(true);
3238 col.setPrimaryKey(false);
3239 col.setNullable(true);
3240 NdbDictionary::Table save = tNew;
3241 tNew.addColumn(col);
3242 if (!pDict->supportedAlterTable(* pOld, tNew))
3243 {
3244 ndbout_c("not supported...");
3245 mask &= ~(1 << type);
3246 tNew = save;
3247 break;
3248 }
3249 ops.append(" addcol");
3250 break;
3251 }
3252 case 1:{
3253 BaseString name;
3254 do
3255 {
3256 unsigned no = ndb_rand_r(seed);
3257 name.assfmt("%s_%u", pOld->getName(), no);
3258 } while (pDict->getTable(name.c_str()));
3259 tNew.setName(name.c_str());
3260 ops.appfmt(" rename: %s", name.c_str());
3261 break;
3262 }
3263
3264 }
3265 }
3266
3267 if (ops.length())
3268 {
3269 ndbout_c("altering %s ops: %s", pOld->getName(), ops.c_str());
3270 if (pDict->alterTable(*pOld, tNew) != 0)
3271 {
3272 g_err << pDict->getNdbError() << endl;
3273 return NDBT_FAILED;
3274 }
3275 pDict->invalidateTable(pOld->getName());
3276 if (strcmp(pOld->getName(), tNew.getName()))
3277 {
3278 obj->m_name.assign(tNew.getName());
3279 }
3280 }
3281
3282 return NDBT_OK;
3283 }
3284
3285
3286 int
validate(Ndb * ndb)3287 RandSchemaOp::validate(Ndb* ndb)
3288 {
3289 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3290 for (Uint32 i = 0; i<m_objects.size(); i++)
3291 {
3292 if (m_objects[i]->m_type == NdbDictionary::Object::UserTable)
3293 {
3294 const NdbDictionary::Table* tab2 =
3295 pDict->getTable(m_objects[i]->m_name.c_str());
3296 HugoTransactions trans(*tab2);
3297 trans.scanUpdateRecords(ndb, 1000);
3298 trans.clearTable(ndb);
3299 trans.loadTable(ndb, 1000);
3300 }
3301 }
3302
3303 return NDBT_OK;
3304 }
3305
3306 /*
3307 SystemTable = 1, ///< System table
3308 UserTable = 2, ///< User table (may be temporary)
3309 UniqueHashIndex = 3, ///< Unique un-ordered hash index
3310 OrderedIndex = 6, ///< Non-unique ordered index
3311 HashIndexTrigger = 7, ///< Index maintenance, internal
3312 IndexTrigger = 8, ///< Index maintenance, internal
3313 SubscriptionTrigger = 9,///< Backup or replication, internal
3314 ReadOnlyConstraint = 10,///< Trigger, internal
3315 Tablespace = 20, ///< Tablespace
3316 LogfileGroup = 21, ///< Logfile group
3317 Datafile = 22, ///< Datafile
3318 Undofile = 23 ///< Undofile
3319 */
3320
3321 int
cleanup(Ndb * ndb)3322 RandSchemaOp::cleanup(Ndb* ndb)
3323 {
3324 Int32 i;
3325 for (i = m_objects.size() - 1; i >= 0; i--)
3326 {
3327 switch(m_objects[i]->m_type){
3328 case NdbDictionary::Object::UniqueHashIndex:
3329 case NdbDictionary::Object::OrderedIndex:
3330 if (drop_obj(ndb, m_objects[i]))
3331 return NDBT_FAILED;
3332
3333 break;
3334 default:
3335 break;
3336 }
3337 }
3338
3339 for (i = m_objects.size() - 1; i >= 0; i--)
3340 {
3341 switch(m_objects[i]->m_type){
3342 case NdbDictionary::Object::UserTable:
3343 if (drop_obj(ndb, m_objects[i]))
3344 return NDBT_FAILED;
3345 break;
3346 default:
3347 break;
3348 }
3349 }
3350
3351 assert(m_objects.size() == 0);
3352 return NDBT_OK;
3353 }
3354
3355 extern unsigned opt_seed;
3356
3357 int
runDictRestart(NDBT_Context * ctx,NDBT_Step * step)3358 runDictRestart(NDBT_Context* ctx, NDBT_Step* step)
3359 {
3360 Ndb* pNdb = GETNDB(step);
3361 int loops = ctx->getNumLoops();
3362
3363 unsigned seed = opt_seed;
3364 NdbMixRestarter res(&seed);
3365 RandSchemaOp dict(&seed);
3366 if (res.getNumDbNodes() < 2)
3367 return NDBT_OK;
3368
3369 if (res.init(ctx, step))
3370 return NDBT_FAILED;
3371
3372 for (int i = 0; i<loops; i++)
3373 {
3374 for (Uint32 j = 0; j<10; j++)
3375 if (dict.schema_op(pNdb))
3376 return NDBT_FAILED;
3377
3378 if (res.dostep(ctx, step))
3379 return NDBT_FAILED;
3380
3381 if (dict.validate(pNdb))
3382 return NDBT_FAILED;
3383 }
3384
3385 if (res.finish(ctx, step))
3386 return NDBT_FAILED;
3387
3388 if (dict.validate(pNdb))
3389 return NDBT_FAILED;
3390
3391 if (dict.cleanup(pNdb))
3392 return NDBT_FAILED;
3393
3394 return NDBT_OK;
3395 }
3396
3397 int
runBug29501(NDBT_Context * ctx,NDBT_Step * step)3398 runBug29501(NDBT_Context* ctx, NDBT_Step* step) {
3399 NdbRestarter res;
3400 NdbDictionary::LogfileGroup lg;
3401 lg.setName("DEFAULT-LG");
3402 lg.setUndoBufferSize(8*1024*1024);
3403
3404 if (res.getNumDbNodes() < 2)
3405 return NDBT_OK;
3406
3407 Ndb* pNdb = GETNDB(step);
3408 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3409
3410 int node = res.getRandomNotMasterNodeId(rand());
3411 res.restartOneDbNode(node, true, true, false);
3412
3413 if(pDict->createLogfileGroup(lg) != 0){
3414 g_err << "Failed to create logfilegroup:"
3415 << endl << pDict->getNdbError() << endl;
3416 return NDBT_FAILED;
3417 }
3418
3419 NdbDictionary::Undofile uf;
3420 uf.setPath("undofile01.dat");
3421 uf.setSize(5*1024*1024);
3422 uf.setLogfileGroup("DEFAULT-LG");
3423
3424 if(pDict->createUndofile(uf) != 0){
3425 g_err << "Failed to create undofile:"
3426 << endl << pDict->getNdbError() << endl;
3427 return NDBT_FAILED;
3428 }
3429
3430 res.waitNodesNoStart(&node, 1);
3431 res.startNodes(&node, 1);
3432
3433 if (res.waitClusterStarted()){
3434 g_err << "Node restart failed"
3435 << endl << pDict->getNdbError() << endl;
3436 return NDBT_FAILED;
3437 }
3438
3439 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lg.getName())) != 0){
3440 g_err << "Drop of LFG Failed"
3441 << endl << pDict->getNdbError() << endl;
3442 return NDBT_FAILED;
3443 }
3444
3445 return NDBT_OK;
3446 }
3447
3448 int
runDropDDObjects(NDBT_Context * ctx,NDBT_Step * step)3449 runDropDDObjects(NDBT_Context* ctx, NDBT_Step* step){
3450 //Purpose is to drop all tables, data files, Table spaces and LFG's
3451 Uint32 i = 0;
3452
3453 Ndb* pNdb = GETNDB(step);
3454 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3455
3456 NdbDictionary::Dictionary::List list;
3457 if (pDict->listObjects(list) == -1)
3458 return NDBT_FAILED;
3459
3460 //Search the list and drop all tables found
3461 const char * tableFound = 0;
3462 for (i = 0; i < list.count; i++){
3463 switch(list.elements[i].type){
3464 case NdbDictionary::Object::UserTable:
3465 tableFound = list.elements[i].name;
3466 if(tableFound != 0){
3467 if(strcmp(list.elements[i].database, "TEST_DB") == 0 &&
3468 !is_prefix(tableFound, "NDB$BLOB"))
3469 {
3470 if(pDict->dropTable(tableFound) != 0){
3471 g_err << "Failed to drop table: " << tableFound << pDict->getNdbError() << endl;
3472 return NDBT_FAILED;
3473 }
3474 }
3475 }
3476 tableFound = 0;
3477 break;
3478 default:
3479 break;
3480 }
3481 }
3482
3483 //Search the list and drop all data file found
3484 const char * dfFound = 0;
3485 for (i = 0; i < list.count; i++){
3486 switch(list.elements[i].type){
3487 case NdbDictionary::Object::Datafile:
3488 dfFound = list.elements[i].name;
3489 if(dfFound != 0){
3490 if(pDict->dropDatafile(pDict->getDatafile(0, dfFound)) != 0){
3491 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
3492 return NDBT_FAILED;
3493 }
3494 }
3495 dfFound = 0;
3496 break;
3497 default:
3498 break;
3499 }
3500 }
3501
3502 //Search the list and drop all Table Spaces Found
3503 const char * tsFound = 0;
3504 for (i = 0; i <list.count; i++){
3505 switch(list.elements[i].type){
3506 case NdbDictionary::Object::Tablespace:
3507 tsFound = list.elements[i].name;
3508 if(tsFound != 0){
3509 if(pDict->dropTablespace(pDict->getTablespace(tsFound)) != 0){
3510 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3511 return NDBT_FAILED;
3512 }
3513 }
3514 tsFound = 0;
3515 break;
3516 default:
3517 break;
3518 }
3519 }
3520
3521 //Search the list and drop all LFG Found
3522 //Currently only 1 LGF is supported, but written for future
3523 //when more then one is supported.
3524 const char * lgFound = 0;
3525 for (i = 0; i < list.count; i++){
3526 switch(list.elements[i].type){
3527 case NdbDictionary::Object::LogfileGroup:
3528 lgFound = list.elements[i].name;
3529 if(lgFound != 0){
3530 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgFound)) != 0){
3531 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3532 return NDBT_FAILED;
3533 }
3534 }
3535 lgFound = 0;
3536 break;
3537 default:
3538 break;
3539 }
3540 }
3541
3542 return NDBT_OK;
3543 }
3544
3545 int
runWaitStarted(NDBT_Context * ctx,NDBT_Step * step)3546 runWaitStarted(NDBT_Context* ctx, NDBT_Step* step){
3547
3548 NdbRestarter restarter;
3549 restarter.waitClusterStarted(300);
3550
3551 NdbSleep_SecSleep(3);
3552 return NDBT_OK;
3553 }
3554
3555 int
testDropDDObjectsSetup(NDBT_Context * ctx,NDBT_Step * step)3556 testDropDDObjectsSetup(NDBT_Context* ctx, NDBT_Step* step){
3557 //Purpose is to setup to test DropDDObjects
3558 char tsname[256];
3559 char dfname[256];
3560
3561 Ndb* pNdb = GETNDB(step);
3562 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3563
3564 NdbDictionary::LogfileGroup lg;
3565 lg.setName("DEFAULT-LG");
3566 lg.setUndoBufferSize(8*1024*1024);
3567
3568
3569 if(pDict->createLogfileGroup(lg) != 0){
3570 g_err << "Failed to create logfilegroup:"
3571 << endl << pDict->getNdbError() << endl;
3572 return NDBT_FAILED;
3573 }
3574
3575 NdbDictionary::Undofile uf;
3576 uf.setPath("undofile01.dat");
3577 uf.setSize(5*1024*1024);
3578 uf.setLogfileGroup("DEFAULT-LG");
3579
3580 if(pDict->createUndofile(uf) != 0){
3581 g_err << "Failed to create undofile:"
3582 << endl << pDict->getNdbError() << endl;
3583 return NDBT_FAILED;
3584 }
3585
3586 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
3587 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u.dat", tsname, rand());
3588
3589 if (create_tablespace(pDict, lg.getName(), tsname, dfname)){
3590 g_err << "Failed to create undofile:"
3591 << endl << pDict->getNdbError() << endl;
3592 return NDBT_FAILED;
3593 }
3594
3595 return NDBT_OK;
3596 }
3597
3598 int
runBug36072(NDBT_Context * ctx,NDBT_Step * step)3599 runBug36072(NDBT_Context* ctx, NDBT_Step* step)
3600 {
3601 Ndb* pNdb = GETNDB(step);
3602 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3603 NdbRestarter res;
3604
3605 int err[] = { 6016,
3606 #if BUG_46856
3607 6017,
3608 #endif
3609 0 };
3610 for (Uint32 i = 0; err[i] != 0; i++)
3611 {
3612 int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
3613
3614 if (res.dumpStateAllNodes(val2, 2))
3615 return NDBT_FAILED;
3616
3617 if (res.insertErrorInAllNodes(932)) // arbit
3618 return NDBT_FAILED;
3619
3620 int code = err[i];
3621
3622 if (code == 6016)
3623 {
3624 if (res.insertErrorInAllNodes(code))
3625 return NDBT_FAILED;
3626 }
3627
3628 NdbDictionary::LogfileGroup lg;
3629 lg.setName("DEFAULT-LG");
3630 lg.setUndoBufferSize(8*1024*1024);
3631
3632 NdbDictionary::Undofile uf;
3633 uf.setPath("undofile01.dat");
3634 uf.setSize(5*1024*1024);
3635 uf.setLogfileGroup("DEFAULT-LG");
3636
3637 int r = pDict->createLogfileGroup(lg);
3638 if (code == 6017)
3639 {
3640 if (r)
3641 {
3642 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3643 return NDBT_FAILED;
3644 }
3645
3646 if (res.insertErrorInAllNodes(err[i]))
3647 return NDBT_FAILED;
3648
3649 pDict->createUndofile(uf);
3650 }
3651
3652 if (res.waitClusterNoStart())
3653 return NDBT_FAILED;
3654
3655 res.startAll();
3656 if (res.waitClusterStarted())
3657 return NDBT_FAILED;
3658
3659 if (code == 6016)
3660 {
3661 NdbDictionary::LogfileGroup lg2 = pDict->getLogfileGroup("DEFAULT-LG");
3662 NdbError err= pDict->getNdbError();
3663 if( (int) err.classification == (int) ndberror_cl_none)
3664 {
3665 ndbout << __LINE__ << endl;
3666 return NDBT_FAILED;
3667 }
3668
3669 if (pDict->createLogfileGroup(lg) != 0)
3670 {
3671 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3672 return NDBT_FAILED;
3673 }
3674 }
3675 else
3676 {
3677 NdbDictionary::Undofile uf2 = pDict->getUndofile(0, "undofile01.dat");
3678 NdbError err= pDict->getNdbError();
3679 if( (int) err.classification == (int) ndberror_cl_none)
3680 {
3681 ndbout << __LINE__ << endl;
3682 return NDBT_FAILED;
3683 }
3684
3685 if (pDict->createUndofile(uf) != 0)
3686 {
3687 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3688 return NDBT_FAILED;
3689 }
3690 }
3691
3692 {
3693 NdbDictionary::LogfileGroup lg2 = pDict->getLogfileGroup("DEFAULT-LG");
3694 NdbError err= pDict->getNdbError();
3695 if( (int) err.classification != (int) ndberror_cl_none)
3696 {
3697 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3698 return NDBT_FAILED;
3699 }
3700
3701 if (pDict->dropLogfileGroup(lg2))
3702 {
3703 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3704 return NDBT_FAILED;
3705 }
3706 }
3707 }
3708
3709 return NDBT_OK;
3710 }
3711
3712 int
restartClusterInitial(NDBT_Context * ctx,NDBT_Step * step)3713 restartClusterInitial(NDBT_Context* ctx, NDBT_Step* step)
3714 {
3715 NdbRestarter res;
3716
3717 res.restartAll2(NdbRestarter::NRRF_INITIAL |
3718 NdbRestarter::NRRF_NOSTART |
3719 NdbRestarter::NRRF_ABORT);
3720 if (res.waitClusterNoStart())
3721 return NDBT_FAILED;
3722
3723 res.startAll();
3724 if (res.waitClusterStarted())
3725 return NDBT_FAILED;
3726
3727 return NDBT_OK;
3728 }
3729
3730
3731 int
DropDDObjectsVerify(NDBT_Context * ctx,NDBT_Step * step)3732 DropDDObjectsVerify(NDBT_Context* ctx, NDBT_Step* step){
3733 //Purpose is to verify test DropDDObjects worked
3734 Uint32 i = 0;
3735
3736 Ndb* pNdb = GETNDB(step);
3737 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3738
3739 NdbDictionary::Dictionary::List list;
3740 if (pDict->listObjects(list) == -1)
3741 return NDBT_FAILED;
3742
3743 bool ddFound = false;
3744 for (i = 0; i <list.count; i++){
3745 switch(list.elements[i].type){
3746 case NdbDictionary::Object::Tablespace:
3747 ddFound = true;
3748 break;
3749 case NdbDictionary::Object::LogfileGroup:
3750 ddFound = true;
3751 break;
3752 default:
3753 break;
3754 }
3755 if(ddFound == true){
3756 g_err << "DropDDObjects Failed: DD found:"
3757 << endl;
3758 return NDBT_FAILED;
3759 }
3760 }
3761 return NDBT_OK;
3762 }
3763
3764 // Bug48604
3765
3766 // string messages between local/remote steps identified by stepNo-1
3767 // each Msg<loc><rem> waits for Ack<loc><rem>
3768
3769 static const uint MaxMsg = 100;
3770
3771 static bool
send_msg(NDBT_Context * ctx,int loc,int rem,const char * msg)3772 send_msg(NDBT_Context* ctx, int loc, int rem, const char* msg)
3773 {
3774 char msgName[20], ackName[20];
3775 sprintf(msgName, "Msg%d%d", loc, rem);
3776 sprintf(ackName, "Ack%d%d", loc, rem);
3777 g_info << loc << ": send to:" << rem << " msg:" << msg << endl;
3778 ctx->setProperty(msgName, msg);
3779 int cnt = 0;
3780 while (1)
3781 {
3782 if (ctx->isTestStopped())
3783 return false;
3784 int ret;
3785 if ((ret = ctx->getProperty(ackName, (Uint32)0)) != 0)
3786 break;
3787 if (++cnt % 100 == 0)
3788 g_info << loc << ": send to:" << rem << " wait for ack" << endl;
3789 NdbSleep_MilliSleep(10);
3790 }
3791 ctx->setProperty(ackName, (Uint32)0);
3792 return true;
3793 }
3794
3795 static bool
poll_msg(NDBT_Context * ctx,int loc,int rem,char * msg)3796 poll_msg(NDBT_Context* ctx, int loc, int rem, char* msg)
3797 {
3798 char msgName[20], ackName[20];
3799 sprintf(msgName, "Msg%d%d", rem, loc);
3800 sprintf(ackName, "Ack%d%d", rem, loc);
3801 const char* ptr;
3802 if ((ptr = ctx->getProperty(msgName, (char*)0)) != 0 && ptr[0] != 0)
3803 {
3804 assert(strlen(ptr) < MaxMsg);
3805 memset(msg, 0, MaxMsg);
3806 strcpy(msg, ptr);
3807 g_info << loc << ": recv from:" << rem << " msg:" << msg << endl;
3808 ctx->setProperty(msgName, "");
3809 ctx->setProperty(ackName, (Uint32)1);
3810 return true;
3811 }
3812 return false;
3813 }
3814
3815 static int
recv_msg(NDBT_Context * ctx,int loc,int rem,char * msg)3816 recv_msg(NDBT_Context* ctx, int loc, int rem, char* msg)
3817 {
3818 uint cnt = 0;
3819 while (1)
3820 {
3821 if (ctx->isTestStopped())
3822 return false;
3823 if (poll_msg(ctx, loc, rem, msg))
3824 break;
3825 if (++cnt % 100 == 0)
3826 g_info << loc << ": recv from:" << rem << " wait for msg" << endl;
3827 NdbSleep_MilliSleep(10);
3828 }
3829 return true;
3830 }
3831
3832 const char* tabName_Bug48604 = "TBug48604";
3833 const char* indName_Bug48604 = "TBug48604X1";
3834
3835 static const NdbDictionary::Table*
runBug48604createtable(NDBT_Context * ctx,NDBT_Step * step)3836 runBug48604createtable(NDBT_Context* ctx, NDBT_Step* step)
3837 {
3838 Ndb* pNdb = GETNDB(step);
3839 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
3840 const NdbDictionary::Table* pTab = 0;
3841 int result = NDBT_OK;
3842 do
3843 {
3844 NdbDictionary::Table tab(tabName_Bug48604);
3845 {
3846 NdbDictionary::Column col("a");
3847 col.setType(NdbDictionary::Column::Unsigned);
3848 col.setPrimaryKey(true);
3849 tab.addColumn(col);
3850 }
3851 {
3852 NdbDictionary::Column col("b");
3853 col.setType(NdbDictionary::Column::Unsigned);
3854 col.setNullable(false);
3855 tab.addColumn(col);
3856 }
3857 CHECK(pDic->createTable(tab) == 0);
3858 CHECK((pTab = pDic->getTable(tabName_Bug48604)) != 0);
3859 }
3860 while (0);
3861 return pTab;
3862 }
3863
3864 static const NdbDictionary::Index*
runBug48604createindex(NDBT_Context * ctx,NDBT_Step * step)3865 runBug48604createindex(NDBT_Context* ctx, NDBT_Step* step)
3866 {
3867 Ndb* pNdb = GETNDB(step);
3868 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
3869 const NdbDictionary::Index* pInd = 0;
3870 int result = NDBT_OK;
3871 do {
3872 NdbDictionary::Index ind(indName_Bug48604);
3873 ind.setTable(tabName_Bug48604);
3874 ind.setType(NdbDictionary::Index::OrderedIndex);
3875 ind.setLogging(false);
3876 ind.addColumn("b");
3877 g_info << "index create.." << endl;
3878 CHECK(pDic->createIndex(ind) == 0);
3879 CHECK((pInd = pDic->getIndex(indName_Bug48604, tabName_Bug48604)) != 0);
3880 g_info << "index created" << endl;
3881 return pInd;
3882 }
3883 while (0);
3884 return pInd;
3885 }
3886
3887 int
runBug48604(NDBT_Context * ctx,NDBT_Step * step)3888 runBug48604(NDBT_Context* ctx, NDBT_Step* step)
3889 {
3890 Ndb* pNdb = GETNDB(step);
3891 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
3892 const NdbDictionary::Table* pTab = 0;
3893 const NdbDictionary::Index* pInd = 0;
3894 (void)pDic->dropTable(tabName_Bug48604);
3895 int loc = step->getStepNo() - 1;
3896 assert(loc == 0);
3897 g_err << "main" << endl;
3898 int result = NDBT_OK;
3899 int loops = ctx->getNumLoops();
3900 char msg[MaxMsg];
3901
3902 do
3903 {
3904 CHECK((pTab = runBug48604createtable(ctx, step)) != 0);
3905 CHECK(send_msg(ctx, 0, 1, "s"));
3906
3907 int loop = 0;
3908 while (result == NDBT_OK && loop++ < loops)
3909 {
3910 g_err << "loop:" << loop << endl;
3911 {
3912 // create index fully while uncommitted ops wait
3913 const char* ops[][3] =
3914 {
3915 { "ozin", "oc", "oa" }, // 0: before 1-2: after
3916 { "oziun", "oc", "oa" },
3917 { "ozidn", "oc", "oa" },
3918 { "ozicun", "oc", "oa" },
3919 { "ozicuuun", "oc", "oa" },
3920 { "ozicdn", "oc", "oa" },
3921 { "ozicdin", "oc", "oa" },
3922 { "ozicdidiuuudidn", "oc", "oa" },
3923 { "ozicdidiuuudidin", "oc", "oa" }
3924 };
3925 const int cnt = sizeof(ops)/sizeof(ops[0]);
3926 int i;
3927 for (i = 0; result == NDBT_OK && i < cnt; i++)
3928 {
3929 int j;
3930 for (j = 1; result == NDBT_OK && j <= 2; j++)
3931 {
3932 if (ops[i][j] == 0)
3933 continue;
3934 CHECK(send_msg(ctx, 0, 1, ops[i][0]));
3935 CHECK(recv_msg(ctx, 0, 1, msg) && msg[0] == 'o');
3936 CHECK((pInd = runBug48604createindex(ctx, step)) != 0);
3937 CHECK(send_msg(ctx, 0, 1, ops[i][j]));
3938 CHECK(recv_msg(ctx, 0, 1, msg) && msg[0] == 'o');
3939
3940 CHECK(pDic->dropIndex(indName_Bug48604, tabName_Bug48604) == 0);
3941 g_info << "index dropped" << endl;
3942 }
3943 }
3944 }
3945 }
3946 }
3947 while (0);
3948
3949 (void)send_msg(ctx, 0, 1, "x");
3950 ctx->stopTest();
3951 g_err << "main: exit:" << result << endl;
3952 return result;
3953 }
3954
3955 int
runBug48604ops(NDBT_Context * ctx,NDBT_Step * step)3956 runBug48604ops(NDBT_Context* ctx, NDBT_Step* step)
3957 {
3958 Ndb* pNdb = GETNDB(step);
3959 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
3960 const NdbDictionary::Table* pTab = 0;
3961 //const NdbDictionary::Index* pInd = 0;
3962 int loc = step->getStepNo() - 1;
3963 assert(loc > 0);
3964 g_err << "ops: loc:" << loc << endl;
3965 int result = NDBT_OK;
3966 int records = ctx->getNumRecords();
3967 char msg[MaxMsg];
3968
3969 do
3970 {
3971 CHECK(recv_msg(ctx, loc, 0, msg));
3972 assert(msg[0] == 's');
3973 CHECK((pTab = pDic->getTable(tabName_Bug48604)) != 0);
3974 HugoOperations ops(*pTab);
3975 bool have_trans = false;
3976 int opseq = 0;
3977
3978 while (result == NDBT_OK && !ctx->isTestStopped())
3979 {
3980 CHECK(recv_msg(ctx, loc, 0, msg));
3981 if (msg[0] == 'x')
3982 break;
3983 if (msg[0] == 'o')
3984 {
3985 char* p = &msg[1];
3986 int c;
3987 while (result == NDBT_OK && (c = *p++) != 0)
3988 {
3989 if (c == 'n')
3990 {
3991 assert(have_trans);
3992 CHECK(ops.execute_NoCommit(pNdb) == 0);
3993 g_info << loc << ": not committed" << endl;
3994 continue;
3995 }
3996 if (c == 'c')
3997 {
3998 assert(have_trans);
3999 CHECK(ops.execute_Commit(pNdb) == 0);
4000 ops.closeTransaction(pNdb);
4001 have_trans = false;
4002 g_info << loc << ": committed" << endl;
4003 continue;
4004 }
4005 if (c == 'a')
4006 {
4007 assert(have_trans);
4008 CHECK(ops.execute_Rollback(pNdb) == 0);
4009 ops.closeTransaction(pNdb);
4010 have_trans = false;
4011 g_info << loc << ": aborted" << endl;
4012 continue;
4013 }
4014 if (c == 'i' || c == 'u' || c == 'd')
4015 {
4016 if (!have_trans)
4017 {
4018 CHECK(ops.startTransaction(pNdb) == 0);
4019 have_trans = true;
4020 g_info << loc << ": trans started" << endl;
4021 }
4022 int i;
4023 for (i = 0; result == NDBT_OK && i < records; i++)
4024 {
4025 if (c == 'i')
4026 CHECK(ops.pkInsertRecord(pNdb, i, 1, opseq) == 0);
4027 if (c == 'u')
4028 CHECK(ops.pkUpdateRecord(pNdb, i, 1, opseq) == 0);
4029 if (c == 'd')
4030 CHECK(ops.pkDeleteRecord(pNdb, i, 1) == 0);
4031 }
4032 char op_str[2];
4033 sprintf(op_str, "%c", c);
4034 g_info << loc << ": op:" << op_str << " records:" << records << endl;
4035 opseq++;
4036 continue;
4037 }
4038 if (c == 'z')
4039 {
4040 CHECK(ops.clearTable(pNdb) == 0);
4041 continue;
4042 }
4043 assert(false);
4044 }
4045 CHECK(send_msg(ctx, loc, 0, "o"));
4046 continue;
4047 }
4048 assert(false);
4049 }
4050 } while (0);
4051
4052 g_err << "ops: loc:" << loc << " exit:" << result << endl;
4053 if (result != NDBT_OK)
4054 ctx->stopTest();
4055 return result;
4056 }
4057
4058 int
runBug54651(NDBT_Context * ctx,NDBT_Step * step)4059 runBug54651(NDBT_Context* ctx, NDBT_Step* step)
4060 {
4061 Ndb* pNdb = GETNDB(step);
4062 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4063
4064 for (Uint32 j = 0; j< 2; j++)
4065 {
4066 pDic->createTable(* ctx->getTab());
4067
4068 const NdbDictionary::Table * pTab =pDic->getTable(ctx->getTab()->getName());
4069 NdbDictionary::Table copy = * pTab;
4070 BaseString name;
4071 name.assfmt("%s_1", pTab->getName());
4072 copy.setName(name.c_str());
4073
4074 if (pDic->createTable(copy))
4075 {
4076 ndbout_c("Failed to create table...");
4077 ndbout << pDic->getNdbError() << endl;
4078 return NDBT_FAILED;
4079 }
4080
4081 NdbDictionary::Table alter = * pTab;
4082 alter.setName(name.c_str());
4083 for (Uint32 i = 0; i<2; i++)
4084 {
4085 // now rename org table to same name...
4086 if (pDic->alterTable(* pTab, alter) == 0)
4087 {
4088 ndbout << "Alter with duplicate name succeeded!!" << endl;
4089 return NDBT_FAILED;
4090 }
4091
4092 ndbout << "Alter with duplicate name failed...good" << endl
4093 << pDic->getNdbError() << endl;
4094 }
4095
4096 pDic->dropTable(copy.getName());
4097 pDic->dropTable(ctx->getTab()->getName());
4098 }
4099 return NDBT_OK;
4100 }
4101
4102 /** telco-6.4 **/
4103
4104 // begin schema trans
4105
4106 #undef chk1
4107 #undef chk2
4108
4109 static bool st_core_on_err = false;
4110
4111 #define chk1(x) \
4112 do { \
4113 if (x) break; \
4114 g_err << "FAIL " << __LINE__ << " " << #x << endl; \
4115 if (st_core_on_err) abort(); \
4116 goto err; \
4117 } while (0)
4118
4119 #define chk2(x, e) \
4120 do { \
4121 if (x) break; \
4122 g_err << "FAIL " << __LINE__ << " " << #x << ": " << e << endl; \
4123 if (st_core_on_err) abort(); \
4124 goto err; \
4125 } while (0)
4126
4127 static uint
urandom(uint m)4128 urandom(uint m)
4129 {
4130 assert(m != 0);
4131 uint n = (uint)ndb_rand();
4132 return n % m;
4133 }
4134
4135 static bool
randomly(uint k,uint m)4136 randomly(uint k, uint m)
4137 {
4138 uint n = urandom(m);
4139 return n < k;
4140 }
4141
4142 // structs
4143
4144 struct ST_Obj;
4145 template class Vector<ST_Obj*>;
4146 typedef Vector<ST_Obj*> ST_Objlist;
4147
4148 static ST_Objlist st_objlist;
4149 #ifndef NDEBUG
4150 static const ST_Obj* st_find_obj(const char* db, const char* name);
4151 #endif
4152
4153 #define ST_MAX_NAME_SIZE (MAX_TAB_NAME_SIZE + 100)
4154
4155 struct ST_Obj {
4156 NdbDictionary::Object::Type type;
4157 char dbname[ST_MAX_NAME_SIZE];
4158 char name[ST_MAX_NAME_SIZE];
4159 int id;
4160 bool create; // true/false = create/drop prepared or committed
4161 bool commit;
existsST_Obj4162 bool exists() const { // visible to trans
4163 return !(!create && commit);
4164 }
is_triggerST_Obj4165 virtual bool is_trigger() const {
4166 return false;
4167 }
is_indexST_Obj4168 virtual bool is_index() const {
4169 return false;
4170 }
is_tableST_Obj4171 virtual bool is_table() const {
4172 return false;
4173 }
realnameST_Obj4174 virtual const char* realname() const {
4175 return name;
4176 }
ST_ObjST_Obj4177 ST_Obj(const char* a_dbname, const char* a_name) {
4178 type = NdbDictionary::Object::TypeUndefined;
4179 strcpy(dbname, a_dbname);
4180 strcpy(name, a_name);
4181 id = -1;
4182 create = false; // init as dropped
4183 commit = true;
4184 assert(st_find_obj(dbname, name) == 0);
4185 st_objlist.push_back(this);
4186 }
~ST_ObjST_Obj4187 virtual ~ST_Obj() {}
4188 };
4189
4190 static NdbOut&
operator <<(NdbOut & out,const ST_Obj & obj)4191 operator<<(NdbOut& out, const ST_Obj& obj)
4192 {
4193 out << obj.name << "[" << obj.id << "]";
4194 return out;
4195 }
4196
4197 struct ST_Trg : public ST_Obj {
4198 struct ST_Ind* ind;
4199 TriggerEvent::Value event;
4200 mutable char realname_buf[ST_MAX_NAME_SIZE];
is_triggerST_Trg4201 virtual bool is_trigger() const {
4202 return true;
4203 }
4204 virtual const char* realname() const;
ST_TrgST_Trg4205 ST_Trg(const char* a_db, const char* a_name) :
4206 ST_Obj(a_db, a_name) {
4207 ind = 0;
4208 }
~ST_TrgST_Trg4209 virtual ~ST_Trg() {};
4210 };
4211
4212 template class Vector<ST_Trg*>;
4213 typedef Vector<ST_Trg*> ST_Trglist;
4214
4215 struct ST_Ind : public ST_Obj {
4216 struct ST_Tab* tab;
4217 const NdbDictionary::Index* ind;
4218 const NdbDictionary::Index* ind_r; // retrieved
4219 BaseString colnames;
4220 ST_Trglist* trglist;
4221 int trgcount;
is_indexST_Ind4222 virtual bool is_index() const {
4223 return true;
4224 }
is_uniqueST_Ind4225 bool is_unique() const {
4226 return type == NdbDictionary::Object::UniqueHashIndex;
4227 }
trgST_Ind4228 const ST_Trg& trg(int k) const {
4229 return *((*trglist)[k]);
4230 }
trgST_Ind4231 ST_Trg& trg(int k) {
4232 return *((*trglist)[k]);
4233 }
ST_IndST_Ind4234 ST_Ind(const char* a_db, const char* a_name) :
4235 ST_Obj(a_db, a_name) {
4236 tab = 0;
4237 ind = 0;
4238 ind_r = 0;
4239 trglist = new ST_Trglist;
4240 trgcount = 0;
4241 };
~ST_IndST_Ind4242 virtual ~ST_Ind() {
4243 delete ind;
4244 delete trglist;
4245 ind = 0;
4246 trglist = 0;
4247 }
4248 };
4249
4250 const char*
realname() const4251 ST_Trg::realname() const
4252 {
4253 if (!exists())
4254 return name;
4255 const char* p = name;
4256 const char* q = strchr(p, '<');
4257 const char* r = strchr(p, '>');
4258 assert(q != 0 && r != 0 && q < r);
4259 assert(ind->id != -1);
4260 sprintf(realname_buf, "%.*s%d%s", (int)(q - p), p, ind->id, r + 1);
4261 return realname_buf;
4262 }
4263
4264 template class Vector<ST_Ind*>;
4265 typedef Vector<ST_Ind*> ST_Indlist;
4266
4267 struct ST_Tab : public ST_Obj {
4268 const NdbDictionary::Table* tab;
4269 const NdbDictionary::Table* tab_r; // retrieved
4270 ST_Indlist* indlist;
4271 int indcount;
4272 int induniquecount;
4273 int indorderedcount;
is_tableST_Tab4274 virtual bool is_table() const {
4275 return true;
4276 }
indST_Tab4277 const ST_Ind& ind(int j) const {
4278 return *((*indlist)[j]);
4279 }
indST_Tab4280 ST_Ind& ind(int j) {
4281 return *((*indlist)[j]);
4282 }
ST_TabST_Tab4283 ST_Tab(const char* a_db, const char* a_name) :
4284 ST_Obj(a_db, a_name) {
4285 tab = 0;
4286 tab_r = 0;
4287 indlist = new ST_Indlist;
4288 indcount = 0;
4289 induniquecount = 0;
4290 indorderedcount = 0;
4291 }
~ST_TabST_Tab4292 virtual ~ST_Tab() {
4293 delete tab;
4294 delete indlist;
4295 tab = 0;
4296 indlist = 0;
4297 }
4298 };
4299
4300 template class Vector<ST_Tab*>;
4301 typedef Vector<ST_Tab*> ST_Tablist;
4302
4303 struct ST_Restarter : public NdbRestarter {
4304 int get_status();
4305 const ndb_mgm_node_state& get_state(int node_id);
ST_RestarterST_Restarter4306 ST_Restarter() {
4307 int i;
4308 for (i = 0; i < MAX_NODES; i++)
4309 state[i].node_type = NDB_MGM_NODE_TYPE_UNKNOWN;
4310 first_time = true;
4311 }
4312 protected:
4313 void set_state(const ndb_mgm_node_state& state);
4314 ndb_mgm_node_state state[MAX_NODES];
4315 bool first_time;
4316 };
4317
4318 const ndb_mgm_node_state&
get_state(int node_id)4319 ST_Restarter::get_state(int node_id) {
4320 assert(node_id > 0 && node_id < MAX_NODES);
4321 assert(!first_time);
4322 return state[node_id];
4323 }
4324
4325 void
set_state(const ndb_mgm_node_state & new_state)4326 ST_Restarter::set_state(const ndb_mgm_node_state& new_state)
4327 {
4328 int node_id = new_state.node_id;
4329 assert(1 <= node_id && node_id < MAX_NODES);
4330
4331 assert(new_state.node_type == NDB_MGM_NODE_TYPE_MGM ||
4332 new_state.node_type == NDB_MGM_NODE_TYPE_NDB ||
4333 new_state.node_type == NDB_MGM_NODE_TYPE_API);
4334
4335 ndb_mgm_node_state& old_state = state[node_id];
4336 if (!first_time)
4337 assert(old_state.node_type == new_state.node_type);
4338 old_state = new_state;
4339 }
4340
4341 int
get_status()4342 ST_Restarter::get_status()
4343 {
4344 if (getStatus() == -1)
4345 return -1;
4346 int i;
4347 for (i = 0; i < (int)mgmNodes.size(); i++)
4348 set_state(mgmNodes[i]);
4349 for (i = 0; i < (int)ndbNodes.size(); i++)
4350 set_state(ndbNodes[i]);
4351 for (i = 0; i < (int)apiNodes.size(); i++)
4352 set_state(apiNodes[i]);
4353 first_time = false;
4354 return 0;
4355 }
4356
4357 struct ST_Con {
4358 Ndb_cluster_connection* ncc;
4359 Ndb* ndb;
4360 NdbDictionary::Dictionary* dic;
4361 ST_Restarter* restarter;
4362 int numdbnodes;
4363 char dbname[ST_MAX_NAME_SIZE];
4364 ST_Tablist* tablist;
4365 int tabcount;
4366 bool tx_on;
4367 bool tx_commit;
4368 bool is_xcon;
4369 ST_Con* xcon;
4370 int node_id;
4371 int loop;
tabST_Con4372 const ST_Tab& tab(int i) const {
4373 return *((*tablist)[i]);
4374 }
tabST_Con4375 ST_Tab& tab(int i) {
4376 return *((*tablist)[i]);
4377 }
ST_ConST_Con4378 ST_Con(Ndb_cluster_connection* a_ncc,
4379 Ndb* a_ndb,
4380 ST_Restarter* a_restarter) {
4381 ncc = a_ncc;
4382 ndb = a_ndb;
4383 dic = a_ndb->getDictionary();
4384 restarter = a_restarter;
4385 numdbnodes = restarter->getNumDbNodes();
4386 assert(numdbnodes >= 1);
4387 sprintf(dbname, "%s", ndb->getDatabaseName());
4388 tablist = new ST_Tablist;
4389 tabcount = 0;
4390 tx_on = false;
4391 tx_commit = false;
4392 is_xcon = false;
4393 xcon = 0;
4394 node_id = ncc->node_id();
4395 {
4396 assert(restarter->get_status() == 0);
4397 const ndb_mgm_node_state& state = restarter->get_state(node_id);
4398 assert(state.node_type == NDB_MGM_NODE_TYPE_API);
4399 assert(state.version != 0); // means "connected"
4400 g_info << "node_id:" << node_id << endl;
4401 }
4402 loop = -1;
4403 }
~ST_ConST_Con4404 ~ST_Con() {
4405 if (!is_xcon) {
4406 delete tablist;
4407 } else {
4408 delete ndb;
4409 delete ncc;
4410 }
4411 tablist = 0;
4412 ndb = 0;
4413 ncc = 0;
4414 }
4415 };
4416
4417 // initialization
4418
4419 static int
st_drop_all_tables(ST_Con & c)4420 st_drop_all_tables(ST_Con& c)
4421 {
4422 g_info << "st_drop_all_tables" << endl;
4423 NdbDictionary::Dictionary::List list;
4424 chk2(c.dic->listObjects(list) == 0, c.dic->getNdbError());
4425 int n;
4426 for (n = 0; n < (int)list.count; n++) {
4427 const NdbDictionary::Dictionary::List::Element& element =
4428 list.elements[n];
4429 if (element.type == NdbDictionary::Object::UserTable &&
4430 strcmp(element.database, "TEST_DB") == 0) {
4431 chk2(c.dic->dropTable(element.name) == 0, c.dic->getNdbError());
4432 }
4433 }
4434 return 0;
4435 err:
4436 return -1;
4437 }
4438
4439 static void
st_init_objects(ST_Con & c,NDBT_Context * ctx)4440 st_init_objects(ST_Con& c, NDBT_Context* ctx)
4441 {
4442 int numTables = ctx->getNumTables();
4443 c.tabcount = 0;
4444 int i;
4445 for (i = 0; i < numTables; i++) {
4446 const NdbDictionary::Table* pTab = 0;
4447 #if ndb_test_ALL_TABLES_is_fixed
4448 const NdbDictionary::Table** tables = ctx->getTables();
4449 pTab = tables[i];
4450 #else
4451 const Vector<BaseString>& tables = ctx->getSuite()->m_tables_in_test;
4452 pTab = NDBT_Tables::getTable(tables[i].c_str());
4453 #endif
4454 assert(pTab != 0 && pTab->getName() != 0);
4455
4456 {
4457 bool ok = true;
4458 int n;
4459 for (n = 0; n < pTab->getNoOfColumns(); n++) {
4460 const NdbDictionary::Column* pCol = pTab->getColumn(n);
4461 assert(pCol != 0);
4462 if (pCol->getStorageType() !=
4463 NdbDictionary::Column::StorageTypeMemory) {
4464 g_err << pTab->getName() << ": skip non-mem table for now" << endl;
4465 ok = false;
4466 break;
4467 }
4468 }
4469 if (!ok)
4470 continue;
4471 }
4472
4473 c.tablist->push_back(new ST_Tab(c.dbname, pTab->getName()));
4474 c.tabcount++;
4475 ST_Tab& tab = *c.tablist->back();
4476 tab.type = NdbDictionary::Object::UserTable;
4477 tab.tab = new NdbDictionary::Table(*pTab);
4478
4479 const char** indspec = NDBT_Tables::getIndexes(tab.name);
4480
4481 while (indspec != 0 && *indspec != 0) {
4482 char ind_name[ST_MAX_NAME_SIZE];
4483 sprintf(ind_name, "%sX%d", tab.name, tab.indcount);
4484 tab.indlist->push_back(new ST_Ind("sys", ind_name));
4485 ST_Ind& ind = *tab.indlist->back();
4486 ind.tab = &tab;
4487
4488 NdbDictionary::Index* pInd = new NdbDictionary::Index(ind.name);
4489 pInd->setTable(tab.name);
4490 pInd->setLogging(false);
4491
4492 const char* type = *indspec++;
4493 if (strcmp(type, "UNIQUE") == 0) {
4494 ind.type = NdbDictionary::Object::UniqueHashIndex;
4495 pInd->setType((NdbDictionary::Index::Type)ind.type);
4496 tab.induniquecount++;
4497
4498 { char trg_name[ST_MAX_NAME_SIZE];
4499 sprintf(trg_name, "NDB$INDEX_<%s>_UI", ind.name);
4500 ind.trglist->push_back(new ST_Trg("", trg_name));
4501 ST_Trg& trg = *ind.trglist->back();
4502 trg.ind = &ind;
4503 trg.type = NdbDictionary::Object::HashIndexTrigger;
4504 trg.event = TriggerEvent::TE_INSERT;
4505 }
4506 ind.trgcount = 1;
4507 }
4508 else if (strcmp(type, "ORDERED") == 0) {
4509 ind.type = NdbDictionary::Object::OrderedIndex;
4510 pInd->setType((NdbDictionary::Index::Type)ind.type);
4511 tab.indorderedcount++;
4512
4513 { char trg_name[ST_MAX_NAME_SIZE];
4514 sprintf(trg_name, "NDB$INDEX_<%s>_CUSTOM", ind.name);
4515 ind.trglist->push_back(new ST_Trg("", trg_name));
4516 ST_Trg& trg = *ind.trglist->back();
4517 trg.ind = &ind;
4518 trg.type = NdbDictionary::Object::IndexTrigger;
4519 trg.event = TriggerEvent::TE_CUSTOM;
4520 }
4521 ind.trgcount = 1;
4522 }
4523 else
4524 assert(false);
4525
4526 const char* sep = "";
4527 const char* colname;
4528 while ((colname = *indspec++) != 0) {
4529 const NdbDictionary::Column* col = tab.tab->getColumn(colname);
4530 assert(col != 0);
4531 pInd->addColumn(*col);
4532
4533 ind.colnames.appfmt("%s%s", sep, colname);
4534 sep = ",";
4535 }
4536
4537 ind.ind = pInd;
4538 tab.indcount++;
4539 }
4540 }
4541 }
4542
4543 // node states
4544
4545 static int
st_report_db_nodes(ST_Con & c,NdbOut & out)4546 st_report_db_nodes(ST_Con& c, NdbOut& out)
4547 {
4548 chk1(c.restarter->get_status() == 0);
4549 char r1[100]; // up
4550 char r2[100]; // down
4551 char r3[100]; // unknown
4552 r1[0] =r2[0] = r3[0] = 0;
4553 int i;
4554 for (i = 1; i < MAX_NODES; i++) {
4555 const ndb_mgm_node_state& state = c.restarter->get_state(i);
4556 if (state.node_type == NDB_MGM_NODE_TYPE_NDB) {
4557 char* r = 0;
4558 if (state.node_status == NDB_MGM_NODE_STATUS_STARTED)
4559 r = r1;
4560 else if (state.node_status == NDB_MGM_NODE_STATUS_NO_CONTACT)
4561 r = r2;
4562 else
4563 r = r3;
4564 sprintf(r + strlen(r), "%s%d", r[0] == 0 ? "" : ",", i);
4565 }
4566 }
4567 if (r2[0] != 0 || r3[0] != 0) {
4568 out << "nodes up:" << r1 << " down:" << r2 << " unknown:" << r3 << endl;
4569 goto err;
4570 }
4571 out << "nodes up:" << r1 << " (all)" << endl;
4572 return 0;
4573 err:
4574 return -1;
4575 }
4576
4577 static int
st_check_db_nodes(ST_Con & c,int ignore_node_id=-1)4578 st_check_db_nodes(ST_Con& c, int ignore_node_id = -1)
4579 {
4580 chk1(c.restarter->get_status() == 0);
4581 int i;
4582 for (i = 1; i < MAX_NODES; i++) {
4583 const ndb_mgm_node_state& state = c.restarter->get_state(i);
4584 if (state.node_type == NDB_MGM_NODE_TYPE_NDB &&
4585 i != ignore_node_id) {
4586 chk2(state.node_status == NDB_MGM_NODE_STATUS_STARTED, " node:" << i);
4587 }
4588 }
4589 return 0;
4590 err:
4591 return -1;
4592 }
4593
4594 #if 0
4595 static int
4596 st_wait_db_node_up(ST_Con& c, int node_id)
4597 {
4598 int count = 0;
4599 int max_count = 30;
4600 int milli_sleep = 2000;
4601 while (count++ < max_count) {
4602 // get status and check that other db nodes have not crashed
4603 chk1(st_check_db_nodes(c, node_id) == 0);
4604
4605 const ndb_mgm_node_state& state = c.restarter->get_state(node_id);
4606 assert(state.node_type == NDB_MGM_NODE_TYPE_NDB);
4607 if (state.node_status == NDB_MGM_NODE_STATUS_STARTED)
4608 break;
4609 g_info << "waiting count:" << count << "/" << max_count << endl;
4610 NdbSleep_MilliSleep(milli_sleep);
4611 }
4612 return 0;
4613 err:
4614 return -1;
4615 }
4616 #endif
4617
4618 // extra connection (separate API node)
4619
4620 static int
st_start_xcon(ST_Con & c)4621 st_start_xcon(ST_Con& c)
4622 {
4623 assert(c.xcon == 0);
4624 g_info << "start extra connection" << endl;
4625
4626 do {
4627 int ret;
4628 Ndb_cluster_connection* xncc = new Ndb_cluster_connection;
4629 chk2((ret = xncc->connect(30, 1, 0)) == 0, "ret:" << ret);
4630 chk2((ret = xncc->wait_until_ready(30, 10)) == 0, "ret:" << ret);
4631 Ndb* xndb = new Ndb(xncc, c.dbname);
4632 chk1(xndb->init() == 0);
4633 chk1(xndb->waitUntilReady(30) == 0);
4634 // share restarter
4635 c.xcon = new ST_Con(xncc, xndb, c.restarter);
4636 // share objects
4637 c.xcon->tablist = c.tablist;
4638 c.xcon->tabcount = c.tabcount;
4639 c.xcon->is_xcon = true;
4640 } while (0);
4641 return 0;
4642 err:
4643 return -1;
4644 }
4645
4646 static int
st_stop_xcon(ST_Con & c)4647 st_stop_xcon(ST_Con& c)
4648 {
4649 assert(c.xcon != 0);
4650 int node_id = c.xcon->node_id;
4651 g_info << "stop extra connection node_id:" << node_id << endl;
4652
4653 c.xcon->restarter = 0;
4654 c.xcon->tablist = 0;
4655 c.xcon->tabcount = 0;
4656 delete c.xcon;
4657 c.xcon = 0;
4658 int count = 0;
4659 while (1) {
4660 chk1(c.restarter->get_status() == 0);
4661 const ndb_mgm_node_state& state = c.restarter->get_state(node_id);
4662 assert(state.node_type == NDB_MGM_NODE_TYPE_API);
4663 if (state.version == 0) // means "disconnected"
4664 break;
4665 g_info << "waiting count:" << ++count << endl;
4666 NdbSleep_MilliSleep(10 * count);
4667 }
4668 return 0;
4669 err:
4670 return -1;
4671 }
4672
4673 // error insert
4674
4675 struct ST_Errins {
4676 int value; // error value to insert
4677 int code; // ndb error code to expect
4678 int master; // insert on master / non-master (-1 = random)
4679 int node; // insert on node id
4680 const ST_Errins* list; // include another list
4681 bool ends; // end list
ST_ErrinsST_Errins4682 ST_Errins() :
4683 value(0), code(0), master(-1), node(0), list(0), ends(true)
4684 {}
ST_ErrinsST_Errins4685 ST_Errins(const ST_Errins* l) :
4686 value(0), code(0), master(-1), node(0), list(l), ends(false)
4687 {}
ST_ErrinsST_Errins4688 ST_Errins(int v, int c, int m = -1) :
4689 value(v), code(c), master(m), node(0), list(0), ends(false)
4690 {}
4691 };
4692
4693 static NdbOut&
operator <<(NdbOut & out,const ST_Errins & errins)4694 operator<<(NdbOut& out, const ST_Errins& errins)
4695 {
4696 out << "value:" << errins.value;
4697 out << " code:" << errins.code;
4698 out << " master:" << errins.master;
4699 out << " node:" << errins.node;
4700 return out;
4701 }
4702
4703 static ST_Errins
st_get_errins(ST_Con & c,const ST_Errins * list)4704 st_get_errins(ST_Con& c, const ST_Errins* list)
4705 {
4706 uint size = 0;
4707 while (!list[size++].ends)
4708 ;
4709 assert(size > 1);
4710 uint n = urandom(size - 1);
4711 const ST_Errins& errins = list[n];
4712 if (errins.list == 0) {
4713 assert(errins.value != 0);
4714 return errins;
4715 }
4716 return st_get_errins(c, errins.list);
4717 }
4718
4719 static int
st_do_errins(ST_Con & c,ST_Errins & errins)4720 st_do_errins(ST_Con& c, ST_Errins& errins)
4721 {
4722 assert(errins.value != 0);
4723 if (c.numdbnodes < 2)
4724 errins.master = 1;
4725 else if (errins.master == -1)
4726 errins.master = randomly(1, 2);
4727 if (errins.master) {
4728 errins.node = c.restarter->getMasterNodeId();
4729 } else {
4730 uint rand = urandom(c.numdbnodes);
4731 errins.node = c.restarter->getRandomNotMasterNodeId(rand);
4732 }
4733 g_info << "errins: " << errins << endl;
4734 chk2(c.restarter->insertErrorInNode(errins.node, errins.value) == 0, errins);
4735 c.restarter->get_status(); // do sync call to ensure error has been inserted
4736 return 0;
4737 err:
4738 return -1;
4739 }
4740
4741 // debug aid
4742 #ifndef NDEBUG
4743 static const ST_Obj*
st_find_obj(const char * dbname,const char * name)4744 st_find_obj(const char* dbname, const char* name)
4745 {
4746 const ST_Obj* ret_objp = 0;
4747 int i;
4748 for (i = 0; i < (int)st_objlist.size(); i++) {
4749 const ST_Obj* objp = st_objlist[i];
4750 if (strcmp(objp->dbname, dbname) == 0 &&
4751 strcmp(objp->name, name) == 0) {
4752 assert(ret_objp == 0);
4753 ret_objp = objp;
4754 }
4755 }
4756 return ret_objp;
4757 }
4758 #endif
4759
4760 #if 0
4761 static void
4762 st_print_obj(const char* dbname, const char* name, int line = 0)
4763 {
4764 const ST_Obj* objp = st_find_obj(dbname, name);
4765 g_info << name << ": by name:";
4766 if (objp != 0)
4767 g_info << " create:" << objp->create
4768 << " commit:" << objp->commit
4769 << " exists:" << objp->exists();
4770 else
4771 g_info << " not found";
4772 if (line != 0)
4773 g_info << " line:" << line;
4774 g_info << endl;
4775 }
4776 #endif
4777
4778 // set object state
4779
4780 static void
st_set_commit_obj(ST_Con & c,ST_Obj & obj)4781 st_set_commit_obj(ST_Con& c, ST_Obj& obj)
4782 {
4783 bool create_old = obj.create;
4784 bool commit_old = obj.commit;
4785 if (!c.tx_commit && !obj.commit)
4786 obj.create = !obj.create;
4787 obj.commit = true;
4788 if (create_old != obj.create || commit_old != obj.commit) {
4789 g_info << obj.name << ": set commit:"
4790 << " create:" << create_old << "->" << obj.create
4791 << " commit:" << commit_old << "->" << obj.commit << endl;
4792 }
4793 }
4794
4795 #if 0
4796 static void
4797 st_set_commit_trg(ST_Con& c, ST_Trg& trg)
4798 {
4799 st_set_commit_obj(c, trg);
4800 }
4801 #endif
4802
4803 static void
st_set_commit_ind(ST_Con & c,ST_Ind & ind)4804 st_set_commit_ind(ST_Con& c, ST_Ind& ind)
4805 {
4806 st_set_commit_obj(c, ind);
4807 int k;
4808 for (k = 0; k < ind.trgcount; k++) {
4809 ST_Trg& trg = ind.trg(k);
4810 st_set_commit_obj(c, trg);
4811 }
4812 }
4813
4814 static void
st_set_commit_tab(ST_Con & c,ST_Tab & tab)4815 st_set_commit_tab(ST_Con& c, ST_Tab& tab)
4816 {
4817 st_set_commit_obj(c, tab);
4818 int j;
4819 for (j = 0; j < tab.indcount; j++) {
4820 ST_Ind& ind = tab.ind(j);
4821 st_set_commit_ind(c, ind);
4822 }
4823 }
4824
4825 static void
st_set_commit_all(ST_Con & c)4826 st_set_commit_all(ST_Con& c)
4827 {
4828 int i;
4829 for (i = 0; i < c.tabcount; i++) {
4830 ST_Tab& tab = c.tab(i);
4831 st_set_commit_tab(c, tab);
4832 }
4833 }
4834
4835 static void
st_set_create_obj(ST_Con & c,ST_Obj & obj,bool create)4836 st_set_create_obj(ST_Con& c, ST_Obj& obj, bool create)
4837 {
4838 bool create_old = obj.create;
4839 bool commit_old = obj.commit;
4840 obj.create = create;
4841 obj.commit = !c.tx_on;
4842 if (create_old != obj.create || commit_old != obj.commit) {
4843 g_info << obj.name << ": set create:"
4844 << " create:" << create_old << "->" << obj.create
4845 << " commit:" << commit_old << "->" << obj.commit << endl;
4846 }
4847 }
4848
4849 static void
st_set_create_trg(ST_Con & c,ST_Trg & trg,bool create)4850 st_set_create_trg(ST_Con& c, ST_Trg& trg, bool create)
4851 {
4852 st_set_create_obj(c, trg, create);
4853 }
4854
4855 static void
st_set_create_ind(ST_Con & c,ST_Ind & ind,bool create)4856 st_set_create_ind(ST_Con& c, ST_Ind& ind, bool create)
4857 {
4858 st_set_create_obj(c, ind, create);
4859 int k;
4860 for (k = 0; k < ind.trgcount; k++) {
4861 ST_Trg& trg = ind.trg(k);
4862 st_set_create_trg(c, trg, create);
4863 }
4864 }
4865
4866 static void
st_set_create_tab(ST_Con & c,ST_Tab & tab,bool create)4867 st_set_create_tab(ST_Con& c, ST_Tab& tab, bool create)
4868 {
4869 st_set_create_obj(c, tab, create);
4870 int j;
4871 for (j = 0; j < tab.indcount; j++) {
4872 ST_Ind& ind = tab.ind(j);
4873 if (create == true)
4874 assert(!ind.exists());
4875 else {
4876 if (ind.exists())
4877 st_set_create_ind(c, ind, false);
4878 }
4879 }
4880 }
4881
4882 // verify against database listing
4883
4884 static bool
st_known_type(const NdbDictionary::Dictionary::List::Element & element)4885 st_known_type(const NdbDictionary::Dictionary::List::Element& element)
4886 {
4887 switch (element.type) {
4888 case NdbDictionary::Object::UserTable:
4889 assert(element.database != 0);
4890 if (strcmp(element.database, "mysql") == 0)
4891 break;
4892 if (strncmp(element.name, "NDB$BLOB", 8) == 0)
4893 break;
4894 return true;
4895 case NdbDictionary::Object::UniqueHashIndex:
4896 case NdbDictionary::Object::OrderedIndex:
4897 case NdbDictionary::Object::HashIndexTrigger:
4898 case NdbDictionary::Object::IndexTrigger:
4899 return true;
4900 default:
4901 break;
4902 }
4903 return false;
4904 }
4905
4906 static bool
st_match_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element)4907 st_match_obj(const ST_Obj& obj,
4908 const NdbDictionary::Dictionary::List::Element& element)
4909 {
4910 int veryverbose = 0;
4911 if (veryverbose) {
4912 g_info
4913 << "match:"
4914 << " " << obj.type << "-" << element.type
4915 << " " << obj.dbname << "-" << element.database
4916 << " " << obj.realname() << "-" << element.name << endl;
4917 }
4918 return
4919 obj.type == element.type &&
4920 strcmp(obj.dbname, element.database) == 0 &&
4921 strcmp(obj.realname(), element.name) == 0;
4922 }
4923
4924 static int // check state
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element)4925 st_verify_obj(const ST_Obj& obj,
4926 const NdbDictionary::Dictionary::List::Element& element)
4927 {
4928 chk2(obj.exists(), obj.name);
4929
4930 if (obj.commit)
4931 chk2(element.state == NdbDictionary::Object::StateOnline, obj.name);
4932
4933 // other states are inconsistent
4934
4935 else if (obj.create) {
4936 if (obj.is_table() || obj.is_index())
4937 chk2(element.state == NdbDictionary::Object::StateBuilding, obj.name);
4938 if (obj.is_trigger())
4939 chk2(element.state == NdbDictionary::Object::StateBuilding, obj.name);
4940 }
4941 else {
4942 if (obj.is_trigger())
4943 chk2(element.state == NdbDictionary::Object::StateOnline, obj.name);
4944 if (obj.is_table() || obj.is_index())
4945 chk2(element.state == NdbDictionary::Object::StateDropping, obj.name);
4946 }
4947 return 0;
4948 err:
4949 return -1;
4950 }
4951
4952 static int // find on list
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List & list)4953 st_verify_obj(const ST_Obj& obj,
4954 const NdbDictionary::Dictionary::List& list)
4955 {
4956 int found = 0;
4957 int n;
4958 for (n = 0; n < (int)list.count; n++) {
4959 const NdbDictionary::Dictionary::List::Element& element =
4960 list.elements[n];
4961 if (!st_known_type(element))
4962 continue;
4963 if (st_match_obj(obj, element)) {
4964 chk1(st_verify_obj(obj, element) == 0);
4965 found += 1;
4966 }
4967 }
4968 if (obj.exists())
4969 chk2(found == 1, obj.name);
4970 else
4971 chk2(found == 0, obj.name);
4972 return 0;
4973 err:
4974 return -1;
4975 }
4976
4977 static int // possible match
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element,int & found)4978 st_verify_obj(const ST_Obj& obj,
4979 const NdbDictionary::Dictionary::List::Element& element,
4980 int& found)
4981 {
4982 if (obj.exists()) {
4983 if (st_match_obj(obj, element)) {
4984 chk1(st_verify_obj(obj, element) == 0);
4985 found += 1;
4986 }
4987 }
4988 else {
4989 chk2(st_match_obj(obj, element) == false, obj.name);
4990 }
4991 return 0;
4992 err:
4993 return -1;
4994 }
4995
4996 static int
st_verify_list(ST_Con & c)4997 st_verify_list(ST_Con& c)
4998 {
4999 NdbDictionary::Dictionary::List list;
5000 chk2(c.dic->listObjects(list) == 0, c.dic->getNdbError());
5001 int i, j, k, n;
5002 // us vs list
5003 for (i = 0; i < c.tabcount; i++) {
5004 const ST_Tab& tab = c.tab(i);
5005 chk1(st_verify_obj(tab, list) == 0);
5006 for (j = 0; j < tab.indcount; j++) {
5007 const ST_Ind& ind = tab.ind(j);
5008 chk1(st_verify_obj(ind, list) == 0);
5009 for (k = 0; k < ind.trgcount; k++) {
5010 const ST_Trg& trg = ind.trg(k);
5011 chk1(st_verify_obj(trg, list) == 0);
5012 }
5013 }
5014 }
5015 // list vs us
5016 for (n = 0; n < (int)list.count; n++) {
5017 const NdbDictionary::Dictionary::List::Element& element =
5018 list.elements[n];
5019 if (!st_known_type(element))
5020 continue;
5021 int found = 0;
5022 for (i = 0; i < c.tabcount; i++) {
5023 const ST_Tab& tab = c.tab(i);
5024 chk1(st_verify_obj(tab, element, found) == 0);
5025 for (j = 0; j < tab.indcount; j++) {
5026 const ST_Ind& ind = tab.ind(j);
5027 chk1(st_verify_obj(ind, element, found) == 0);
5028 for (k = 0; k < ind.trgcount; k++) {
5029 const ST_Trg& trg = ind.trg(k);
5030 chk1(st_verify_obj(trg, element, found) == 0);
5031 }
5032 }
5033 }
5034 const char* dot = element.database[0] != 0 ? "." : "";
5035 chk2(found == 1, element.database << dot << element.name);
5036 }
5037 return 0;
5038 err:
5039 return -1;
5040 }
5041
5042 // wait for DICT to finish current trans
5043
5044 static int
st_wait_idle(ST_Con & c)5045 st_wait_idle(ST_Con& c)
5046 {
5047 // todo: use try-lock when available
5048 g_info << "st_wait_idle" << endl;
5049 int count = 0;
5050 int max_count = 60;
5051 int milli_sleep = 1000;
5052 while (count++ < max_count) {
5053 NdbDictionary::Dictionary::List list;
5054 chk2(c.dic->listObjects(list) == 0, c.dic->getNdbError());
5055 bool ok = true;
5056 int n;
5057 for (n = 0; n < (int)list.count; n++) {
5058 const NdbDictionary::Dictionary::List::Element& element =
5059 list.elements[n];
5060 if (!st_known_type(element))
5061 continue;
5062 if (element.state != NdbDictionary::Object::StateOnline) {
5063 ok = false;
5064 break;
5065 }
5066 }
5067 if (ok)
5068 return 0;
5069 g_info << "waiting count:" << count << "/" << max_count << endl;
5070 NdbSleep_MilliSleep(milli_sleep);
5071 }
5072 g_err << "st_wait_idle: objects did not become Online" << endl;
5073 err:
5074 return -1;
5075 }
5076
5077 // ndb dict comparisons (non-retrieved vs retrieved)
5078
5079 static int
st_equal_column(const NdbDictionary::Column & c1,const NdbDictionary::Column & c2,NdbDictionary::Object::Type type)5080 st_equal_column(const NdbDictionary::Column& c1,
5081 const NdbDictionary::Column& c2,
5082 NdbDictionary::Object::Type type)
5083 {
5084 chk1(strcmp(c1.getName(), c2.getName()) == 0);
5085 chk1(c1.getNullable() == c2.getNullable());
5086 if (type == NdbDictionary::Object::UserTable) {
5087 chk1(c1.getPrimaryKey() == c2.getPrimaryKey());
5088 }
5089 if (0) { // should fix
5090 chk1(c1.getColumnNo() == c2.getColumnNo());
5091 }
5092 chk1(c1.getType() == c2.getType());
5093 if (c1.getType() == NdbDictionary::Column::Decimal ||
5094 c1.getType() == NdbDictionary::Column::Decimalunsigned) {
5095 chk1(c1.getPrecision() == c2.getPrecision());
5096 chk1(c1.getScale() == c2.getScale());
5097 }
5098 if (c1.getType() != NdbDictionary::Column::Blob &&
5099 c1.getType() != NdbDictionary::Column::Text) {
5100 chk1(c1.getLength() == c2.getLength());
5101 } else {
5102 chk1(c1.getInlineSize() == c2.getInlineSize());
5103 chk1(c1.getPartSize() == c2.getPartSize());
5104 chk1(c1.getStripeSize() == c2.getStripeSize());
5105 }
5106 chk1(c1.getCharset() == c2.getCharset());
5107 if (type == NdbDictionary::Object::UserTable) {
5108 chk1(c1.getPartitionKey() == c2.getPartitionKey());
5109 }
5110 chk1(c1.getArrayType() == c2.getArrayType());
5111 chk1(c1.getStorageType() == c2.getStorageType());
5112 chk1(c1.getDynamic() == c2.getDynamic());
5113 chk1(c1.getAutoIncrement() == c2.getAutoIncrement());
5114 return 0;
5115 err:
5116 return -1;
5117 }
5118
5119 static int
st_equal_table(const NdbDictionary::Table & t1,const NdbDictionary::Table & t2)5120 st_equal_table(const NdbDictionary::Table& t1, const NdbDictionary::Table& t2)
5121 {
5122 chk1(strcmp(t1.getName(), t2.getName()) == 0);
5123 chk1(t1.getLogging() == t2.getLogging());
5124 chk1(t1.getFragmentType() == t2.getFragmentType());
5125 chk1(t1.getKValue() == t2.getKValue());
5126 chk1(t1.getMinLoadFactor() == t2.getMinLoadFactor());
5127 chk1(t1.getMaxLoadFactor() == t2.getMaxLoadFactor());
5128 chk1(t1.getNoOfColumns() == t2.getNoOfColumns());
5129 /*
5130 * There is no method to get type of table...
5131 * On the other hand SystemTable/UserTable should be just Table
5132 * and "System" should be an independent property.
5133 */
5134 NdbDictionary::Object::Type type;
5135 type = NdbDictionary::Object::UserTable;
5136 int n;
5137 for (n = 0; n < t1.getNoOfColumns(); n++) {
5138 const NdbDictionary::Column* c1 = t1.getColumn(n);
5139 const NdbDictionary::Column* c2 = t2.getColumn(n);
5140 assert(c1 != 0 && c2 != 0);
5141 chk2(st_equal_column(*c1, *c2, type) == 0, "col:" << n);
5142 }
5143 chk1(t1.getNoOfPrimaryKeys() == t2.getNoOfPrimaryKeys());
5144 chk1(t1.getTemporary() == t2.getTemporary());
5145 chk1(t1.getForceVarPart() == t2.getForceVarPart());
5146 return 0;
5147 err:
5148 return -1;
5149 }
5150
5151 static int
st_equal_index(const NdbDictionary::Index & i1,const NdbDictionary::Index & i2)5152 st_equal_index(const NdbDictionary::Index& i1, const NdbDictionary::Index& i2)
5153 {
5154 chk1(strcmp(i1.getName(), i2.getName()) == 0);
5155 assert(i1.getTable() != 0 && i2.getTable() != 0);
5156 chk1(strcmp(i1.getTable(), i2.getTable()) == 0);
5157 chk1(i1.getNoOfColumns() == i2.getNoOfColumns());
5158 chk1(i1.getType() == i2.getType());
5159 NdbDictionary::Object::Type type;
5160 type = (NdbDictionary::Object::Type)i1.getType();
5161 int n;
5162 for (n = 0; n < (int)i1.getNoOfColumns(); n++) {
5163 const NdbDictionary::Column* c1 = i1.getColumn(n);
5164 const NdbDictionary::Column* c2 = i2.getColumn(n);
5165 assert(c1 != 0 && c2 != 0);
5166 chk2(st_equal_column(*c1, *c2, type) == 0, "col:" << n);
5167 }
5168 chk1(i1.getLogging() == i2.getLogging());
5169 chk1(i1.getTemporary() == i2.getTemporary());
5170 return 0;
5171 err:
5172 return -1;
5173 }
5174
5175 // verify against database objects (hits all nodes randomly)
5176
5177 static int
st_verify_table(ST_Con & c,ST_Tab & tab)5178 st_verify_table(ST_Con& c, ST_Tab& tab)
5179 {
5180 c.dic->invalidateTable(tab.name);
5181 const NdbDictionary::Table* pTab = c.dic->getTable(tab.name);
5182 tab.tab_r = pTab;
5183 if (tab.exists()) {
5184 chk2(pTab != 0, c.dic->getNdbError());
5185 chk1(st_equal_table(*tab.tab, *pTab) == 0);
5186 tab.id = pTab->getObjectId();
5187 g_info << tab << ": verified exists tx_on:" << c.tx_on << endl;
5188 } else {
5189 chk2(pTab == 0, tab);
5190 chk2(c.dic->getNdbError().code == 723, c.dic->getNdbError());
5191 g_info << tab << ": verified not exists tx_on:" << c.tx_on << endl;
5192 tab.id = -1;
5193 }
5194 return 0;
5195 err:
5196 return -1;
5197 }
5198
5199 static int
st_verify_index(ST_Con & c,ST_Ind & ind)5200 st_verify_index(ST_Con& c, ST_Ind& ind)
5201 {
5202 ST_Tab& tab = *ind.tab;
5203 c.dic->invalidateIndex(ind.name, tab.name);
5204 const NdbDictionary::Index* pInd = c.dic->getIndex(ind.name, tab.name);
5205 ind.ind_r = pInd;
5206 if (ind.exists()) {
5207 chk2(pInd != 0, c.dic->getNdbError());
5208 chk1(st_equal_index(*ind.ind, *pInd) == 0);
5209 ind.id = pInd->getObjectId();
5210 g_info << ind << ": verified exists tx_on:" << c.tx_on << endl;
5211 } else {
5212 chk2(pInd == 0, ind);
5213 chk2(c.dic->getNdbError().code == 4243, c.dic->getNdbError());
5214 g_info << ind << ": verified not exists tx_on:" << c.tx_on << endl;
5215 ind.id = -1;
5216 }
5217 return 0;
5218 err:
5219 return -1;
5220 }
5221
5222 static int
st_verify_all(ST_Con & c)5223 st_verify_all(ST_Con& c)
5224 {
5225 chk1(st_verify_list(c) == 0);
5226 int i, j;
5227 for (i = 0; i < c.tabcount; i++) {
5228 ST_Tab& tab = c.tab(i);
5229 chk1(st_verify_table(c, tab) == 0);
5230 for (j = 0; j < tab.indcount; j++) {
5231 ST_Ind& ind = tab.ind(j);
5232 chk1(st_verify_index(c, ind) == 0);
5233 }
5234 }
5235 return 0;
5236 err:
5237 return -1;
5238 }
5239
5240 // subroutines
5241
5242 static const uint
5243 ST_CommitFlag = 0;
5244
5245 static const uint
5246 ST_AbortFlag = NdbDictionary::Dictionary::SchemaTransAbort;
5247
5248 static const uint
5249 ST_BackgroundFlag = NdbDictionary::Dictionary::SchemaTransBackground;
5250
5251 struct ST_Retry {
5252 int max_tries;
5253 int sleep_ms;
5254 };
5255
5256 static int
st_begin_trans(ST_Con & c,int code=0)5257 st_begin_trans(ST_Con& c, int code = 0)
5258 {
5259 g_info << "begin trans";
5260 if (code == 0) {
5261 g_info << endl;
5262 chk2(c.dic->beginSchemaTrans() == 0, c.dic->getNdbError());
5263 chk1(c.dic->hasSchemaTrans() == true);
5264 c.tx_on = true;
5265 } else {
5266 g_info << " - expect error " << code << endl;
5267 chk1(c.dic->beginSchemaTrans() == -1);
5268 const NdbError& error = c.dic->getNdbError();
5269 chk2(error.code == code, error << " wanted: " << code);
5270 }
5271 return 0;
5272 err:
5273 return -1;
5274 }
5275
5276 static int
st_begin_trans(ST_Con & c,ST_Errins errins)5277 st_begin_trans(ST_Con& c, ST_Errins errins)
5278 {
5279 assert(errins.code != 0);
5280 chk1(st_do_errins(c, errins) == 0);
5281 chk1(st_begin_trans(c, errins.code) == 0);
5282 return 0;
5283 err:
5284 return -1;
5285 }
5286
5287 static int
st_begin_trans(ST_Con & c,ST_Retry retry)5288 st_begin_trans(ST_Con& c, ST_Retry retry)
5289 {
5290 int tries = 0;
5291 while (++tries <= retry.max_tries) {
5292 int code = 0;
5293 if (c.dic->beginSchemaTrans() == -1) {
5294 code = c.dic->getNdbError().code;
5295 assert(code != 0);
5296 }
5297 chk2(code == 0 || code == 780 || code == 701, c.dic->getNdbError());
5298 if (code == 0) {
5299 chk1(c.dic->hasSchemaTrans() == true);
5300 g_info << "begin trans at try " << tries << endl;
5301 break;
5302 }
5303 NdbSleep_MilliSleep(retry.sleep_ms);
5304 }
5305 return 0;
5306 err:
5307 return -1;
5308 }
5309
5310 static int
st_end_trans(ST_Con & c,uint flags)5311 st_end_trans(ST_Con& c, uint flags)
5312 {
5313 g_info << "end trans flags:" << hex << flags << endl;
5314 int res= c.dic->endSchemaTrans(flags);
5315 g_info << "end trans result:" << res << endl;
5316 chk2(res == 0, c.dic->getNdbError());
5317 c.tx_on = false;
5318 c.tx_commit = !(flags & ST_AbortFlag);
5319 st_set_commit_all(c);
5320 return 0;
5321 err:
5322 return -1;
5323 }
5324
5325 static int
st_end_trans_aborted(ST_Con & c,uint flags)5326 st_end_trans_aborted(ST_Con& c, uint flags)
5327 {
5328 g_info << "end trans flags:" << hex << flags << endl;
5329 int res= c.dic->endSchemaTrans(flags);
5330 g_info << "end trans result:" << res << endl;
5331 if (flags & ST_AbortFlag)
5332 chk1(res == 0);
5333 else
5334 chk1(res != 0);
5335 c.tx_on = false;
5336 c.tx_commit = (flags & ST_AbortFlag);
5337 return 0;
5338 err:
5339 return -1;
5340 }
5341
5342 static int
st_end_trans(ST_Con & c,ST_Errins errins,uint flags)5343 st_end_trans(ST_Con& c, ST_Errins errins, uint flags)
5344 {
5345 chk1(st_do_errins(c, errins) == 0);
5346 chk1(st_end_trans(c, flags) == 0);
5347 return 0;
5348 err:
5349 return -1;
5350 }
5351
5352 static int
st_end_trans_aborted(ST_Con & c,ST_Errins errins,uint flags)5353 st_end_trans_aborted(ST_Con& c, ST_Errins errins, uint flags)
5354 {
5355 chk1(st_do_errins(c, errins) == 0);
5356 chk1(st_end_trans_aborted(c, flags) == 0);
5357 return 0;
5358 err:
5359 return -1;
5360 }
5361
5362 static int
st_load_table(ST_Con & c,ST_Tab & tab,int rows=1000)5363 st_load_table(ST_Con& c, ST_Tab& tab, int rows = 1000)
5364 {
5365 g_info << tab.name << ": load data rows:" << rows << endl;
5366 assert(tab.tab_r != 0);
5367 HugoTransactions ht(*tab.tab_r);
5368 chk1(ht.loadTable(c.ndb, rows) == 0);
5369 return 0;
5370 err:
5371 return -1;
5372 }
5373
5374 static int
st_create_table(ST_Con & c,ST_Tab & tab,int code=0)5375 st_create_table(ST_Con& c, ST_Tab& tab, int code = 0)
5376 {
5377 g_info << tab.name << ": create table";
5378 if (code == 0) {
5379 g_info << endl;
5380 assert(!tab.exists());
5381 chk2(c.dic->createTable(*tab.tab) == 0, c.dic->getNdbError());
5382 g_info << tab.name << ": created" << endl;
5383 st_set_create_tab(c, tab, true);
5384 }
5385 else {
5386 g_info << " - expect error " << code << endl;
5387 chk1(c.dic->createTable(*tab.tab) == -1);
5388 const NdbError& error = c.dic->getNdbError();
5389 chk2(error.code == code, error << " wanted: " << code);
5390 }
5391 chk1(st_verify_table(c, tab) == 0);
5392 return 0;
5393 err:
5394 return -1;
5395 }
5396
5397 static int
st_create_table(ST_Con & c,ST_Tab & tab,ST_Errins errins)5398 st_create_table(ST_Con& c, ST_Tab& tab, ST_Errins errins)
5399 {
5400 assert(errins.code != 0);
5401 chk1(st_do_errins(c, errins) == 0);
5402 chk1(st_create_table(c, tab, errins.code) == 0);
5403 return 0;
5404 err:
5405 return -1;
5406 }
5407
5408 static int
st_drop_table(ST_Con & c,ST_Tab & tab,int code=0)5409 st_drop_table(ST_Con& c, ST_Tab& tab, int code = 0)
5410 {
5411 g_info << tab.name << ": drop table";
5412 if (code == 0) {
5413 g_info << endl;
5414 assert(tab.exists());
5415 c.dic->invalidateTable(tab.name);
5416 chk2(c.dic->dropTable(tab.name) == 0, c.dic->getNdbError());
5417 g_info << tab.name << ": dropped" << endl;
5418 st_set_create_tab(c, tab, false);
5419 } else {
5420 g_info << " - expect error " << code << endl;
5421 c.dic->invalidateTable(tab.name);
5422 chk1(c.dic->dropTable(tab.name) == -1);
5423 const NdbError& error = c.dic->getNdbError();
5424 chk2(error.code == code, error << " wanted: " << code);
5425 }
5426 chk1(st_verify_table(c, tab) == 0);
5427 return 0;
5428 err:
5429 return -1;
5430 }
5431
5432 static int
st_drop_table(ST_Con & c,ST_Tab & tab,ST_Errins errins)5433 st_drop_table(ST_Con& c, ST_Tab& tab, ST_Errins errins)
5434 {
5435 assert(errins.code != 0);
5436 chk1(st_do_errins(c, errins) == 0);
5437 chk1(st_drop_table(c, tab, errins.code) == 0);
5438 return 0;
5439 err:
5440 return -1;
5441 }
5442
5443 static int
st_create_index(ST_Con & c,ST_Ind & ind,int code=0)5444 st_create_index(ST_Con& c, ST_Ind& ind, int code = 0)
5445 {
5446 ST_Tab& tab = *ind.tab;
5447 g_info << ind.name << ": create index on "
5448 << tab.name << "(" << ind.colnames.c_str() << ")";
5449 if (code == 0) {
5450 g_info << endl;
5451 assert(!ind.exists());
5452 chk2(c.dic->createIndex(*ind.ind, *tab.tab_r) == 0, c.dic->getNdbError());
5453 st_set_create_ind(c, ind, true);
5454 g_info << ind.name << ": created" << endl;
5455 } else {
5456 g_info << " - expect error " << code << endl;
5457 chk1(c.dic->createIndex(*ind.ind, *tab.tab_r) == -1);
5458 const NdbError& error = c.dic->getNdbError();
5459 chk2(error.code == code, error << " wanted: " << code);
5460 }
5461 chk1(st_verify_index(c, ind) == 0);
5462 return 0;
5463 err:
5464 return -1;
5465 }
5466
5467 static int
st_create_index(ST_Con & c,ST_Ind & ind,ST_Errins errins)5468 st_create_index(ST_Con& c, ST_Ind& ind, ST_Errins errins)
5469 {
5470 assert(errins.code != 0);
5471 chk1(st_do_errins(c, errins) == 0);
5472 chk1(st_create_index(c, ind, errins.code) == 0);
5473 return 0;
5474 err:
5475 return -1;
5476 }
5477
5478 static int
st_drop_index(ST_Con & c,ST_Ind & ind,int code=0)5479 st_drop_index(ST_Con& c, ST_Ind& ind, int code = 0)
5480 {
5481 ST_Tab& tab = *ind.tab;
5482 g_info << ind.name << ": drop index";
5483 if (code == 0) {
5484 g_info << endl;
5485 assert(ind.exists());
5486 c.dic->invalidateIndex(ind.name, tab.name);
5487 chk2(c.dic->dropIndex(ind.name, tab.name) == 0, c.dic->getNdbError());
5488 g_info << ind.name << ": dropped" << endl;
5489 st_set_create_ind(c, ind, false);
5490 } else {
5491 g_info << " expect error " << code << endl;
5492 c.dic->invalidateIndex(ind.name, tab.name);
5493 chk1(c.dic->dropIndex(ind.name, tab.name) == -1);
5494 const NdbError& error = c.dic->getNdbError();
5495 chk2(error.code == code, error << " wanted: " << code);
5496 }
5497 chk1(st_verify_index(c, ind) == 0);
5498 return 0;
5499 err:
5500 return -1;
5501 }
5502
5503 static int
st_drop_index(ST_Con & c,ST_Ind & ind,ST_Errins errins)5504 st_drop_index(ST_Con& c, ST_Ind& ind, ST_Errins errins)
5505 {
5506 assert(errins.code != 0);
5507 chk1(st_do_errins(c, errins) == 0);
5508 chk1(st_drop_index(c, ind, errins.code) == 0);
5509 return 0;
5510 err:
5511 return -1;
5512 }
5513
5514 static int
st_create_table_index(ST_Con & c,ST_Tab & tab)5515 st_create_table_index(ST_Con& c, ST_Tab& tab)
5516 {
5517 chk1(st_create_table(c, tab) == 0);
5518 int j;
5519 for (j = 0; j < tab.indcount; j++) {
5520 ST_Ind& ind = tab.ind(j);
5521 chk1(st_create_index(c, ind) == 0);
5522 }
5523 return 0;
5524 err:
5525 return -1;
5526 }
5527
5528 // drop all
5529
5530 static int
st_drop_test_tables(ST_Con & c)5531 st_drop_test_tables(ST_Con& c)
5532 {
5533 g_info << "st_drop_test_tables" << endl;
5534 int i;
5535 for (i = 0; i < c.tabcount; i++) {
5536 ST_Tab& tab = c.tab(i);
5537 if (tab.exists())
5538 chk1(st_drop_table(c, tab) == 0);
5539 }
5540 return 0;
5541 err:
5542 return -1;
5543 }
5544
5545 // error insert values
5546
5547 static const ST_Errins
5548 st_errins_begin_trans[] = {
5549 ST_Errins(6101, 780),
5550 ST_Errins()
5551 };
5552
5553 static const ST_Errins
5554 st_errins_end_trans1[] = {
5555 ST_Errins(ERR_INSERT_MASTER_FAILURE1, 0, 1),
5556 ST_Errins()
5557 };
5558
5559 static const ST_Errins
5560 st_errins_end_trans2[] = {
5561 ST_Errins(ERR_INSERT_MASTER_FAILURE2, 0, 1),
5562 ST_Errins()
5563 };
5564
5565 static const ST_Errins
5566 st_errins_end_trans3[] = {
5567 ST_Errins(ERR_INSERT_MASTER_FAILURE3, 0, 1),
5568 ST_Errins()
5569 };
5570
5571 static const ST_Errins
5572 st_errins_table[] = {
5573 ST_Errins(6111, 783),
5574 ST_Errins(6121, 9121),
5575 //ST_Errins(6131, 9131),
5576 ST_Errins()
5577 };
5578
5579 static ST_Errins
5580 st_errins_index[] = {
5581 ST_Errins(st_errins_table),
5582 ST_Errins(6112, 783),
5583 ST_Errins(6113, 783),
5584 ST_Errins(6114, 783),
5585 ST_Errins(6122, 9122),
5586 ST_Errins(6123, 9123),
5587 ST_Errins(6124, 9124),
5588 //ST_Errins(6132, 9131),
5589 //ST_Errins(6133, 9131),
5590 //ST_Errins(6134, 9131),
5591 //ST_Errins(6135, 9131),
5592 ST_Errins()
5593 };
5594
5595 static ST_Errins
5596 st_errins_index_create[] = {
5597 ST_Errins(st_errins_index),
5598 ST_Errins(6116, 783),
5599 ST_Errins(6126, 9126),
5600 //ST_Errins(6136, 9136),
5601 ST_Errins()
5602 };
5603
5604 static ST_Errins
5605 st_errins_index_drop[] = {
5606 ST_Errins(st_errins_index),
5607 ST_Errins()
5608 };
5609
5610 // specific test cases
5611
5612 static int
st_test_create(ST_Con & c,int arg=-1)5613 st_test_create(ST_Con& c, int arg = -1)
5614 {
5615 int do_abort = (arg == 1);
5616 int i;
5617 chk1(st_begin_trans(c) == 0);
5618 for (i = 0; i < c.tabcount; i++) {
5619 ST_Tab& tab = c.tab(i);
5620 chk1(st_create_table_index(c, tab) == 0);
5621 }
5622 chk1(st_verify_list(c) == 0);
5623 if (!do_abort)
5624 chk1(st_end_trans(c, 0) == 0);
5625 else
5626 chk1(st_end_trans(c, ST_AbortFlag) == 0);
5627 chk1(st_verify_list(c) == 0);
5628 if (!do_abort)
5629 chk1(st_drop_test_tables(c) == 0);
5630 return NDBT_OK;
5631 err:
5632 return NDBT_FAILED;
5633 }
5634
5635 static int
st_test_drop(ST_Con & c,int arg=-1)5636 st_test_drop(ST_Con& c, int arg = -1)
5637 {
5638 int do_abort = (arg == 1);
5639 int i;
5640 for (i = 0; i < c.tabcount; i++) {
5641 ST_Tab& tab = c.tab(i);
5642 chk1(st_create_table_index(c, tab) == 0);
5643 }
5644 chk1(st_begin_trans(c) == 0);
5645 for (i = 0; i < c.tabcount; i++) {
5646 ST_Tab& tab = c.tab(i);
5647 chk1(st_drop_table(c, tab) == 0);
5648 }
5649 chk1(st_verify_list(c) == 0);
5650 if (!do_abort)
5651 chk1(st_end_trans(c, 0) == 0);
5652 else
5653 chk1(st_end_trans(c, ST_AbortFlag) == 0);
5654 chk1(st_verify_list(c) == 0);
5655 return NDBT_OK;
5656 err:
5657 return NDBT_FAILED;
5658 }
5659
5660 static int
st_test_rollback_create_table(ST_Con & c,int arg=-1)5661 st_test_rollback_create_table(ST_Con& c, int arg = -1)
5662 {
5663 int i;
5664 chk1(st_begin_trans(c) == 0);
5665 for (i = 0; i < c.tabcount; i++) {
5666 ST_Tab& tab = c.tab(i);
5667 if (i % 2 == 0) {
5668 ST_Errins errins(6111, 783, 0); // fail CTa seize op
5669 chk1(st_create_table(c, tab, errins) == 0);
5670 } else {
5671 chk1(st_create_table(c, tab) == 0);
5672 }
5673 }
5674 chk1(st_end_trans(c, 0) == 0);
5675 chk1(st_verify_list(c) == 0);
5676 for (i = 0; i < c.tabcount; i++) {
5677 ST_Tab& tab = c.tab(i);
5678 if (i % 2 == 0)
5679 assert(!tab.exists());
5680 else {
5681 assert(tab.exists());
5682 chk1(st_drop_table(c, tab) == 0);
5683 }
5684 }
5685 return NDBT_OK;
5686 err:
5687 return NDBT_FAILED;
5688 }
5689
5690 static int
st_test_rollback_drop_table(ST_Con & c,int arg=-1)5691 st_test_rollback_drop_table(ST_Con& c, int arg = -1)
5692 {
5693 int i;
5694 for (i = 0; i < c.tabcount; i++) {
5695 ST_Tab& tab = c.tab(i);
5696 chk1(st_create_table(c, tab) == 0);
5697 }
5698 chk1(st_begin_trans(c) == 0);
5699 for (i = 0; i < c.tabcount; i++) {
5700 ST_Tab& tab = c.tab(i);
5701 if (i % 2 == 0) {
5702 ST_Errins errins(6111, 783, 0); // fail DTa seize op
5703 chk1(st_drop_table(c, tab, errins) == 0);
5704 } else {
5705 chk1(st_drop_table(c, tab) == 0);
5706 }
5707 }
5708 chk1(st_end_trans(c, 0) == 0);
5709 chk1(st_verify_list(c) == 0);
5710 for (i = 0; i < c.tabcount; i++) {
5711 ST_Tab& tab = c.tab(i);
5712 if (i % 2 == 0) {
5713 assert(tab.exists());
5714 chk1(st_drop_table(c, tab) == 0);
5715 } else {
5716 assert(!tab.exists());
5717 }
5718 }
5719 return NDBT_OK;
5720 err:
5721 return NDBT_FAILED;
5722 }
5723
5724 static int
st_test_rollback_create_index(ST_Con & c,int arg=-1)5725 st_test_rollback_create_index(ST_Con& c, int arg = -1)
5726 {
5727 int i, j;
5728 for (i = 0; i < c.tabcount; i++) {
5729 ST_Tab& tab = c.tab(i);
5730 if (tab.indcount < 1)
5731 continue;
5732 chk1(st_create_table(c, tab) == 0);
5733 chk1(st_begin_trans(c) == 0);
5734 for (j = 0; j < tab.indcount; j++) {
5735 ST_Ind& ind = tab.ind(j);
5736 if (j % 2 == 0) {
5737 ST_Errins errins(6116, 783, 0); // fail BIn seize op
5738 chk1(st_create_index(c, ind, errins) == 0);
5739 } else {
5740 chk1(st_create_index(c, ind) == 0);
5741 }
5742 }
5743 chk1(st_end_trans(c, 0) == 0);
5744 chk1(st_verify_list(c) == 0);
5745 for (j = 0; j < tab.indcount; j++) {
5746 ST_Ind& ind = tab.ind(j);
5747 if (j % 2 == 0)
5748 assert(!ind.exists());
5749 else {
5750 assert(ind.exists());
5751 chk1(st_drop_index(c, ind) == 0);
5752 }
5753 }
5754 chk1(st_drop_table(c, tab) == 0);
5755 }
5756 return NDBT_OK;
5757 err:
5758 return NDBT_FAILED;
5759 }
5760
5761 static int
st_test_rollback_drop_index(ST_Con & c,int arg=-1)5762 st_test_rollback_drop_index(ST_Con& c, int arg = -1)
5763 {
5764 int i, j;
5765 for (i = 0; i < c.tabcount; i++) {
5766 ST_Tab& tab = c.tab(i);
5767 if (tab.indcount < 1)
5768 continue;
5769 chk1(st_create_table_index(c, tab) == 0);
5770 }
5771 for (i = 0; i < c.tabcount; i++) {
5772 ST_Tab& tab = c.tab(i);
5773 if (tab.indcount < 1)
5774 continue;
5775 chk1(st_begin_trans(c) == 0);
5776 for (j = 0; j < tab.indcount; j++) {
5777 ST_Ind& ind = tab.ind(j);
5778 if (j % 2 == 0) {
5779 ST_Errins errins(6114, 783, 0); // fail ATr seize op
5780 chk1(st_drop_index(c, ind, errins) == 0);
5781 } else {
5782 chk1(st_drop_index(c, ind) == 0);
5783 }
5784 }
5785 chk1(st_end_trans(c, 0) == 0);
5786 chk1(st_verify_list(c) == 0);
5787 for (j = 0; j < tab.indcount; j++) {
5788 ST_Ind& ind = tab.ind(j);
5789 if (j % 2 == 0) {
5790 assert(ind.exists());
5791 chk1(st_drop_index(c, ind) == 0);
5792 } else {
5793 assert(!ind.exists());
5794 }
5795 }
5796 }
5797 return NDBT_OK;
5798 err:
5799 return NDBT_FAILED;
5800 }
5801
5802 static int
st_test_dup_create_table(ST_Con & c,int arg=-1)5803 st_test_dup_create_table(ST_Con& c, int arg = -1)
5804 {
5805 int do_trans;
5806 int do_abort;
5807 int i;
5808 for (do_trans = 0; do_trans <= 1; do_trans++) {
5809 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
5810 g_info << "trans:" << do_trans
5811 << " abort:" << do_abort << endl;
5812 for (i = 0; i < c.tabcount; i++) {
5813 ST_Tab& tab = c.tab(i);
5814 if (do_trans)
5815 chk1(st_begin_trans(c) == 0);
5816 chk1(st_create_table(c, tab) == 0);
5817 chk1(st_create_table(c, tab, 721) == 0);
5818 if (do_trans) {
5819 if (!do_abort)
5820 chk1(st_end_trans(c, 0) == 0);
5821 else
5822 chk1(st_end_trans(c, ST_AbortFlag) == 0);
5823 }
5824 chk1(st_verify_list(c) == 0);
5825 if (tab.exists()) {
5826 chk1(st_drop_table(c, tab) == 0);
5827 }
5828 }
5829 }
5830 }
5831 return NDBT_OK;
5832 err:
5833 return NDBT_FAILED;
5834 }
5835
5836 static int
st_test_dup_drop_table(ST_Con & c,int arg=-1)5837 st_test_dup_drop_table(ST_Con& c, int arg = -1)
5838 {
5839 int do_trans;
5840 int do_abort;
5841 int i;
5842 for (do_trans = 0; do_trans <= 1; do_trans++) {
5843 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
5844 g_info << "trans:" << do_trans
5845 << " abort:" << do_abort << endl;
5846 for (i = 0; i < c.tabcount; i++) {
5847 ST_Tab& tab = c.tab(i);
5848 chk1(st_create_table(c, tab) == 0);
5849 if (do_trans)
5850 chk1(st_begin_trans(c) == 0);
5851 chk1(st_drop_table(c, tab) == 0);
5852 if (!do_trans)
5853 chk1(st_drop_table(c, tab, 723) == 0);
5854 else
5855 chk1(st_drop_table(c, tab, 785) == 0);
5856 if (do_trans) {
5857 if (!do_abort)
5858 chk1(st_end_trans(c, 0) == 0);
5859 else
5860 chk1(st_end_trans(c, ST_AbortFlag) == 0);
5861 }
5862 chk1(st_verify_list(c) == 0);
5863 if (tab.exists()) {
5864 chk1(st_drop_table(c, tab) == 0);
5865 }
5866 }
5867 }
5868 }
5869 return NDBT_OK;
5870 err:
5871 return NDBT_FAILED;
5872 }
5873
5874 static int
st_test_dup_create_index(ST_Con & c,int arg=-1)5875 st_test_dup_create_index(ST_Con& c, int arg = -1)
5876 {
5877 int do_trans;
5878 int do_abort;
5879 int i, j;
5880 for (do_trans = 0; do_trans <= 1; do_trans++) {
5881 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
5882 g_info << "trans:" << do_trans
5883 << " abort:" << do_abort << endl;
5884 for (i = 0; i < c.tabcount; i++) {
5885 ST_Tab& tab = c.tab(i);
5886 if (tab.indcount < 1)
5887 continue;
5888 chk1(st_create_table(c, tab) == 0);
5889 for (j = 0; j < tab.indcount; j++) {
5890 ST_Ind& ind = tab.ind(j);
5891 if (do_trans)
5892 chk1(st_begin_trans(c) == 0);
5893 chk1(st_create_index(c, ind) == 0);
5894 chk1(st_create_index(c, ind, 721) == 0);
5895 if (do_trans) {
5896 if (!do_abort)
5897 chk1(st_end_trans(c, 0) == 0);
5898 else
5899 chk1(st_end_trans(c, ST_AbortFlag) == 0);
5900 }
5901 chk1(st_verify_list(c) == 0);
5902 }
5903 chk1(st_drop_table(c, tab) == 0);
5904 }
5905 }
5906 }
5907 return NDBT_OK;
5908 err:
5909 return NDBT_FAILED;
5910 }
5911
5912 static int
st_test_dup_drop_index(ST_Con & c,int arg=-1)5913 st_test_dup_drop_index(ST_Con& c, int arg = -1)
5914 {
5915 int do_trans;
5916 int do_abort;
5917 int i, j;
5918 for (do_trans = 0; do_trans <= 1; do_trans++) {
5919 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
5920 g_info << "trans:" << do_trans
5921 << " abort:" << do_abort << endl;
5922 for (i = 0; i < c.tabcount; i++) {
5923 ST_Tab& tab = c.tab(i);
5924 if (tab.indcount < 1)
5925 continue;
5926 chk1(st_create_table(c, tab) == 0);
5927 for (j = 0; j < tab.indcount; j++) {
5928 ST_Ind& ind = tab.ind(j);
5929 chk1(st_create_index(c, ind) == 0);
5930 if (do_trans)
5931 chk1(st_begin_trans(c) == 0);
5932 chk1(st_drop_index(c, ind) == 0);
5933 if (!do_trans)
5934 chk1(st_drop_index(c, ind, 4243) == 0);
5935 else
5936 chk1(st_drop_index(c, ind, 785) == 0);
5937 if (do_trans) {
5938 if (!do_abort)
5939 chk1(st_end_trans(c, 0) == 0);
5940 else
5941 chk1(st_end_trans(c, ST_AbortFlag) == 0);
5942 }
5943 chk1(st_verify_list(c) == 0);
5944 }
5945 chk1(st_drop_table(c, tab) == 0);
5946 }
5947 }
5948 }
5949 return NDBT_OK;
5950 err:
5951 return NDBT_FAILED;
5952 }
5953
5954 static int
st_test_build_index(ST_Con & c,int arg=-1)5955 st_test_build_index(ST_Con& c, int arg = -1)
5956 {
5957 int i, j;
5958 for (i = 0; i < c.tabcount; i++) {
5959 ST_Tab& tab = c.tab(i);
5960 if (tab.indcount < 1)
5961 continue;
5962 chk1(st_create_table(c, tab) == 0);
5963 chk1(st_load_table(c, tab) == 0);
5964 for (j = 0; j < tab.indcount; j++) {
5965 ST_Ind& ind = tab.ind(j);
5966 chk1(st_create_index(c, ind) == 0);
5967 chk1(st_verify_list(c) == 0);
5968 }
5969 chk1(st_drop_table(c, tab) == 0);
5970 }
5971 return NDBT_OK;
5972 err:
5973 return NDBT_FAILED;
5974 }
5975
5976 static ST_Errins
5977 st_test_local_create_list[] = {
5978 ST_Errins(8033, 293, 1), // TC trigger
5979 ST_Errins(8033, 293, 0),
5980 ST_Errins(4003, 4237, 1), // TUP trigger
5981 ST_Errins(4003, 4237, 0),
5982 ST_Errins(8034, 292, 1), // TC index
5983 ST_Errins(8034, 292, 0)
5984 };
5985
5986 static int
st_test_local_create(ST_Con & c,int arg=-1)5987 st_test_local_create(ST_Con& c, int arg = -1)
5988 {
5989 const int n = arg;
5990 ST_Errins *list = st_test_local_create_list;
5991 const int listlen =
5992 sizeof(st_test_local_create_list)/sizeof(st_test_local_create_list[0]);
5993 assert(0 <= n && n < listlen);
5994 const bool only_unique = (n == 0 || n == 1 || n == 4 || n == 5);
5995 int i, j;
5996 for (i = 0; i < c.tabcount; i++) {
5997 ST_Tab& tab = c.tab(i);
5998 bool tabdone = false;
5999 for (j = 0; j < tab.indcount; j++) {
6000 ST_Ind& ind = tab.ind(j);
6001 if (only_unique && !ind.is_unique())
6002 continue;
6003 if (!tabdone) {
6004 chk1(st_create_table(c, tab) == 0);
6005 chk1(st_load_table(c, tab) == 0);
6006 tabdone = true;
6007 }
6008 ST_Errins errins = list[n];
6009 chk1(st_create_index(c, ind, errins) == 0);
6010 chk1(st_verify_list(c) == 0);
6011 }
6012 if (tabdone)
6013 chk1(st_drop_table(c, tab) == 0);
6014 }
6015 return NDBT_OK;
6016 err:
6017 return NDBT_FAILED;
6018 }
6019
6020 // random test cases
6021
6022 static const uint ST_AllowAbort = 1;
6023 static const uint ST_AllowErrins = 2;
6024
6025 static int
st_test_trans(ST_Con & c,int arg=-1)6026 st_test_trans(ST_Con& c, int arg = -1)
6027 {
6028 if ((arg & ST_AllowErrins) && randomly(2, 3)) {
6029 ST_Errins errins = st_get_errins(c, st_errins_begin_trans);
6030 chk1(st_begin_trans(c, errins) == 0);
6031 } else {
6032 chk1(st_begin_trans(c) == 0);
6033 if (randomly(1, 5)) {
6034 g_info << "try duplicate begin trans" << endl;
6035 chk1(st_begin_trans(c, 4410) == 0);
6036 chk1(c.dic->hasSchemaTrans() == true);
6037 }
6038 if ((arg & ST_AllowAbort) && randomly(1, 3)) {
6039 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6040 } else {
6041 chk1(st_end_trans(c, 0) == 0);
6042 }
6043 }
6044 return NDBT_OK;
6045 err:
6046 return NDBT_FAILED;
6047 }
6048
6049 static int
st_test_create_table(ST_Con & c,int arg=-1)6050 st_test_create_table(ST_Con& c, int arg = -1)
6051 {
6052 bool trans = randomly(3, 4);
6053 bool simpletrans = !trans && randomly(1, 2);
6054 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6055 if (trans) {
6056 chk1(st_begin_trans(c) == 0);
6057 }
6058 int i;
6059 for (i = 0; i < c.tabcount; i++) {
6060 ST_Tab& tab = c.tab(i);
6061 if (tab.exists()) {
6062 g_info << tab.name << ": skip existing" << endl;
6063 continue;
6064 }
6065 g_info << tab.name << ": to create" << endl;
6066 if (simpletrans) {
6067 chk1(st_begin_trans(c) == 0);
6068 }
6069 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6070 ST_Errins errins = st_get_errins(c, st_errins_table);
6071 chk1(st_create_table(c, tab, errins) == 0);
6072 if (simpletrans) {
6073 if (randomly(1, 2))
6074 chk1(st_end_trans(c, 0) == 0);
6075 else
6076 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6077 }
6078 } else {
6079 chk1(st_create_table(c, tab) == 0);
6080 if (simpletrans) {
6081 uint flags = 0;
6082 if ((arg & ST_AllowAbort) && randomly(4, 5))
6083 flags |= ST_AbortFlag;
6084 chk1(st_end_trans(c, flags) == 0);
6085 }
6086 }
6087 if (tab.exists() && randomly(1, 3)) {
6088 g_info << tab.name << ": try duplicate create" << endl;
6089 chk1(st_create_table(c, tab, 721) == 0);
6090 }
6091 }
6092 if (trans) {
6093 uint flags = 0;
6094 if ((arg & ST_AllowAbort) && randomly(4, 5))
6095 flags |= ST_AbortFlag;
6096 chk1(st_end_trans(c, flags) == 0);
6097 }
6098 return NDBT_OK;
6099 err:
6100 return NDBT_FAILED;
6101 }
6102
6103 static int
st_test_drop_table(ST_Con & c,int arg=-1)6104 st_test_drop_table(ST_Con& c, int arg = -1)
6105 {
6106 bool trans = randomly(3, 4);
6107 bool simpletrans = !trans && randomly(1, 2);
6108 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6109 if (trans) {
6110 chk1(st_begin_trans(c) == 0);
6111 }
6112 int i;
6113 for (i = 0; i < c.tabcount; i++) {
6114 ST_Tab& tab = c.tab(i);
6115 if (!tab.exists()) {
6116 g_info << tab.name << ": skip not existing" << endl;
6117 continue;
6118 }
6119 g_info << tab.name << ": to drop" << endl;
6120 if (simpletrans) {
6121 chk1(st_begin_trans(c) == 0);
6122 }
6123 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6124 ST_Errins errins = st_get_errins(c, st_errins_table);
6125 chk1(st_drop_table(c, tab, errins) == 0);
6126 if (simpletrans) {
6127 if (randomly(1, 2))
6128 chk1(st_end_trans(c, 0) == 0);
6129 else
6130 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6131 }
6132 } else {
6133 chk1(st_drop_table(c, tab) == 0);
6134 if (simpletrans) {
6135 uint flags = 0;
6136 if ((arg & ST_AllowAbort) && randomly(4, 5))
6137 flags |= ST_AbortFlag;
6138 chk1(st_end_trans(c, flags) == 0);
6139 }
6140 }
6141 if (!tab.exists() && randomly(1, 3)) {
6142 g_info << tab.name << ": try duplicate drop" << endl;
6143 chk1(st_drop_table(c, tab, 723) == 0);
6144 }
6145 }
6146 if (trans) {
6147 uint flags = 0;
6148 if ((arg & ST_AllowAbort) && randomly(4, 5))
6149 flags |= ST_AbortFlag;
6150 chk1(st_end_trans(c, flags) == 0);
6151 }
6152 return NDBT_OK;
6153 err:
6154 return NDBT_FAILED;
6155 }
6156
6157 static int
st_test_table(ST_Con & c,int arg=-1)6158 st_test_table(ST_Con& c, int arg = -1)
6159 {
6160 chk1(st_test_create_table(c) == NDBT_OK);
6161 chk1(st_test_drop_table(c) == NDBT_OK);
6162 return NDBT_OK;
6163 err:
6164 return NDBT_FAILED;
6165 }
6166
6167 static int
st_test_create_index(ST_Con & c,int arg=-1)6168 st_test_create_index(ST_Con& c, int arg = -1)
6169 {
6170 bool trans = randomly(3, 4);
6171 bool simpletrans = !trans && randomly(1, 2);
6172 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6173 if (trans) {
6174 chk1(st_begin_trans(c) == 0);
6175 }
6176 int i, j;
6177 for (i = 0; i < c.tabcount; i++) {
6178 ST_Tab& tab = c.tab(i);
6179 if (tab.indcount == 0)
6180 continue;
6181 if (!tab.exists()) {
6182 g_info << tab.name << ": to create" << endl;
6183 chk1(st_create_table(c, tab) == 0);
6184 }
6185 for (j = 0; j < tab.indcount; j++) {
6186 ST_Ind& ind = tab.ind(j);
6187 if (ind.exists()) {
6188 g_info << ind.name << ": skip existing" << endl;
6189 continue;
6190 }
6191 g_info << ind.name << ": to create" << endl;
6192 if (simpletrans) {
6193 chk1(st_begin_trans(c) == 0);
6194 }
6195 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6196 const ST_Errins* list = st_errins_index_create;
6197 ST_Errins errins = st_get_errins(c, list);
6198 chk1(st_create_index(c, ind, errins) == 0);
6199 if (simpletrans) {
6200 if (randomly(1, 2))
6201 chk1(st_end_trans(c, 0) == 0);
6202 else
6203 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6204 }
6205 } else {
6206 chk1(st_create_index(c, ind) == 0);
6207 if (simpletrans) {
6208 uint flags = 0;
6209 if ((arg & ST_AllowAbort) && randomly(4, 5))
6210 flags |= ST_AbortFlag;
6211 chk1(st_end_trans(c, flags) == 0);
6212 }
6213 }
6214 if (ind.exists() && randomly(1, 3)) {
6215 g_info << ind.name << ": try duplicate create" << endl;
6216 chk1(st_create_index(c, ind, 721) == 0);
6217 }
6218 }
6219 }
6220 if (trans) {
6221 uint flags = 0;
6222 if ((arg & ST_AllowAbort) && randomly(4, 5))
6223 flags |= ST_AbortFlag;
6224 chk1(st_end_trans(c, flags) == 0);
6225 }
6226 return NDBT_OK;
6227 err:
6228 return NDBT_FAILED;
6229 }
6230
6231 static int
st_test_drop_index(ST_Con & c,int arg=-1)6232 st_test_drop_index(ST_Con& c, int arg = -1)
6233 {
6234 bool trans = randomly(3, 4);
6235 bool simpletrans = !trans && randomly(1, 2);
6236 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6237 if (trans) {
6238 chk1(st_begin_trans(c) == 0);
6239 }
6240 int i, j;
6241 for (i = 0; i < c.tabcount; i++) {
6242 ST_Tab& tab = c.tab(i);
6243 if (tab.indcount == 0)
6244 continue;
6245 if (!tab.exists()) {
6246 g_info << tab.name << ": skip not existing" << endl;
6247 continue;
6248 }
6249 for (j = 0; j < tab.indcount; j++) {
6250 ST_Ind& ind = tab.ind(j);
6251 if (!ind.exists()) {
6252 g_info << ind.name << ": skip not existing" << endl;
6253 continue;
6254 }
6255 g_info << ind.name << ": to drop" << endl;
6256 if (simpletrans) {
6257 chk1(st_begin_trans(c) == 0);
6258 }
6259 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6260 const ST_Errins* list = st_errins_index_drop;
6261 ST_Errins errins = st_get_errins(c, list);
6262 chk1(st_drop_index(c, ind, errins) == 0);
6263 if (simpletrans) {
6264 if (randomly(1, 2))
6265 chk1(st_end_trans(c, 0) == 0);
6266 else
6267 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6268 }
6269 } else {
6270 chk1(st_drop_index(c, ind) == 0);
6271 if (simpletrans) {
6272 uint flags = 0;
6273 if ((arg & ST_AllowAbort) && randomly(4, 5))
6274 flags |= ST_AbortFlag;
6275 chk1(st_end_trans(c, flags) == 0);
6276 }
6277 }
6278 if (!ind.exists() && randomly(1, 3)) {
6279 g_info << ind.name << ": try duplicate drop" << endl;
6280 chk1(st_drop_index(c, ind, 4243) == 0);
6281 }
6282 }
6283 }
6284 if (trans) {
6285 uint flags = 0;
6286 if ((arg & ST_AllowAbort) && randomly(4, 5))
6287 flags |= ST_AbortFlag;
6288 chk1(st_end_trans(c, flags) == 0);
6289 }
6290 return NDBT_OK;
6291 err:
6292 return NDBT_FAILED;
6293 }
6294
6295 static int
st_test_index(ST_Con & c,int arg=-1)6296 st_test_index(ST_Con& c, int arg = -1)
6297 {
6298 chk1(st_test_create_index(c) == NDBT_OK);
6299 chk1(st_test_drop_index(c) == NDBT_OK);
6300 return NDBT_OK;
6301 err:
6302 return NDBT_FAILED;
6303 }
6304
6305 // node failure and system restart
6306
6307 static int
st_test_anf_parse(ST_Con & c,int arg=-1)6308 st_test_anf_parse(ST_Con& c, int arg = -1)
6309 {
6310 int i;
6311 chk1(st_start_xcon(c) == 0);
6312 {
6313 ST_Con& xc = *c.xcon;
6314 chk1(st_begin_trans(xc) == 0);
6315 for (i = 0; i < c.tabcount; i++) {
6316 ST_Tab& tab = c.tab(i);
6317 chk1(st_create_table_index(xc, tab) == 0);
6318 }
6319 // DICT aborts the trans
6320 xc.tx_on = false;
6321 xc.tx_commit = false;
6322 st_set_commit_all(xc);
6323 chk1(st_stop_xcon(c) == 0);
6324 chk1(st_wait_idle(c) == 0);
6325 chk1(st_verify_list(c) == 0);
6326 }
6327 return NDBT_OK;
6328 err:
6329 return NDBT_FAILED;
6330 }
6331
6332 static int
st_test_anf_background(ST_Con & c,int arg=-1)6333 st_test_anf_background(ST_Con& c, int arg = -1)
6334 {
6335 int i;
6336 chk1(st_start_xcon(c) == 0);
6337 {
6338 ST_Con& xc = *c.xcon;
6339 chk1(st_begin_trans(xc) == 0);
6340 for (i = 0; i < c.tabcount; i++) {
6341 ST_Tab& tab = c.tab(i);
6342 chk1(st_create_table(xc, tab) == 0);
6343 }
6344 // DICT takes over and completes the trans
6345 st_end_trans(xc, ST_BackgroundFlag);
6346 chk1(st_stop_xcon(c) == 0);
6347 chk1(st_wait_idle(c) == 0);
6348 chk1(st_verify_list(c) == 0);
6349 }
6350 return NDBT_OK;
6351 err:
6352 return NDBT_FAILED;
6353 }
6354
6355 static int
st_test_anf_fail_begin(ST_Con & c,int arg=-1)6356 st_test_anf_fail_begin(ST_Con& c, int arg = -1)
6357 {
6358 chk1(st_start_xcon(c) == 0);
6359 {
6360 ST_Con& xc = *c.xcon;
6361
6362 ST_Errins errins1(6102, -1, 1); // master kills us at begin
6363 ST_Errins errins2(6103, -1, 0); // slave delays conf
6364 chk1(st_do_errins(xc, errins1) == 0);
6365 chk1(st_do_errins(xc, errins2) == 0);
6366
6367 chk1(st_begin_trans(xc, 4009) == 0);
6368
6369 // DICT aborts the trans
6370 xc.tx_on = false;
6371 xc.tx_commit = false;
6372 st_set_commit_all(xc);
6373 chk1(st_stop_xcon(c) == 0);
6374
6375 // xc may get 4009 before takeover is ready (5000 ms delay)
6376 ST_Retry retry = { 100, 100 }; // 100 * 100ms = 10000ms
6377 chk1(st_begin_trans(c, retry) == 0);
6378 chk1(st_wait_idle(c) == 0);
6379 chk1(st_verify_list(c) == 0);
6380 }
6381 return NDBT_OK;
6382 err:
6383 return NDBT_FAILED;
6384 }
6385
6386 static int
st_test_snf_parse(ST_Con & c,int arg=-1)6387 st_test_snf_parse(ST_Con& c, int arg = -1)
6388 {
6389 bool do_abort = (arg == 1);
6390 chk1(st_begin_trans(c) == 0);
6391 int node_id;
6392 node_id = -1;
6393 int i;
6394 int midcount;
6395 midcount = c.tabcount / 2;
6396
6397 for (i = 0; i < c.tabcount; i++) {
6398 ST_Tab& tab = c.tab(i);
6399 if (i == midcount) {
6400 assert(c.numdbnodes > 1);
6401 uint rand = urandom(c.numdbnodes);
6402 node_id = c.restarter->getRandomNotMasterNodeId(rand);
6403 g_info << "restart node " << node_id << " (async)" << endl;
6404 int flags = 0;
6405 chk1(c.restarter->restartOneDbNode2(node_id, flags) == 0);
6406 chk1(c.restarter->waitNodesNoStart(&node_id, 1) == 0);
6407 chk1(c.restarter->startNodes(&node_id, 1) == 0);
6408 }
6409 chk1(st_create_table_index(c, tab) == 0);
6410 }
6411 if (!do_abort)
6412 chk1(st_end_trans(c, 0) == 0);
6413 else
6414 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6415
6416 g_info << "wait for node " << node_id << " to come up" << endl;
6417 chk1(c.restarter->waitClusterStarted() == 0);
6418 g_info << "verify all" << endl;
6419 chk1(st_verify_all(c) == 0);
6420 return NDBT_OK;
6421 err:
6422 return NDBT_FAILED;
6423 }
6424
6425 static int
st_test_mnf_parse(ST_Con & c,int arg=-1)6426 st_test_mnf_parse(ST_Con& c, int arg = -1)
6427 {
6428 const NdbDictionary::Table* pTab;
6429 bool do_abort = (arg == 1);
6430 chk1(st_begin_trans(c) == 0);
6431 int node_id;
6432 node_id = -1;
6433 int i;
6434 int midcount;
6435 midcount = c.tabcount / 2;
6436
6437 for (i = 0; i < c.tabcount; i++) {
6438 ST_Tab& tab = c.tab(i);
6439 chk1(st_create_table_index(c, tab) == 0);
6440 if (i == midcount) {
6441 assert(c.numdbnodes > 1);
6442 node_id = c.restarter->getMasterNodeId();
6443 g_info << "restart node " << node_id << " (async)" << endl;
6444 int flags = 0;
6445 chk1(c.restarter->restartOneDbNode2(node_id, flags) == 0);
6446 chk1(c.restarter->waitNodesNoStart(&node_id, 1) == 0);
6447 chk1(c.restarter->startNodes(&node_id, 1) == 0);
6448 break;
6449 }
6450 }
6451 if (!do_abort)
6452 chk1(st_end_trans_aborted(c, ST_CommitFlag) == 0);
6453 else
6454 chk1(st_end_trans_aborted(c, ST_AbortFlag) == 0);
6455
6456 g_info << "wait for node " << node_id << " to come up" << endl;
6457 chk1(c.restarter->waitClusterStarted() == 0);
6458 g_info << "verify all" << endl;
6459 for (i = 0; i < c.tabcount; i++) {
6460 ST_Tab& tab = c.tab(i);
6461 // Verify that table is not in db
6462 c.dic->invalidateTable(tab.name);
6463 pTab =
6464 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
6465 chk1(pTab == NULL);
6466 }
6467 /*
6468 chk1(st_verify_all(c) == 0);
6469 */
6470 return NDBT_OK;
6471 err:
6472 return NDBT_FAILED;
6473 }
6474
6475 static int
st_test_mnf_prepare(ST_Con & c,int arg=-1)6476 st_test_mnf_prepare(ST_Con& c, int arg = -1)
6477 {
6478 NdbRestarter restarter;
6479 //int master = restarter.getMasterNodeId();
6480 ST_Errins errins = st_get_errins(c, st_errins_end_trans1);
6481 int i;
6482
6483 chk1(st_begin_trans(c) == 0);
6484 for (i = 0; i < c.tabcount; i++) {
6485 ST_Tab& tab = c.tab(i);
6486 chk1(st_create_table_index(c, tab) == 0);
6487 }
6488 if (arg == 1)
6489 {
6490 chk1(st_end_trans_aborted(c, errins, ST_BackgroundFlag) == 0);
6491 chk1(st_wait_idle(c) == 0);
6492 }
6493 else
6494 chk1(st_end_trans_aborted(c, errins, ST_CommitFlag) == 0);
6495 chk1(c.restarter->waitClusterStarted() == 0);
6496 //st_wait_db_node_up(c, master);
6497 for (i = 0; i < c.tabcount; i++) {
6498 ST_Tab& tab = c.tab(i);
6499 // Verify that table is not in db
6500 c.dic->invalidateTable(tab.name);
6501 const NdbDictionary::Table* pTab =
6502 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
6503 chk1(pTab == NULL);
6504 }
6505 return NDBT_OK;
6506 err:
6507 return NDBT_FAILED;
6508 }
6509
6510 static int
st_test_mnf_commit1(ST_Con & c,int arg=-1)6511 st_test_mnf_commit1(ST_Con& c, int arg = -1)
6512 {
6513 NdbRestarter restarter;
6514 //int master = restarter.getMasterNodeId();
6515 ST_Errins errins = st_get_errins(c, st_errins_end_trans2);
6516 int i;
6517
6518 chk1(st_begin_trans(c) == 0);
6519 for (i = 0; i < c.tabcount; i++) {
6520 ST_Tab& tab = c.tab(i);
6521 chk1(st_create_table_index(c, tab) == 0);
6522 }
6523 if (arg == 1)
6524 {
6525 chk1(st_end_trans(c, errins, ST_BackgroundFlag) == 0);
6526 chk1(st_wait_idle(c) == 0);
6527 }
6528 else
6529 chk1(st_end_trans(c, errins, ST_CommitFlag) == 0);
6530 chk1(c.restarter->waitClusterStarted() == 0);
6531 //st_wait_db_node_up(c, master);
6532 for (i = 0; i < c.tabcount; i++) {
6533 ST_Tab& tab = c.tab(i);
6534 chk1(st_verify_table(c, tab) == 0);
6535 }
6536 chk1(st_drop_test_tables(c) == 0);
6537 return NDBT_OK;
6538 err:
6539 return NDBT_FAILED;
6540 }
6541
6542 static int
st_test_mnf_commit2(ST_Con & c,int arg=-1)6543 st_test_mnf_commit2(ST_Con& c, int arg = -1)
6544 {
6545 NdbRestarter restarter;
6546 //int master = restarter.getMasterNodeId();
6547 ST_Errins errins = st_get_errins(c, st_errins_end_trans3);
6548 int i;
6549
6550 chk1(st_begin_trans(c) == 0);
6551 for (i = 0; i < c.tabcount; i++) {
6552 ST_Tab& tab = c.tab(i);
6553 chk1(st_create_table_index(c, tab) == 0);
6554 }
6555 if (arg == 1)
6556 {
6557 chk1(st_end_trans(c, errins, ST_BackgroundFlag) == 0);
6558 chk1(st_wait_idle(c) == 0);
6559 }
6560 else
6561 chk1(st_end_trans(c, errins, ST_CommitFlag) == 0);
6562 chk1(c.restarter->waitClusterStarted() == 0);
6563 //st_wait_db_node_up(c, master);
6564 chk1(st_verify_all(c) == 0);
6565 for (i = 0; i < c.tabcount; i++) {
6566 ST_Tab& tab = c.tab(i);
6567 chk1(st_load_table(c, tab) == 0);
6568 }
6569 chk1(st_drop_test_tables(c) == 0);
6570 return NDBT_OK;
6571 err:
6572 return NDBT_FAILED;
6573 }
6574
6575 static int
st_test_mnf_run_commit(ST_Con & c,int arg=-1)6576 st_test_mnf_run_commit(ST_Con& c, int arg = -1)
6577 {
6578 const NdbDictionary::Table* pTab;
6579 NdbRestarter restarter;
6580 //int master = restarter.getMasterNodeId();
6581 int i;
6582
6583 if (arg == FAIL_BEGIN)
6584 {
6585 // No transaction to be found if only one node left
6586 if (restarter.getNumDbNodes() < 3)
6587 return NDBT_OK;
6588 chk1(st_begin_trans(c) == -1);
6589 goto verify;
6590 }
6591 else
6592 chk1(st_begin_trans(c) == 0);
6593 for (i = 0; i < c.tabcount; i++) {
6594 ST_Tab& tab = c.tab(i);
6595 if (arg == FAIL_CREATE)
6596 {
6597 chk1(st_create_table_index(c, tab) == -1);
6598 goto verify;
6599 }
6600 else
6601 chk1(st_create_table_index(c, tab) == 0);
6602 }
6603 if (arg == FAIL_END)
6604 {
6605 chk1(st_end_trans(c, ST_CommitFlag) == -1);
6606 }
6607 else // if (arg == SUCCEED_COMMIT)
6608 chk1(st_end_trans(c, ST_CommitFlag) == 0);
6609
6610 verify:
6611 g_info << "wait for master node to come up" << endl;
6612 chk1(c.restarter->waitClusterStarted() == 0);
6613 //st_wait_db_node_up(c, master);
6614 g_info << "verify all" << endl;
6615 for (i = 0; i < c.tabcount; i++) {
6616 ST_Tab& tab = c.tab(i);
6617 switch (arg) {
6618 case FAIL_BEGIN:
6619 case FAIL_CREATE:
6620 case FAIL_END:
6621 {
6622 // Verify that table is not in db
6623 c.dic->invalidateTable(tab.name);
6624 pTab =
6625 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
6626 chk1(pTab == NULL);
6627 break;
6628 }
6629 default:
6630 chk1(st_verify_table(c, tab) == 0);
6631 }
6632 }
6633
6634 return NDBT_OK;
6635 err:
6636 return NDBT_FAILED;
6637 }
6638
6639 static int
st_test_mnf_run_abort(ST_Con & c,int arg=-1)6640 st_test_mnf_run_abort(ST_Con& c, int arg = -1)
6641 {
6642 NdbRestarter restarter;
6643 //int master = restarter.getMasterNodeId();
6644 const NdbDictionary::Table* pTab;
6645 bool do_abort = (arg == SUCCEED_ABORT);
6646 int i;
6647
6648 chk1(st_begin_trans(c) == 0);
6649 for (i = 0; i < c.tabcount; i++) {
6650 ST_Tab& tab = c.tab(i);
6651 chk1(st_create_table_index(c, tab) == 0);
6652 }
6653 if (!do_abort)
6654 chk1(st_end_trans(c, ST_CommitFlag) == -1);
6655 else
6656 chk1(st_end_trans_aborted(c, ST_AbortFlag) == 0);
6657
6658 g_info << "wait for master node to come up" << endl;
6659 chk1(c.restarter->waitClusterStarted() == 0);
6660 //st_wait_db_node_up(c, master);
6661 g_info << "verify all" << endl;
6662 for (i = 0; i < c.tabcount; i++) {
6663 ST_Tab& tab = c.tab(i);
6664 // Verify that table is not in db
6665 c.dic->invalidateTable(tab.name);
6666 pTab =
6667 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
6668 chk1(pTab == NULL);
6669 }
6670
6671 return NDBT_OK;
6672 err:
6673 return NDBT_FAILED;
6674 }
6675
6676 static int
st_test_mnf_start_partial(ST_Con & c,int arg=-1)6677 st_test_mnf_start_partial(ST_Con& c, int arg = -1)
6678 {
6679 ST_Errins errins(ERR_INSERT_PARTIAL_START_FAIL, 0, 1); // slave skips start
6680 chk1(st_do_errins(c, errins) == 0);
6681 return st_test_mnf_run_commit(c, arg);
6682 err:
6683 return -1;
6684 }
6685
6686 static int
st_test_mnf_parse_partial(ST_Con & c,int arg=-1)6687 st_test_mnf_parse_partial(ST_Con& c, int arg = -1)
6688 {
6689 ST_Errins errins(ERR_INSERT_PARTIAL_PARSE_FAIL, 0, 1); // slave skips parse
6690 chk1(st_do_errins(c, errins) == 0);
6691 return st_test_mnf_run_commit(c, arg);
6692 err:
6693 return -1;
6694 }
6695
6696 static int
st_test_mnf_flush_prepare_partial(ST_Con & c,int arg=-1)6697 st_test_mnf_flush_prepare_partial(ST_Con& c, int arg = -1)
6698 {
6699 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_PREPARE_FAIL, 0, 1); // slave skips flush prepare
6700 chk1(st_do_errins(c, errins) == 0);
6701 return st_test_mnf_run_commit(c, arg);
6702 err:
6703 return -1;
6704 }
6705
6706 static int
st_test_mnf_prepare_partial(ST_Con & c,int arg=-1)6707 st_test_mnf_prepare_partial(ST_Con& c, int arg = -1)
6708 {
6709 ST_Errins errins(ERR_INSERT_PARTIAL_PREPARE_FAIL, 0, 1); // slave skips prepare
6710 chk1(st_do_errins(c, errins) == 0);
6711 return st_test_mnf_run_commit(c, arg);
6712 err:
6713 return -1;
6714 }
6715
6716 static int
st_test_mnf_abort_parse_partial(ST_Con & c,int arg=-1)6717 st_test_mnf_abort_parse_partial(ST_Con& c, int arg = -1)
6718 {
6719 ST_Errins errins(ERR_INSERT_PARTIAL_ABORT_PARSE_FAIL, 0, 1); // slave skips abort parse
6720 chk1(st_do_errins(c, errins) == 0);
6721 return st_test_mnf_run_abort(c, arg);
6722 err:
6723 return -1;
6724 }
6725
6726 static int
st_test_mnf_abort_prepare_partial(ST_Con & c,int arg=-1)6727 st_test_mnf_abort_prepare_partial(ST_Con& c, int arg = -1)
6728 {
6729 ST_Errins errins(ERR_INSERT_PARTIAL_ABORT_PREPARE_FAIL, 0, 1); // slave skips abort prepare
6730 chk1(st_do_errins(c, errins) == 0);
6731 return st_test_mnf_run_abort(c, arg);
6732 err:
6733 return -1;
6734 }
6735
6736 static int
st_test_mnf_flush_commit_partial(ST_Con & c,int arg=-1)6737 st_test_mnf_flush_commit_partial(ST_Con& c, int arg = -1)
6738 {
6739 NdbRestarter restarter;
6740 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_COMMIT_FAIL, 0, 1); // slave skips flush commit
6741 chk1(st_do_errins(c, errins) == 0);
6742 if (restarter.getNumDbNodes() < 3)
6743 // If new master is only node and it hasn't flush commit, we abort
6744 return st_test_mnf_run_commit(c, FAIL_END);
6745 else
6746 return st_test_mnf_run_commit(c, arg);
6747 err:
6748 return -1;
6749 }
6750
6751 static int
st_test_mnf_commit_partial(ST_Con & c,int arg=-1)6752 st_test_mnf_commit_partial(ST_Con& c, int arg = -1)
6753 {
6754 ST_Errins errins(ERR_INSERT_PARTIAL_COMMIT_FAIL, 0, 1); // slave skips commit
6755 chk1(st_do_errins(c, errins) == 0);
6756 return st_test_mnf_run_commit(c, arg);
6757 err:
6758 return -1;
6759 }
6760
6761 static int
st_test_mnf_flush_complete_partial(ST_Con & c,int arg=-1)6762 st_test_mnf_flush_complete_partial(ST_Con& c, int arg = -1)
6763 {
6764 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_COMPLETE_FAIL, 0, 1); // slave skips flush complete
6765 chk1(st_do_errins(c, errins) == 0);
6766 return st_test_mnf_run_commit(c, arg);
6767 err:
6768 return -1;
6769 }
6770
6771 static int
st_test_mnf_complete_partial(ST_Con & c,int arg=-1)6772 st_test_mnf_complete_partial(ST_Con& c, int arg = -1)
6773 {
6774 ST_Errins errins(ERR_INSERT_PARTIAL_COMPLETE_FAIL, 0, 1); // slave skips complete
6775 chk1(st_do_errins(c, errins) == 0);
6776 return st_test_mnf_run_commit(c, arg);
6777 err:
6778 return -1;
6779 }
6780
6781 static int
st_test_mnf_end_partial(ST_Con & c,int arg=-1)6782 st_test_mnf_end_partial(ST_Con& c, int arg = -1)
6783 {
6784 ST_Errins errins(ERR_INSERT_PARTIAL_END_FAIL, 0, 1); // slave skips end
6785 chk1(st_do_errins(c, errins) == 0);
6786 return st_test_mnf_run_commit(c, arg);
6787 err:
6788 return -1;
6789 }
6790
6791 static int
st_test_sr_parse(ST_Con & c,int arg=-1)6792 st_test_sr_parse(ST_Con& c, int arg = -1)
6793 {
6794 bool do_abort = (arg == 1);
6795 chk1(st_begin_trans(c) == 0);
6796 int i;
6797 for (i = 0; i < c.tabcount; i++) {
6798 ST_Tab& tab = c.tab(i);
6799 chk1(st_create_table_index(c, tab) == 0);
6800 }
6801 if (!do_abort)
6802 chk1(st_end_trans(c, 0) == 0);
6803 else
6804 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6805
6806 g_info << "restart all" << endl;
6807 int flags;
6808 flags = NdbRestarter::NRRF_NOSTART;
6809 chk1(c.restarter->restartAll2(flags) == 0);
6810 g_info << "wait for cluster started" << endl;
6811 chk1(c.restarter->waitClusterNoStart() == 0);
6812 chk1(c.restarter->startAll() == 0);
6813 chk1(c.restarter->waitClusterStarted() == 0);
6814 g_info << "verify all" << endl;
6815 chk1(st_verify_all(c) == 0);
6816 return NDBT_OK;
6817 err:
6818 return NDBT_FAILED;
6819 }
6820
6821 #if 0
6822 static int
6823 st_test_sr_commit(ST_Con& c, int arg = -1)
6824 {
6825 g_info << "not yet" << endl;
6826 return NDBT_OK;
6827 }
6828 #endif
6829
6830 // run test cases
6831
6832 struct ST_Test {
6833 const char* key;
6834 int mindbnodes;
6835 int arg;
6836 int (*func)(ST_Con& c, int arg);
6837 const char* name;
6838 const char* desc;
6839 };
6840
6841 static NdbOut&
operator <<(NdbOut & out,const ST_Test & test)6842 operator<<(NdbOut& out, const ST_Test& test)
6843 {
6844 out << "CASE " << test.key;
6845 out << " " << test.name;
6846 if (test.arg != -1)
6847 out << "+" << test.arg;
6848 out << " - " << test.desc;
6849 return out;
6850 }
6851
6852 static const ST_Test
6853 st_test_list[] = {
6854 #define func(f) f, #f
6855 // specific ops
6856 { "a1", 1, 0,
6857 func(st_test_create),
6858 "create all within trans, commit" },
6859 { "a2", 1, 1,
6860 func(st_test_create),
6861 "create all within trans, abort" },
6862 { "a3", 1, 0,
6863 func(st_test_drop),
6864 "drop all within trans, commit" },
6865 { "a4", 1, 1,
6866 func(st_test_drop),
6867 "drop all within trans, abort" },
6868 { "b1", 1, -1,
6869 func(st_test_rollback_create_table),
6870 "partial rollback of create table ops" },
6871 { "b2", 1, -1,
6872 func(st_test_rollback_drop_table),
6873 "partial rollback of drop table ops" },
6874 { "b3", 1, -1,
6875 func(st_test_rollback_create_index),
6876 "partial rollback of create index ops" },
6877 { "b4", 1, -1,
6878 func(st_test_rollback_drop_index),
6879 "partial rollback of drop index ops" },
6880 { "c1", 1, -1,
6881 func(st_test_dup_create_table),
6882 "try to create same table twice" },
6883 { "c2", 1, -1,
6884 func(st_test_dup_drop_table),
6885 "try to drop same table twice" },
6886 { "c3", 1, -1,
6887 func(st_test_dup_create_index),
6888 "try to create same index twice" },
6889 { "c4", 1, -1,
6890 func(st_test_dup_drop_index),
6891 "try to drop same index twice" },
6892 { "d1", 1, -1,
6893 func(st_test_build_index),
6894 "build index on non-empty table" },
6895 { "e1", 1, 0,
6896 func(st_test_local_create),
6897 "fail trigger create in TC, master errins 8033" },
6898 { "e2", 2, 1,
6899 func(st_test_local_create),
6900 "fail trigger create in TC, slave errins 8033" },
6901 { "e3", 1, 2,
6902 func(st_test_local_create),
6903 "fail trigger create in TUP, master errins 4003" },
6904 { "e4", 2, 3,
6905 func(st_test_local_create),
6906 "fail trigger create in TUP, slave errins 4003" },
6907 { "e5", 1, 4,
6908 func(st_test_local_create),
6909 "fail index create in TC, master errins 8034" },
6910 { "e6", 2, 5,
6911 func(st_test_local_create),
6912 "fail index create in TC, slave errins 8034" },
6913 // random ops
6914 { "o1", 1, 0,
6915 func(st_test_trans),
6916 "start and stop schema trans" },
6917 { "o2", 1, ST_AllowAbort,
6918 func(st_test_trans),
6919 "start and stop schema trans, allow abort" },
6920 { "o3", 1, ST_AllowAbort | ST_AllowErrins,
6921 func(st_test_trans),
6922 "start and stop schema trans, allow abort errins" },
6923 //
6924 { "p1", 1, 0,
6925 func(st_test_create_table),
6926 "create tables at random" },
6927 { "p2", 1, ST_AllowAbort,
6928 func(st_test_create_table),
6929 "create tables at random, allow abort" },
6930 { "p3", 1, ST_AllowAbort | ST_AllowErrins,
6931 func(st_test_create_table),
6932 "create tables at random, allow abort errins" },
6933 //
6934 { "p4", 1, 0,
6935 func(st_test_table),
6936 "create and drop tables at random" },
6937 { "p5", 1, ST_AllowAbort,
6938 func(st_test_table),
6939 "create and drop tables at random, allow abort" },
6940 { "p6", 1, ST_AllowAbort | ST_AllowErrins,
6941 func(st_test_table),
6942 "create and drop tables at random, allow abort errins" },
6943 //
6944 { "q1", 1, 0,
6945 func(st_test_create_index),
6946 "create indexes at random" },
6947 { "q2", 1, ST_AllowAbort,
6948 func(st_test_create_index),
6949 "create indexes at random, allow abort" },
6950 { "q3", 1, ST_AllowAbort | ST_AllowErrins,
6951 func(st_test_create_index),
6952 "create indexes at random, allow abort errins" },
6953 //
6954 { "q4", 1, 0,
6955 func(st_test_index),
6956 "create and drop indexes at random" },
6957 { "q5", 1, ST_AllowAbort,
6958 func(st_test_index),
6959 "create and drop indexes at random, allow abort" },
6960 { "q6", 1, ST_AllowAbort | ST_AllowErrins,
6961 func(st_test_index),
6962 "create and drop indexes at random, allow abort errins" },
6963 // node failure and system restart
6964 { "u1", 1, -1,
6965 func(st_test_anf_parse),
6966 "api node fail in parse phase" },
6967 { "u2", 1, -1,
6968 func(st_test_anf_background),
6969 "api node fail after background trans" },
6970 { "u3", 2, -1,
6971 func(st_test_anf_fail_begin),
6972 "api node fail in middle of kernel begin trans" },
6973 //
6974 { "v1", 2, 0,
6975 func(st_test_snf_parse),
6976 "slave node fail in parse phase, commit" },
6977 { "v2", 2, 1,
6978 func(st_test_snf_parse),
6979 "slave node fail in parse phase, abort" },
6980 { "w1", 1, 0,
6981 func(st_test_sr_parse),
6982 "system restart in parse phase, commit" },
6983 { "w2", 1, 1,
6984 func(st_test_sr_parse),
6985 "system restart in parse phase, abort" },
6986 #ifdef ndb_master_failure
6987 { "x1", 2, 0,
6988 func(st_test_mnf_parse),
6989 "master node fail in parse phase, commit" },
6990 { "x2", 2, 1,
6991 func(st_test_mnf_parse),
6992 "master node fail in parse phase, abort" },
6993 { "x3", 2, 0,
6994 func(st_test_mnf_prepare),
6995 "master node fail in prepare phase" },
6996 { "x4", 2, 0,
6997 func(st_test_mnf_commit1),
6998 "master node fail in start of commit phase" },
6999 { "x5", 2, 0,
7000 func(st_test_mnf_commit2),
7001 "master node fail in end of commit phase" },
7002 { "y1", 2, FAIL_BEGIN,
7003 func(st_test_mnf_start_partial),
7004 "master node fail in start phase, partial rollback" },
7005 { "y2", 2, FAIL_CREATE,
7006 func(st_test_mnf_parse_partial),
7007 "master node fail in parse phase, partial rollback" },
7008 { "y3", 2, FAIL_END,
7009 func(st_test_mnf_flush_prepare_partial),
7010 "master node fail in flush prepare phase, partial rollback" },
7011 { "y4", 2, FAIL_END,
7012 func(st_test_mnf_prepare_partial),
7013 "master node fail in prepare phase, partial rollback" },
7014 { "y5", 2, SUCCEED_COMMIT,
7015 func(st_test_mnf_flush_commit_partial),
7016 "master node fail in flush commit phase, partial rollback" },
7017 { "y6", 2, SUCCEED_COMMIT,
7018 func(st_test_mnf_commit_partial),
7019 "master node fail in commit phase, commit, partial rollforward" },
7020 { "y7", 2, SUCCEED_COMMIT,
7021 func(st_test_mnf_flush_complete_partial),
7022 "master node fail in flush complete phase, commit, partial rollforward" },
7023 { "y8", 2, SUCCEED_COMMIT,
7024 func(st_test_mnf_complete_partial),
7025 "master node fail in complete phase, commit, partial rollforward" },
7026 { "y9", 2, SUCCEED_COMMIT,
7027 func(st_test_mnf_end_partial),
7028 "master node fail in end phase, commit, partial rollforward" },
7029 { "z1", 2, SUCCEED_ABORT,
7030 func(st_test_mnf_abort_parse_partial),
7031 "master node fail in abort parse phase, partial rollback" },
7032 { "z2", 2, FAIL_END,
7033 func(st_test_mnf_abort_prepare_partial),
7034 "master node fail in abort prepare phase, partial rollback" },
7035 { "z3", 2, 1,
7036 func(st_test_mnf_prepare),
7037 "master node fail in prepare phase in background" },
7038 { "z4", 2, 1,
7039 func(st_test_mnf_commit1),
7040 "master node fail in start of commit phase in background" },
7041 { "z5", 2, 1,
7042 func(st_test_mnf_commit2),
7043 "master node fail in end of commit phase in background" },
7044
7045 #endif
7046 #undef func
7047 };
7048
7049 static const int
7050 st_test_count = sizeof(st_test_list)/sizeof(st_test_list[0]);
7051
7052 static const char* st_test_case = 0;
7053 static const char* st_test_skip = 0;
7054
7055 static bool
st_test_match(const ST_Test & test)7056 st_test_match(const ST_Test& test)
7057 {
7058 const char* p = 0;
7059 if (st_test_case == 0)
7060 goto skip;
7061 if (strstr(st_test_case, test.key) != 0)
7062 goto skip;
7063 p = strchr(st_test_case, test.key[0]);
7064 if (p != 0 && (p[1] < '0' || p[1] > '9'))
7065 goto skip;
7066 return false;
7067 skip:
7068 if (st_test_skip == 0)
7069 return true;
7070 if (strstr(st_test_skip, test.key) != 0)
7071 return false;
7072 p = strchr(st_test_skip, test.key[0]);
7073 if (p != 0 && (p[1] < '0' || p[1] > '9'))
7074 return false;
7075 return true;
7076 }
7077
7078 static int
st_test(ST_Con & c,const ST_Test & test)7079 st_test(ST_Con& c, const ST_Test& test)
7080 {
7081 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7082 chk1(st_drop_test_tables(c) == 0);
7083 chk1(st_check_db_nodes(c) == 0);
7084
7085 g_err << test << endl;
7086 if (c.numdbnodes < test.mindbnodes) {
7087 g_err << "skip, too few db nodes" << endl;
7088 return NDBT_OK;
7089 }
7090
7091 chk1((*test.func)(c, test.arg) == NDBT_OK);
7092 chk1(st_check_db_nodes(c) == 0);
7093 //chk1(st_verify_list(c) == 0);
7094
7095 return NDBT_OK;
7096 err:
7097 return NDBT_FAILED;
7098 }
7099
7100 static int st_random_seed = -1;
7101
7102 int
runSchemaTrans(NDBT_Context * ctx,NDBT_Step * step)7103 runSchemaTrans(NDBT_Context* ctx, NDBT_Step* step)
7104 {
7105 { const char* env = NdbEnv_GetEnv("NDB_TEST_DBUG", 0, 0);
7106 if (env != 0 && env[0] != 0) // e.g. d:t:L:F:o,ndb_test.log
7107 DBUG_PUSH(env);
7108 }
7109 { const char* env = NdbEnv_GetEnv("NDB_TEST_CORE", 0, 0);
7110 if (env != 0 && env[0] != 0 && env[0] != '0' && env[0] != 'N')
7111 st_core_on_err = true;
7112 }
7113 { const char* env = NdbEnv_GetEnv("NDB_TEST_CASE", 0, 0);
7114 st_test_case = env;
7115 }
7116 { const char* env = NdbEnv_GetEnv("NDB_TEST_SKIP", 0, 0);
7117 st_test_skip = env;
7118 }
7119 { const char* env = NdbEnv_GetEnv("NDB_TEST_SEED", 0, 0);
7120 if (env != 0)
7121 st_random_seed = atoi(env);
7122 }
7123
7124 if (st_test_case != 0 && strcmp(st_test_case, "?") == 0) {
7125 int i;
7126 ndbout << "case func+arg desc" << endl;
7127 for (i = 0; i < st_test_count; i++) {
7128 const ST_Test& test = st_test_list[i];
7129 ndbout << test << endl;
7130 }
7131 return NDBT_WRONGARGS;
7132 }
7133
7134 if (st_random_seed == -1)
7135 st_random_seed = (short)getpid();
7136 if (st_random_seed != 0) {
7137 g_err << "random seed: " << st_random_seed << endl;
7138 ndb_srand(st_random_seed);
7139 } else {
7140 g_err << "random seed: loop number" << endl;
7141 }
7142
7143 Ndb_cluster_connection* ncc = &ctx->m_cluster_connection;
7144 Ndb* ndb = GETNDB(step);
7145 ST_Restarter* restarter = new ST_Restarter;
7146 ST_Con c(ncc, ndb, restarter);
7147
7148 chk1(st_drop_all_tables(c) == 0);
7149 st_init_objects(c, ctx);
7150
7151 int numloops;
7152 numloops = ctx->getNumLoops();
7153
7154 for (c.loop = 0; numloops == 0 || c.loop < numloops; c.loop++) {
7155 g_err << "LOOP " << c.loop << endl;
7156 if (st_random_seed == 0)
7157 ndb_srand(c.loop);
7158 int i;
7159 for (i = 0; i < st_test_count; i++) {
7160 const ST_Test& test = st_test_list[i];
7161 if (st_test_match(test)) {
7162 chk1(st_test(c, test) == NDBT_OK);
7163 }
7164 }
7165 }
7166
7167 st_report_db_nodes(c, g_err);
7168 return NDBT_OK;
7169 err:
7170 st_report_db_nodes(c, g_err);
7171 return NDBT_FAILED;
7172 }
7173
7174 // end schema trans
7175
7176 int
runFailCreateHashmap(NDBT_Context * ctx,NDBT_Step * step)7177 runFailCreateHashmap(NDBT_Context* ctx, NDBT_Step* step)
7178 {
7179 static int lst[] = { 6204, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 0 };
7180
7181 NdbRestarter restarter;
7182 int nodeId = restarter.getMasterNodeId();
7183 Ndb* pNdb = GETNDB(step);
7184 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7185
7186 int errNo = 0;
7187 char buf[100];
7188 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
7189 {
7190 errNo = atoi(buf);
7191 ndbout_c("Using errno: %u", errNo);
7192 }
7193
7194 const int loops = ctx->getNumLoops();
7195 int result = NDBT_OK;
7196
7197 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
7198 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
7199
7200 NdbDictionary::HashMap hm;
7201 pDic->initDefaultHashMap(hm, 1);
7202
7203 loop:
7204 if (pDic->getHashMap(hm, hm.getName()) != -1)
7205 {
7206 pDic->initDefaultHashMap(hm, rand() % 64);
7207 goto loop;
7208 }
7209
7210 for (int l = 0; l < loops; l++)
7211 {
7212 for (unsigned i0 = 0; lst[i0]; i0++)
7213 {
7214 unsigned j = (l == 0 ? i0 : myRandom48(i0 + l));
7215 int errval = lst[j];
7216 if (errNo != 0 && errNo != errval)
7217 continue;
7218 g_info << "insert error node=" << nodeId << " value=" << errval << endl;
7219 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
7220 "failed to set error insert");
7221 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
7222
7223 int res = pDic->createHashMap(hm);
7224 CHECK2(res != 0, "create hashmap failed to fail");
7225
7226 NdbDictionary::HashMap check;
7227 CHECK2(res != 0, "create hashmap existed");
7228
7229 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
7230 "failed to clear error insert");
7231 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
7232 }
7233 }
7234 end:
7235 return result;
7236 }
7237 // end FAIL create hashmap
7238
7239 int
runFailAddPartition(NDBT_Context * ctx,NDBT_Step * step)7240 runFailAddPartition(NDBT_Context* ctx, NDBT_Step* step)
7241 {
7242 static int lst[] = { 7211, 7212, 4050, 12008, 6212, 6124, 6213, 6214, 0 };
7243
7244 Ndb* pNdb = GETNDB(step);
7245 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7246 NdbDictionary::Table tab(*ctx->getTab());
7247 NdbRestarter restarter;
7248 int nodeId = restarter.getMasterNodeId();
7249
7250 int errNo = 0;
7251 char buf[100];
7252 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
7253 {
7254 errNo = atoi(buf);
7255 ndbout_c("Using errno: %u", errNo);
7256 }
7257
7258 // ordered index on first few columns
7259 NdbDictionary::Index idx("X");
7260 idx.setTable(tab.getName());
7261 idx.setType(NdbDictionary::Index::OrderedIndex);
7262 idx.setLogging(false);
7263 for (int cnt = 0, i_hate_broken_compilers = 0;
7264 cnt < 3 &&
7265 i_hate_broken_compilers < tab.getNoOfColumns();
7266 i_hate_broken_compilers++) {
7267 if (NdbSqlUtil::check_column_for_ordered_index
7268 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
7269 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
7270 NdbDictionary::Column::StorageTypeDisk)
7271 {
7272 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
7273 cnt++;
7274 }
7275 }
7276
7277 for (int i = 0; i<tab.getNoOfColumns(); i++)
7278 {
7279 if (tab.getColumn(i)->getStorageType() ==
7280 NdbDictionary::Column::StorageTypeDisk)
7281 {
7282 NDBT_Tables::create_default_tablespace(pNdb);
7283 break;
7284 }
7285 }
7286
7287 const int loops = ctx->getNumLoops();
7288 int result = NDBT_OK;
7289 (void)pDic->dropTable(tab.getName());
7290 if (pDic->createTable(tab) != 0)
7291 {
7292 ndbout << "FAIL: " << pDic->getNdbError() << endl;
7293 return NDBT_FAILED;
7294 }
7295
7296 if (pDic->createIndex(idx) != 0)
7297 {
7298 ndbout << "FAIL: " << pDic->getNdbError() << endl;
7299 return NDBT_FAILED;
7300 }
7301
7302 const NdbDictionary::Table * org = pDic->getTable(tab.getName());
7303 NdbDictionary::Table altered = * org;
7304 altered.setFragmentCount(org->getFragmentCount() +
7305 restarter.getNumDbNodes());
7306
7307 if (pDic->beginSchemaTrans())
7308 {
7309 ndbout << "Failed to beginSchemaTrans()" << pDic->getNdbError() << endl;
7310 return NDBT_FAILED;
7311 }
7312
7313 if (pDic->prepareHashMap(*org, altered) == -1)
7314 {
7315 ndbout << "Failed to create hashmap: " << pDic->getNdbError() << endl;
7316 return NDBT_FAILED;
7317 }
7318
7319 if (pDic->endSchemaTrans())
7320 {
7321 ndbout << "Failed to endSchemaTrans()" << pDic->getNdbError() << endl;
7322 return NDBT_FAILED;
7323 }
7324
7325 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
7326 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
7327
7328 for (int l = 0; l < loops; l++)
7329 {
7330 for (unsigned i0 = 0; lst[i0]; i0++)
7331 {
7332 unsigned j = (l == 0 ? i0 : myRandom48(sizeof(lst)/sizeof(lst[0]) - 1));
7333 int errval = lst[j];
7334 if (errNo != 0 && errNo != errval)
7335 continue;
7336 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
7337 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
7338 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
7339 "failed to set error insert");
7340
7341 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
7342
7343 int res = pDic->alterTable(*org, altered);
7344 if (res)
7345 {
7346 ndbout << pDic->getNdbError() << endl;
7347 }
7348 CHECK2(res != 0,
7349 "failed to fail after error insert " << errval);
7350 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
7351 "failed to clear error insert");
7352 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
7353 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
7354
7355 const NdbDictionary::Table* check = pDic->getTable(tab.getName());
7356
7357 CHECK2((check->getObjectId() == org->getObjectId() &&
7358 check->getObjectVersion() == org->getObjectVersion()),
7359 "table has been altered!");
7360 }
7361 }
7362
7363 end:
7364 (void)pDic->dropTable(tab.getName());
7365 return result;
7366 }
7367 // fail add partition
7368
7369 int
runTableAddPartition(NDBT_Context * ctx,NDBT_Step * step)7370 runTableAddPartition(NDBT_Context* ctx, NDBT_Step* step){
7371
7372 int result = NDBT_OK;
7373
7374 Ndb* pNdb = GETNDB(step);
7375 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
7376 int records = ctx->getNumRecords();
7377 const int loops = ctx->getNumLoops();
7378
7379 ndbout << "|- " << ctx->getTab()->getName() << endl;
7380
7381 NdbDictionary::Table myTab= *(ctx->getTab());
7382 myTab.setFragmentType(NdbDictionary::Object::HashMapPartition);
7383
7384 for (int l = 0; l < loops && result == NDBT_OK ; l++)
7385 {
7386 // Try to create table in db
7387 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
7388 return NDBT_FAILED;
7389 }
7390
7391 // Verify that table is in db
7392 const NdbDictionary::Table* pTab2 =
7393 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
7394 if (pTab2 == NULL){
7395 ndbout << myTab.getName() << " was not found in DB"<< endl;
7396 return NDBT_FAILED;
7397 }
7398 ctx->setTab(pTab2);
7399
7400 #if 1
7401 // Load table
7402 HugoTransactions beforeTrans(*ctx->getTab());
7403 if (beforeTrans.loadTable(pNdb, records) != 0){
7404 return NDBT_FAILED;
7405 }
7406 #endif
7407
7408 // Add attributes to table.
7409 BaseString pTabName(pTab2->getName());
7410 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
7411
7412 NdbDictionary::Table newTable= *oldTable;
7413
7414 newTable.setFragmentCount(2 * oldTable->getFragmentCount());
7415 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
7416 "TableAddAttrs failed");
7417
7418 /* Need to purge old version and reload new version after alter table. */
7419 dict->invalidateTable(pTabName.c_str());
7420
7421 #if 0
7422 {
7423 HugoTransactions afterTrans(* dict->getTable(pTabName.c_str()));
7424
7425 ndbout << "delete...";
7426 if (afterTrans.clearTable(pNdb) != 0)
7427 {
7428 return NDBT_FAILED;
7429 }
7430 ndbout << endl;
7431
7432 ndbout << "insert...";
7433 if (afterTrans.loadTable(pNdb, records) != 0){
7434 return NDBT_FAILED;
7435 }
7436 ndbout << endl;
7437
7438 ndbout << "update...";
7439 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
7440 {
7441 return NDBT_FAILED;
7442 }
7443 ndbout << endl;
7444
7445 ndbout << "delete...";
7446 if (afterTrans.clearTable(pNdb) != 0)
7447 {
7448 return NDBT_FAILED;
7449 }
7450 ndbout << endl;
7451 }
7452 #endif
7453 abort();
7454 // Drop table.
7455 dict->dropTable(pTabName.c_str());
7456 }
7457 end:
7458
7459 return result;
7460 }
7461
7462 int
runBug41905(NDBT_Context * ctx,NDBT_Step * step)7463 runBug41905(NDBT_Context* ctx, NDBT_Step* step)
7464 {
7465 const NdbDictionary::Table* pTab = ctx->getTab();
7466 BaseString tabName(pTab->getName());
7467 Ndb* pNdb = GETNDB(step);
7468 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7469
7470 NdbDictionary::Table creTab = *pTab;
7471 creTab.setForceVarPart(true);
7472 int ret = NDBT_OK;
7473
7474 (void)pDic->dropTable(tabName.c_str());
7475 if (pDic->createTable(creTab)) {
7476 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7477 ret = NDBT_FAILED;
7478 }
7479
7480 Uint32 cols = creTab.getNoOfColumns();
7481 Uint32 vers = 0;
7482 while (ret == NDBT_OK) {
7483 const NdbDictionary::Table* pOldTab = pDic->getTableGlobal(tabName.c_str());
7484 assert(pOldTab != 0);
7485
7486 const Uint32 old_st = pOldTab->getObjectStatus();
7487 const Uint32 old_cols = pOldTab->getNoOfColumns();
7488 const Uint32 old_vers = pOldTab->getObjectVersion() >> 24;
7489
7490 if (old_st != NdbDictionary::Object::Retrieved) {
7491 g_err << __LINE__ << ": " << "got status " << old_st << endl;
7492 ret = NDBT_FAILED;
7493 break;
7494 }
7495 // bug#41905 or related: other thread causes us to get old version
7496 if (old_cols != cols || old_vers != vers) {
7497 g_err << __LINE__ << ": "
7498 << "got cols,vers " << old_cols << "," << old_vers
7499 << " expected " << cols << "," << vers << endl;
7500 ret = NDBT_FAILED;
7501 break;
7502 }
7503 if (old_cols >= 100)
7504 break;
7505 const NdbDictionary::Table& oldTab = *pOldTab;
7506
7507 NdbDictionary::Table newTab = oldTab;
7508 char colName[100];
7509 sprintf(colName, "COL41905_%02d", cols);
7510 g_info << "add " << colName << endl;
7511 NDBT_Attribute newCol(colName, NdbDictionary::Column::Unsigned, 1,
7512 false, true, (CHARSET_INFO*)0,
7513 NdbDictionary::Column::StorageTypeMemory, true);
7514 newTab.addColumn(newCol);
7515
7516 ctx->setProperty("Bug41905", 1);
7517 NdbSleep_MilliSleep(10);
7518
7519 const bool removeEarly = (uint)rand() % 2;
7520 g_info << "removeEarly = " << removeEarly << endl;
7521
7522 if (pDic->beginSchemaTrans() != 0) {
7523 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7524 ret = NDBT_FAILED;
7525 break;
7526 }
7527 if (pDic->alterTable(oldTab, newTab) != 0) {
7528 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7529 ret = NDBT_FAILED;
7530 break;
7531 }
7532
7533 if (removeEarly)
7534 pDic->removeTableGlobal(*pOldTab, 0);
7535
7536 if (pDic->endSchemaTrans() != 0) {
7537 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7538 ret = NDBT_FAILED;
7539 break;
7540 }
7541
7542 cols++;
7543 vers++;
7544 if (!removeEarly)
7545 pDic->removeTableGlobal(*pOldTab, 0);
7546 ctx->setProperty("Bug41905", 2);
7547 NdbSleep_MilliSleep(10);
7548 }
7549
7550 ctx->setProperty("Bug41905", 3);
7551 return ret;
7552 }
7553
7554 int
runBug41905getTable(NDBT_Context * ctx,NDBT_Step * step)7555 runBug41905getTable(NDBT_Context* ctx, NDBT_Step* step)
7556 {
7557 const NdbDictionary::Table* pTab = ctx->getTab();
7558 BaseString tabName(pTab->getName());
7559 Ndb* pNdb = GETNDB(step);
7560 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7561
7562 while (1) {
7563 while (1) {
7564 if (ctx->getProperty("Bug41905") == 1)
7565 break;
7566 if (ctx->getProperty("Bug41905") == 3)
7567 goto out;
7568 NdbSleep_MilliSleep(10);
7569 }
7570
7571 uint ms = (uint)rand() % 1000;
7572 NdbSleep_MilliSleep(ms);
7573 g_info << "get begin ms=" << ms << endl;
7574
7575 Uint32 count = 0;
7576 Uint32 oldstatus = 0;
7577 while (1) {
7578 count++;
7579 const NdbDictionary::Table* pTmp = pDic->getTableGlobal(tabName.c_str());
7580 assert(pTmp != 0);
7581 Uint32 code = pDic->getNdbError().code;
7582 Uint32 status = pTmp->getObjectStatus();
7583 if (oldstatus == 2 && status == 3)
7584 g_info << "code=" << code << " status=" << status << endl;
7585 oldstatus = status;
7586 pDic->removeTableGlobal(*pTmp, 0);
7587 if (ctx->getProperty("Bug41905") != 1)
7588 break;
7589 NdbSleep_MilliSleep(10);
7590 }
7591 g_info << "get end count=" << count << endl;
7592 }
7593
7594 out:
7595 (void)pDic->dropTable(tabName.c_str());
7596 return NDBT_OK;
7597 }
7598
7599 static
7600 int
createIndexes(NdbDictionary::Dictionary * pDic,const NdbDictionary::Table & tab,int cnt)7601 createIndexes(NdbDictionary::Dictionary* pDic,
7602 const NdbDictionary::Table & tab, int cnt)
7603 {
7604 for (int i = 0; i<cnt && i < tab.getNoOfColumns(); i++)
7605 {
7606 char buf[256];
7607 NdbDictionary::Index idx0;
7608 BaseString::snprintf(buf, sizeof(buf), "%s-idx-%u", tab.getName(), i);
7609 idx0.setName(buf);
7610 idx0.setType(NdbDictionary::Index::OrderedIndex);
7611 idx0.setTable(tab.getName());
7612 idx0.setStoredIndex(false);
7613 idx0.addIndexColumn(tab.getColumn(i)->getName());
7614
7615 if (pDic->createIndex(idx0))
7616 {
7617 ndbout << pDic->getNdbError() << endl;
7618 return NDBT_FAILED;
7619 }
7620 }
7621
7622 return 0;
7623 }
7624
7625 int
runBug46552(NDBT_Context * ctx,NDBT_Step * step)7626 runBug46552(NDBT_Context* ctx, NDBT_Step* step)
7627 {
7628 Ndb* pNdb = GETNDB(step);
7629 const NdbDictionary::Table* pTab = ctx->getTab();
7630 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7631
7632 NdbRestarter res;
7633 if (res.getNumDbNodes() < 2)
7634 return NDBT_OK;
7635
7636 NdbDictionary::Table tab0 = *pTab;
7637 NdbDictionary::Table tab1 = *pTab;
7638
7639 BaseString name;
7640 name.assfmt("%s_0", tab0.getName());
7641 tab0.setName(name.c_str());
7642 name.assfmt("%s_1", tab1.getName());
7643 tab1.setName(name.c_str());
7644
7645 pDic->dropTable(tab0.getName());
7646 pDic->dropTable(tab1.getName());
7647
7648 if (pDic->createTable(tab0))
7649 {
7650 ndbout << pDic->getNdbError() << endl;
7651 return NDBT_FAILED;
7652 }
7653
7654 if (pDic->createTable(tab1))
7655 {
7656 ndbout << pDic->getNdbError() << endl;
7657 return NDBT_FAILED;
7658 }
7659
7660 if (createIndexes(pDic, tab1, 4))
7661 return NDBT_FAILED;
7662
7663 Vector<int> group1;
7664 Vector<int> group2;
7665 Bitmask<256/32> nodeGroupMap;
7666 for (int j = 0; j<res.getNumDbNodes(); j++)
7667 {
7668 int node = res.getDbNodeId(j);
7669 int ng = res.getNodeGroup(node);
7670 if (nodeGroupMap.get(ng))
7671 {
7672 group2.push_back(node);
7673 }
7674 else
7675 {
7676 group1.push_back(node);
7677 nodeGroupMap.set(ng);
7678 }
7679 }
7680
7681 res.restartNodes(group1.getBase(), (int)group1.size(),
7682 NdbRestarter::NRRF_NOSTART |
7683 NdbRestarter::NRRF_ABORT);
7684
7685 res.waitNodesNoStart(group1.getBase(), (int)group1.size());
7686 res.startNodes(group1.getBase(), (int)group1.size());
7687 res.waitClusterStarted();
7688
7689 res.restartNodes(group2.getBase(), (int)group2.size(),
7690 NdbRestarter::NRRF_NOSTART |
7691 NdbRestarter::NRRF_ABORT);
7692 res.waitNodesNoStart(group2.getBase(), (int)group2.size());
7693 res.startNodes(group2.getBase(), (int)group2.size());
7694 res.waitClusterStarted();
7695
7696 if (pDic->dropTable(tab0.getName()))
7697 {
7698 ndbout << pDic->getNdbError() << endl;
7699 return NDBT_FAILED;
7700 }
7701
7702 if (pDic->createTable(tab0))
7703 {
7704 ndbout << pDic->getNdbError() << endl;
7705 return NDBT_FAILED;
7706 }
7707
7708 if (createIndexes(pDic, tab0, 4))
7709 return NDBT_FAILED;
7710
7711 res.restartAll2(NdbRestarter::NRRF_NOSTART | NdbRestarter::NRRF_ABORT);
7712 res.waitClusterNoStart();
7713 res.startAll();
7714 res.waitClusterStarted();
7715
7716 if (pDic->dropTable(tab0.getName()))
7717 {
7718 ndbout << pDic->getNdbError() << endl;
7719 return NDBT_FAILED;
7720 }
7721
7722 if (pDic->dropTable(tab1.getName()))
7723 {
7724 ndbout << pDic->getNdbError() << endl;
7725 return NDBT_FAILED;
7726 }
7727
7728 return NDBT_OK;
7729 }
7730
7731 int
runBug46585(NDBT_Context * ctx,NDBT_Step * step)7732 runBug46585(NDBT_Context* ctx, NDBT_Step* step)
7733 {
7734 Ndb* pNdb = GETNDB(step);
7735 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7736 NdbDictionary::Table tab(*ctx->getTab());
7737 NdbRestarter res;
7738 int records = ctx->getNumRecords();
7739
7740 // ordered index on first few columns
7741 NdbDictionary::Index idx("X");
7742 idx.setTable(tab.getName());
7743 idx.setType(NdbDictionary::Index::OrderedIndex);
7744 idx.setLogging(false);
7745 for (int cnt = 0, i_hate_broken_compilers = 0;
7746 cnt < 3 &&
7747 i_hate_broken_compilers < tab.getNoOfColumns();
7748 i_hate_broken_compilers++) {
7749 if (NdbSqlUtil::check_column_for_ordered_index
7750 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
7751 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
7752 NdbDictionary::Column::StorageTypeDisk)
7753 {
7754 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
7755 cnt++;
7756 }
7757 }
7758
7759 for (int i = 0; i<tab.getNoOfColumns(); i++)
7760 {
7761 if (tab.getColumn(i)->getStorageType() ==
7762 NdbDictionary::Column::StorageTypeDisk)
7763 {
7764 NDBT_Tables::create_default_tablespace(pNdb);
7765 break;
7766 }
7767 }
7768
7769 const int loops = ctx->getNumLoops();
7770 int result = NDBT_OK;
7771 (void)pDic->dropTable(tab.getName());
7772 if (pDic->createTable(tab) != 0)
7773 {
7774 ndbout << "FAIL: " << pDic->getNdbError() << endl;
7775 return NDBT_FAILED;
7776 }
7777
7778 if (pDic->createIndex(idx) != 0)
7779 {
7780 ndbout << "FAIL: " << pDic->getNdbError() << endl;
7781 return NDBT_FAILED;
7782 }
7783
7784 for (int i = 0; i<loops; i++)
7785 {
7786 const NdbDictionary::Table * org = pDic->getTable(tab.getName());
7787 {
7788 HugoTransactions trans(* org);
7789 CHECK2(trans.loadTable(pNdb, records) == 0,
7790 "load table failed");
7791 }
7792
7793 NdbDictionary::Table altered = * org;
7794 altered.setFragmentCount(org->getFragmentCount() + 1);
7795 ndbout_c("alter from %u to %u partitions",
7796 org->getFragmentCount(),
7797 altered.getFragmentCount());
7798
7799 if (pDic->beginSchemaTrans())
7800 {
7801 ndbout << "Failed to beginSchemaTrans()" << pDic->getNdbError() << endl;
7802 return NDBT_FAILED;
7803 }
7804
7805 if (pDic->prepareHashMap(*org, altered) == -1)
7806 {
7807 ndbout << "Failed to create hashmap: " << pDic->getNdbError() << endl;
7808 return NDBT_FAILED;
7809 }
7810
7811 if (pDic->endSchemaTrans())
7812 {
7813 ndbout << "Failed to endSchemaTrans()" << pDic->getNdbError() << endl;
7814 return NDBT_FAILED;
7815 }
7816
7817 result = pDic->alterTable(*org, altered);
7818 if (result)
7819 {
7820 ndbout << pDic->getNdbError() << endl;
7821 }
7822 if (pDic->getNdbError().code == 1224)
7823 {
7824 /**
7825 * To many fragments is an acceptable error
7826 * depending on configuration used for test-case
7827 */
7828 result = NDBT_OK;
7829 goto end;
7830 }
7831 CHECK2(result == 0,
7832 "failed to alter");
7833
7834 pDic->invalidateTable(tab.getName());
7835 {
7836 const NdbDictionary::Table * alteredP = pDic->getTable(tab.getName());
7837 CHECK2(alteredP->getFragmentCount() == altered.getFragmentCount(),
7838 "altered table does not have correct frag count");
7839
7840 HugoTransactions trans(* alteredP);
7841
7842 CHECK2(trans.scanUpdateRecords(pNdb, records) == 0,
7843 "scan update failed");
7844 trans.startTransaction(pNdb);
7845 trans.pkUpdateRecord(pNdb, 0);
7846 trans.execute_Commit(pNdb);
7847 ndbout_c("before restart, gci: %d", trans.getRecordGci(0));
7848 trans.closeTransaction(pNdb);
7849 }
7850
7851 switch(i % 2){
7852 case 0:
7853 if (res.getNumDbNodes() > 1)
7854 {
7855 int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
7856 ndbout_c("performing node-restart of node %d", nodeId);
7857 CHECK2(res.restartOneDbNode(nodeId,
7858 false,
7859 true,
7860 true) == 0,
7861 "restart one node failed");
7862 CHECK2(res.waitNodesNoStart(&nodeId, 1) == 0,
7863 "wait node started failed");
7864 CHECK2(res.startNodes(&nodeId, 1) == 0,
7865 "start node failed");
7866 break;
7867 }
7868 case 1:
7869 {
7870 ndbout_c("performing system restart");
7871 CHECK2(res.restartAll(false, true, false) == 0,
7872 "restart all failed");
7873 CHECK2(res.waitClusterNoStart() == 0,
7874 "waitClusterNoStart failed");
7875 CHECK2(res.startAll() == 0,
7876 "startAll failed");
7877 break;
7878 }
7879 }
7880 CHECK2(res.waitClusterStarted() == 0,
7881 "wait cluster started failed");
7882
7883 Uint32 restartGCI = 0;
7884 CHECK2(pDic->getRestartGCI(&restartGCI) == 0,
7885 "getRestartGCI failed");
7886 ndbout_c("restartGCI: %u", restartGCI);
7887
7888 pDic->invalidateTable(tab.getName());
7889 {
7890 const NdbDictionary::Table * alteredP = pDic->getTable(tab.getName());
7891 HugoTransactions trans(* alteredP);
7892
7893 int cnt;
7894 CHECK2(trans.selectCount(pNdb, 0, &cnt) == 0,
7895 "select count failed");
7896
7897 CHECK2(cnt == records,
7898 "table does not have correct record count: "
7899 << cnt << " != " << records);
7900
7901 CHECK2(alteredP->getFragmentCount() == altered.getFragmentCount(),
7902 "altered table does not have correct frag count");
7903
7904 CHECK2(trans.scanUpdateRecords(pNdb, records) == 0,
7905 "scan update failed");
7906 CHECK2(trans.pkUpdateRecords(pNdb, records) == 0,
7907 "pkUpdateRecords failed");
7908 CHECK2(trans.clearTable(pNdb) == 0,
7909 "clear table failed");
7910 }
7911 }
7912
7913 end:
7914 (void)pDic->dropTable(tab.getName());
7915 return result;
7916 }
7917
7918 int
runBug53944(NDBT_Context * ctx,NDBT_Step * step)7919 runBug53944(NDBT_Context* ctx, NDBT_Step* step)
7920 {
7921 Ndb* pNdb = GETNDB(step);
7922 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7923 NdbDictionary::Table tab(*ctx->getTab());
7924 NdbRestarter res;
7925
7926 Vector<int> ids;
7927 for (unsigned i = 0; i< 25; i++)
7928 {
7929 NdbDictionary::Table copy = tab;
7930 BaseString name;
7931 name.appfmt("%s_%u", copy.getName(), i);
7932 copy.setName(name.c_str());
7933 int res = pDic->createTable(copy);
7934 if (res)
7935 {
7936 g_err << "Failed to create table" << copy.getName() << "\n"
7937 << pDic->getNdbError() << endl;
7938 return NDBT_FAILED;
7939 }
7940 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
7941 if (tab == 0)
7942 {
7943 g_err << "Failed to retreive table" << copy.getName() << endl;
7944 return NDBT_FAILED;
7945
7946 }
7947 ids.push_back(tab->getObjectId());
7948 }
7949
7950 res.restartAll2(NdbRestarter::NRRF_ABORT | NdbRestarter::NRRF_NOSTART);
7951 res.waitClusterNoStart();
7952 res.startAll();
7953 res.waitClusterStarted();
7954
7955 for (unsigned i = 0; i< 25; i++)
7956 {
7957 NdbDictionary::Table copy = tab;
7958 BaseString name;
7959 name.appfmt("%s_%u", copy.getName(), i);
7960 copy.setName(name.c_str());
7961 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
7962 if (tab == 0)
7963 {
7964 g_err << "Failed to retreive table" << copy.getName() << endl;
7965 return NDBT_FAILED;
7966
7967 }
7968 int res = pDic->dropTable(copy.getName());
7969 if (res)
7970 {
7971 g_err << "Failed to drop table" << copy.getName() << "\n"
7972 << pDic->getNdbError() << endl;
7973 return NDBT_FAILED;
7974 }
7975 }
7976
7977 Vector<int> ids2;
7978 for (unsigned i = 0; i< 25; i++)
7979 {
7980 NdbDictionary::Table copy = tab;
7981 BaseString name;
7982 name.appfmt("%s_%u", copy.getName(), i);
7983 copy.setName(name.c_str());
7984 int res = pDic->createTable(copy);
7985 if (res)
7986 {
7987 g_err << "Failed to create table" << copy.getName() << "\n"
7988 << pDic->getNdbError() << endl;
7989 return NDBT_FAILED;
7990 }
7991 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
7992 if (tab == 0)
7993 {
7994 g_err << "Failed to retreive table" << copy.getName() << endl;
7995 return NDBT_FAILED;
7996
7997 }
7998 ids2.push_back(tab->getObjectId());
7999 }
8000
8001 for (unsigned i = 0; i< 25; i++)
8002 {
8003 NdbDictionary::Table copy = tab;
8004 BaseString name;
8005 name.appfmt("%s_%u", copy.getName(), i);
8006 copy.setName(name.c_str());
8007 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
8008 if (tab == 0)
8009 {
8010 g_err << "Failed to retreive table" << copy.getName() << endl;
8011 return NDBT_FAILED;
8012
8013 }
8014 int res = pDic->dropTable(copy.getName());
8015 if (res)
8016 {
8017 g_err << "Failed to drop table" << copy.getName() << "\n"
8018 << pDic->getNdbError() << endl;
8019 return NDBT_FAILED;
8020 }
8021 }
8022
8023 /**
8024 * With Bug53944 - none of the table-id have been reused in this scenario
8025 * check that atleast 15 of the 25 have been to return OK
8026 */
8027 size_t reused = 0;
8028 for (size_t i = 0; i<ids.size(); i++)
8029 {
8030 int id = ids[i];
8031 for (size_t j = 0; j<ids2.size(); j++)
8032 {
8033 if (ids2[j] == id)
8034 {
8035 reused++;
8036 break;
8037 }
8038 }
8039 }
8040
8041 ndbout_c("reused %u table-ids out of %u",
8042 (unsigned)reused, (unsigned)ids.size());
8043
8044 if (reused >= (ids.size() >> 2))
8045 {
8046 return NDBT_OK;
8047 }
8048 else
8049 {
8050 return NDBT_FAILED;
8051 }
8052 }
8053
8054 // Bug58277 + Bug57057
8055
8056 #define CHK2(b, e) \
8057 if (!(b)) { \
8058 g_err << "ERR: " << #b << " failed at line " << __LINE__ \
8059 << ": " << e << endl; \
8060 result = NDBT_FAILED; \
8061 break; \
8062 }
8063
8064 // allow list of expected error codes which do not cause NDBT_FAILED
8065 #define CHK3(b, e, x) \
8066 if (!(b)) { \
8067 int n = sizeof(x)/sizeof(x[0]); \
8068 int i; \
8069 for (i = 0; i < n; i++) { \
8070 int s = (x[i] >= 0 ? +1 : -1); \
8071 if (e.code == s * x[i]) { \
8072 if (s == +1) \
8073 g_info << "OK: " << #b << " failed at line " << __LINE__ \
8074 << ": " << e << endl; \
8075 break; \
8076 } \
8077 } \
8078 if (i == n) { \
8079 g_err << "ERR: " << #b << " failed at line " << __LINE__ \
8080 << ": " << e << endl; \
8081 result = NDBT_FAILED; \
8082 } \
8083 break; \
8084 }
8085
8086 const char* tabName_Bug58277 = "TBug58277";
8087 const char* indName_Bug58277 = "TBug58277X1";
8088
8089 static void
sync_main_step(NDBT_Context * ctx,NDBT_Step * step,const char * state)8090 sync_main_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
8091 {
8092 // total sub-steps
8093 Uint32 sub_steps = ctx->getProperty("SubSteps", (Uint32)0);
8094 require(sub_steps != 0);
8095 // count has been reset before
8096 require(ctx->getProperty("SubCount", (Uint32)0) == 0);
8097 // set the state
8098 g_info << "step main: set " << state << endl;
8099 require(ctx->getProperty(state, (Uint32)0) == 0);
8100 ctx->setProperty(state, (Uint32)1);
8101 // wait for sub-steps
8102 ctx->getPropertyWait("SubCount", sub_steps);
8103 if (ctx->isTestStopped())
8104 return;
8105 g_info << "step main: sub-steps got " << state << endl;
8106 // reset count and state
8107 ctx->setProperty("SubCount", (Uint32)0);
8108 ctx->setProperty(state, (Uint32)0);
8109 }
8110
8111 static void
sync_sub_step(NDBT_Context * ctx,NDBT_Step * step,const char * state)8112 sync_sub_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
8113 {
8114 // wait for main step to set state
8115 g_info << "step " << step->getStepNo() << ": wait for " << state << endl;
8116 ctx->getPropertyWait(state, (Uint32)1);
8117 if (ctx->isTestStopped())
8118 return;
8119 // add to sub-step counter
8120 ctx->incProperty("SubCount");
8121 g_info << "step " << step->getStepNo() << ": got " << state << endl;
8122 // continue to run until next sync
8123 }
8124
8125 static int
runBug58277createtable(NDBT_Context * ctx,NDBT_Step * step)8126 runBug58277createtable(NDBT_Context* ctx, NDBT_Step* step)
8127 {
8128 Ndb* pNdb = GETNDB(step);
8129 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8130 int result = NDBT_OK;
8131 const int rows = ctx->getNumRecords();
8132 const char* tabname = tabName_Bug58277;
8133
8134 do
8135 {
8136 CHK2(rows > 0, "cannot use --records=0"); // others require this
8137 g_info << "create table " << tabname << endl;
8138 NdbDictionary::Table tab(tabname);
8139 const char* name[] = { "a", "b" };
8140 for (int i = 0; i <= 1; i++)
8141 {
8142 NdbDictionary::Column c(name[i]);
8143 c.setType(NdbDictionary::Column::Unsigned);
8144 c.setPrimaryKey(i == 0);
8145 c.setNullable(false);
8146 tab.addColumn(c);
8147 }
8148 if (rand() % 3 != 0)
8149 {
8150 g_info << "set FragAllLarge" << endl;
8151 tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
8152 }
8153 CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
8154 }
8155 while (0);
8156 return result;
8157 }
8158
8159 static int
runBug58277loadtable(NDBT_Context * ctx,NDBT_Step * step)8160 runBug58277loadtable(NDBT_Context* ctx, NDBT_Step* step)
8161 {
8162 Ndb* pNdb = GETNDB(step);
8163 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8164 int result = NDBT_OK;
8165 const int rows = ctx->getNumRecords();
8166 const char* tabname = tabName_Bug58277;
8167
8168 do
8169 {
8170 g_info << "load table" << endl;
8171 const NdbDictionary::Table* pTab = 0;
8172 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
8173
8174 int cnt = 0;
8175 for (int i = 0; i < rows; i++)
8176 {
8177 NdbTransaction* pTx = 0;
8178 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8179
8180 NdbOperation* pOp = 0;
8181 CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
8182 CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
8183 Uint32 aVal = i;
8184 Uint32 bVal = rand() % rows;
8185 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
8186 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
8187
8188 do
8189 {
8190 int x[] = {
8191 -630
8192 };
8193 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
8194 cnt++;
8195 }
8196 while (0);
8197 CHK2(result == NDBT_OK, "load failed");
8198 pNdb->closeTransaction(pTx);
8199 }
8200 CHK2(result == NDBT_OK, "load failed");
8201 g_info << "load " << cnt << " rows" << endl;
8202 }
8203 while (0);
8204 return result;
8205 }
8206
8207 static int
runBug58277createindex(NDBT_Context * ctx,NDBT_Step * step)8208 runBug58277createindex(NDBT_Context* ctx, NDBT_Step* step)
8209 {
8210 Ndb* pNdb = GETNDB(step);
8211 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8212 int result = NDBT_OK;
8213 const char* tabname = tabName_Bug58277;
8214 const char* indname = indName_Bug58277;
8215
8216 do
8217 {
8218 g_info << "create index " << indname << endl;
8219 NdbDictionary::Index ind(indname);
8220 ind.setTable(tabname);
8221 ind.setType(NdbDictionary::Index::OrderedIndex);
8222 ind.setLogging(false);
8223 ind.addColumn("b");
8224 CHK2(pDic->createIndex(ind) == 0, pDic->getNdbError());
8225
8226 const NdbDictionary::Index* pInd = 0;
8227 CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
8228 }
8229 while (0);
8230 return result;
8231 }
8232
8233 // separate error handling test
8234 int
runBug58277errtest(NDBT_Context * ctx,NDBT_Step * step)8235 runBug58277errtest(NDBT_Context* ctx, NDBT_Step* step)
8236 {
8237 Ndb* pNdb = GETNDB(step);
8238 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8239 const int loops = ctx->getNumLoops();
8240 int result = NDBT_OK;
8241 //const int rows = ctx->getNumRecords();
8242 NdbRestarter restarter;
8243 const char* tabname = tabName_Bug58277;
8244 const char* indname = indName_Bug58277;
8245 (void)pDic->dropTable(tabname);
8246
8247 const int errloops = loops < 5 ? loops : 5;
8248 int errloop = 0;
8249 while (!ctx->isTestStopped() && errloop < errloops)
8250 {
8251 g_info << "===== errloop " << errloop << " =====" << endl;
8252
8253 if (errloop == 0)
8254 {
8255 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
8256 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
8257 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
8258 }
8259 const NdbDictionary::Index* pInd = 0;
8260 CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
8261
8262 int errins[] = {
8263 12008, 909, // TuxNoFreeScanOp
8264 12009, 4259 // InvalidBounds
8265 };
8266 const int errcnt = (int)(sizeof(errins)/sizeof(errins[0]));
8267 for (int i = 0; i < errcnt; i += 2)
8268 {
8269 const int ei = errins[i + 0];
8270 const int ec = errins[i + 1];
8271 CHK2(restarter.insertErrorInAllNodes(ei) == 0, "value " << ei);
8272
8273 NdbTransaction* pSTx = 0;
8274 CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8275 NdbIndexScanOperation* pSOp = 0;
8276 CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
8277
8278 NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
8279 Uint32 flags = 0;
8280 CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
8281
8282 Uint32 aVal = 0;
8283 CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
8284 CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
8285 // before fixes 12009 failed to fail at once here
8286 CHK2(pSOp->nextResult(true) == -1, "failed to fail on " << ei);
8287 CHK2(pSOp->getNdbError().code == ec, "expect " << ec << " got " << pSOp->getNdbError());
8288 pNdb->closeTransaction(pSTx);
8289
8290 g_info << "error " << ei << " " << ec << " ok" << endl;
8291 CHK2(restarter.insertErrorInAllNodes(0) == 0, "value " << 0);
8292 }
8293 CHK2(result == NDBT_OK, "test error handling failed");
8294
8295 errloop++;
8296 if (errloop == errloops)
8297 {
8298 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
8299 g_info << "table " << tabname << " dropped" << endl;
8300 }
8301 }
8302 if (result != NDBT_OK)
8303 {
8304 g_info << "stop test at line " << __LINE__ << endl;
8305 ctx->stopTest();
8306 }
8307 return result;
8308 }
8309
8310 int
runBug58277drop(NDBT_Context * ctx,NDBT_Step * step)8311 runBug58277drop(NDBT_Context* ctx, NDBT_Step* step)
8312 {
8313 Ndb* pNdb = GETNDB(step);
8314 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8315 int result = NDBT_OK;
8316 const char* tabname = tabName_Bug58277;
8317 const char* indname = indName_Bug58277;
8318 int dropms = 0;
8319
8320 while (!ctx->isTestStopped())
8321 {
8322 sync_sub_step(ctx, step, "Start");
8323 if (ctx->isTestStopped())
8324 break;
8325 dropms = ctx->getProperty("DropMs", (Uint32)0);
8326 NdbSleep_MilliSleep(dropms);
8327
8328 g_info << "drop index " << indname << endl;
8329 CHK2(pDic->dropIndex(indname, tabname) == 0, pDic->getNdbError());
8330 pDic->invalidateIndex(indname, tabname);
8331 CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
8332 g_info << "drop index done" << endl;
8333
8334 sync_sub_step(ctx, step, "Stop");
8335 if (ctx->isTestStopped())
8336 break;
8337 }
8338 if (result != NDBT_OK)
8339 {
8340 g_info << "stop test at line " << __LINE__ << endl;
8341 ctx->stopTest();
8342 }
8343 return result;
8344 }
8345
8346 static int
runBug58277scanop(NDBT_Context * ctx,NDBT_Step * step,int cnt[1+3])8347 runBug58277scanop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
8348 {
8349 Ndb* pNdb = GETNDB(step);
8350 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8351 int result = NDBT_OK;
8352 const int rows = ctx->getNumRecords();
8353 const char* tabname = tabName_Bug58277;
8354 const char* indname = indName_Bug58277;
8355 const int range_max = ctx->getProperty("RANGE_MAX", (Uint32)0);
8356 require(range_max > 0);
8357 const bool scan_delete = ctx->getProperty("SCAN_DELETE", (Uint32)0);
8358
8359 do
8360 {
8361 const NdbDictionary::Index* pInd = 0;
8362 {
8363 int x[] = {
8364 4243 // Index not found
8365 };
8366 pDic->invalidateIndex(indname, tabname);
8367 CHK3((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError(), x);
8368 }
8369
8370 NdbTransaction* pSTx = 0;
8371 CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8372 NdbIndexScanOperation* pSOp = 0;
8373 CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
8374 NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
8375 Uint32 flags = 0;
8376 int range_cnt = rand() % range_max;
8377 if (range_cnt > 1 || rand() % 5 == 0)
8378 flags |= NdbIndexScanOperation::SF_MultiRange;
8379 CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
8380 g_info << "range cnt " << range_cnt << endl;
8381 for (int i = 0; i < range_cnt; )
8382 {
8383 int tlo = -1;
8384 int thi = -1;
8385 if (rand() % 5 == 0)
8386 {
8387 if (rand() % 5 != 0)
8388 tlo = 0 + rand() % 2;
8389 if (rand() % 5 != 0)
8390 thi = 2 + rand() % 2;
8391 }
8392 else
8393 tlo = 4;
8394 // apparently no bounds is not allowed (see also bug#57396)
8395 if (tlo == -1 && thi == -1)
8396 continue;
8397 Uint32 blo = 0;
8398 Uint32 bhi = 0;
8399 if (tlo != -1)
8400 {
8401 blo = rand() % rows;
8402 CHK2(pSOp->setBound("b", tlo, &blo) == 0, pSOp->getNdbError());
8403 }
8404 if (thi != -1)
8405 {
8406 bhi = rand() % (rows + 1);
8407 if (bhi < blo)
8408 bhi = rand() % (rows + 1);
8409 CHK2(pSOp->setBound("b", thi, &bhi) == 0, pSOp->getNdbError());
8410 }
8411 CHK2(pSOp->end_of_bound() == 0, pSOp->getNdbError());
8412 i++;
8413 }
8414 CHK2(result == NDBT_OK, "set bound ranges failed");
8415
8416 Uint32 aVal = 0;
8417 CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
8418 CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
8419
8420 while (1)
8421 {
8422 int ret;
8423 {
8424 int x[] = {
8425 241, // Invalid schema object version
8426 274, // Time-out in NDB, probably caused by deadlock
8427 283, // Table is being dropped
8428 284, // Table not defined in transaction coordinator
8429 910, // Index is being dropped
8430 1226 // Table is being dropped
8431 };
8432 CHK3((ret = pSOp->nextResult(true)) != -1, pSOp->getNdbError(), x);
8433 }
8434 require(ret == 0 || ret == 1);
8435 if (ret == 1)
8436 break;
8437
8438 NdbTransaction* pTx = 0;
8439 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8440
8441 while (1)
8442 {
8443 int type = 1 + rand() % 3;
8444 if (type == 2) // insert->update
8445 type = 1;
8446 if (scan_delete)
8447 type = 3;
8448 do
8449 {
8450 if (type == 1)
8451 {
8452 NdbOperation* pOp = 0;
8453 CHK2((pOp = pSOp->updateCurrentTuple(pTx)) != 0, pSOp->getNdbError());
8454 Uint32 bVal = (Uint32)(rand() % rows);
8455 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
8456 break;
8457 }
8458 if (type == 3)
8459 {
8460 CHK2(pSOp->deleteCurrentTuple(pTx) == 0, pSOp->getNdbError());
8461 break;
8462 }
8463 require(false);
8464 }
8465 while (0);
8466 CHK2(result == NDBT_OK, "scan takeover error");
8467 cnt[type]++;
8468 {
8469 int x[] = {
8470 266, // Time-out in NDB, probably caused by deadlock
8471 499, // Scan take over error
8472 631, // 631
8473 4350 // Transaction already aborted
8474 };
8475 CHK3(pTx->execute(NoCommit) == 0, pTx->getNdbError(), x);
8476 }
8477
8478 CHK2((ret = pSOp->nextResult(false)) != -1, pSOp->getNdbError());
8479 require(ret == 0 || ret == 2);
8480 if (ret == 2)
8481 break;
8482 }
8483 CHK2(result == NDBT_OK, "batch failed");
8484
8485 {
8486 int x[] = {
8487 266, // Time-out in NDB, probably caused by deadlock
8488 4350 // Transaction already aborted
8489 };
8490 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
8491 }
8492 pNdb->closeTransaction(pTx);
8493 }
8494 CHK2(result == NDBT_OK, "batch failed");
8495 pNdb->closeTransaction(pSTx);
8496 }
8497 while (0);
8498 return result;
8499 }
8500
8501 int
runBug58277scan(NDBT_Context * ctx,NDBT_Step * step)8502 runBug58277scan(NDBT_Context* ctx, NDBT_Step* step)
8503 {
8504 int result = NDBT_OK;
8505
8506 while (!ctx->isTestStopped())
8507 {
8508 sync_sub_step(ctx, step, "Start");
8509 if (ctx->isTestStopped())
8510 break;
8511 g_info << "start scan loop" << endl;
8512 while (!ctx->isTestStopped())
8513 {
8514 g_info << "start scan" << endl;
8515 int cnt[1+3] = { 0, 0, 0, 0 };
8516 CHK2(runBug58277scanop(ctx, step, cnt) == NDBT_OK, "scan failed");
8517 g_info << "scan ops " << cnt[1] << "/-/" << cnt[3] << endl;
8518
8519 if (ctx->getProperty("Stop", (Uint32)0) == 1)
8520 {
8521 sync_sub_step(ctx, step, "Stop");
8522 break;
8523 }
8524 }
8525 CHK2(result == NDBT_OK, "scan loop failed");
8526 }
8527 if (result != NDBT_OK)
8528 {
8529 g_info << "stop test at line " << __LINE__ << endl;
8530 ctx->stopTest();
8531 }
8532 return result;
8533 }
8534
8535 static int
runBug58277pkop(NDBT_Context * ctx,NDBT_Step * step,int cnt[1+3])8536 runBug58277pkop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
8537 {
8538 Ndb* pNdb = GETNDB(step);
8539 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8540 int result = NDBT_OK;
8541 const int rows = ctx->getNumRecords();
8542 const char* tabname = tabName_Bug58277;
8543
8544 do
8545 {
8546 const NdbDictionary::Table* pTab = 0;
8547 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
8548
8549 NdbTransaction* pTx = 0;
8550 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8551 NdbOperation* pOp = 0;
8552 CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
8553 int type = 1 + rand() % 3;
8554 Uint32 aVal = rand() % rows;
8555 Uint32 bVal = rand() % rows;
8556
8557 do
8558 {
8559 if (type == 1)
8560 {
8561 CHK2(pOp->updateTuple() == 0, pOp->getNdbError());
8562 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
8563 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
8564 int x[] = {
8565 266, // Time-out in NDB, probably caused by deadlock
8566 -626 // Tuple did not exist
8567 };
8568 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
8569 break;
8570 }
8571 if (type == 2)
8572 {
8573 CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
8574 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
8575 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
8576 int x[] = {
8577 266, // Time-out in NDB, probably caused by deadlock
8578 -630 // Tuple already existed when attempting to insert
8579 };
8580 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
8581 break;
8582 }
8583 if (type == 3)
8584 {
8585 CHK2(pOp->deleteTuple() == 0, pOp->getNdbError());
8586 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
8587 int x[] = {
8588 266, // Time-out in NDB, probably caused by deadlock
8589 -626 // Tuple did not exist
8590 };
8591 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
8592 break;
8593 }
8594 require(false);
8595 }
8596 while (0);
8597 CHK2(result == NDBT_OK, "pk op failed");
8598
8599 pNdb->closeTransaction(pTx);
8600 cnt[type]++;
8601 }
8602 while (0);
8603 return result;
8604 }
8605
8606 int
runBug58277pk(NDBT_Context * ctx,NDBT_Step * step)8607 runBug58277pk(NDBT_Context* ctx, NDBT_Step* step)
8608 {
8609 int result = NDBT_OK;
8610
8611 while (!ctx->isTestStopped())
8612 {
8613 sync_sub_step(ctx, step, "Start");
8614 if (ctx->isTestStopped())
8615 break;
8616
8617 g_info << "start pk loop" << endl;
8618 int cnt[1+3] = { 0, 0, 0, 0 };
8619 while (!ctx->isTestStopped())
8620 {
8621 CHK2(runBug58277pkop(ctx, step, cnt) == NDBT_OK, "pk op failed");
8622
8623 if (ctx->getProperty("Stop", (Uint32)0) == 1)
8624 {
8625 sync_sub_step(ctx, step, "Stop");
8626 break;
8627 }
8628 }
8629 CHK2(result == NDBT_OK, "pk loop failed");
8630 g_info << "pk ops " << cnt[1] << "/" << cnt[2] << "/" << cnt[3] << endl;
8631 }
8632 if (result != NDBT_OK)
8633 {
8634 g_info << "stop test at line " << __LINE__ << endl;
8635 ctx->stopTest();
8636 }
8637 return result;
8638 }
8639
8640 int
runBug58277rand(NDBT_Context * ctx,NDBT_Step * step)8641 runBug58277rand(NDBT_Context* ctx, NDBT_Step* step)
8642 {
8643 int result = NDBT_OK;
8644 NdbRestarter restarter;
8645
8646 while (!ctx->isTestStopped())
8647 {
8648 int sleepms = rand() % 5000;
8649 g_info << "rand sleep " << sleepms << " ms" << endl;
8650 NdbSleep_MilliSleep(sleepms);
8651 if (rand() % 5 == 0)
8652 {
8653 g_info << "rand force LCP" << endl;
8654 int dump1[] = { DumpStateOrd::DihStartLcpImmediately };
8655 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
8656 }
8657 }
8658 if (result != NDBT_OK)
8659 {
8660 g_info << "stop test at line " << __LINE__ << endl;
8661 ctx->stopTest();
8662 }
8663 g_info << "rand exit" << endl;
8664 return result;
8665 }
8666
8667 int
runBug58277(NDBT_Context * ctx,NDBT_Step * step)8668 runBug58277(NDBT_Context* ctx, NDBT_Step* step)
8669 {
8670 Ndb* pNdb = GETNDB(step);
8671 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8672 const int loops = ctx->getNumLoops();
8673 int result = NDBT_OK;
8674 const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
8675 NdbRestarter restarter;
8676 const char* tabname = tabName_Bug58277;
8677 const char* indname = indName_Bug58277;
8678 (void)pDic->dropTable(tabname);
8679
8680 int loop = 0;
8681 while (!ctx->isTestStopped())
8682 {
8683 g_info << "===== loop " << loop << " =====" << endl;
8684
8685 if (loop == 0)
8686 {
8687 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
8688 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
8689 }
8690
8691 if (rss_check)
8692 {
8693 g_info << "save all resource usage" << endl;
8694 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
8695 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
8696 }
8697
8698 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
8699
8700 int dropmin = 1000;
8701 int dropmax = 9000;
8702 int dropms = dropmin + rand() % (dropmax - dropmin + 1);
8703 g_info << "drop in " << dropms << " ms" << endl;
8704 ctx->setProperty("DropMs", dropms);
8705
8706 sync_main_step(ctx, step, "Start");
8707 if (ctx->isTestStopped())
8708 break;
8709
8710 // vary Stop time a bit in either direction
8711 int stopvar = rand() % 100;
8712 int stopsgn = (rand() % 2 == 0 ? +1 : -1);
8713 int stopms = dropms + stopsgn * stopvar;
8714 NdbSleep_MilliSleep(stopms);
8715
8716 sync_main_step(ctx, step, "Stop");
8717 if (ctx->isTestStopped())
8718 break;
8719
8720 // index must have been dropped
8721 pDic->invalidateIndex(indname, tabname);
8722 CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
8723
8724 if (rss_check)
8725 {
8726 g_info << "check all resource usage" << endl;
8727 int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
8728 CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
8729
8730 g_info << "check cluster is up" << endl;
8731 CHK2(restarter.waitClusterStarted() == 0, "failed");
8732 }
8733
8734 if (++loop == loops)
8735 {
8736 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
8737 g_info << "table " << tabname << " dropped" << endl;
8738 break;
8739 }
8740 }
8741
8742 g_info << "stop test at line " << __LINE__ << endl;
8743 ctx->stopTest();
8744 return result;
8745 }
8746
8747 int
runBug57057(NDBT_Context * ctx,NDBT_Step * step)8748 runBug57057(NDBT_Context* ctx, NDBT_Step* step)
8749 {
8750 Ndb* pNdb = GETNDB(step);
8751 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8752 const int loops = ctx->getNumLoops();
8753 int result = NDBT_OK;
8754 const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
8755 NdbRestarter restarter;
8756 const char* tabname = tabName_Bug58277;
8757 //const char* indname = indName_Bug58277;
8758 (void)pDic->dropTable(tabname);
8759
8760 int loop = 0;
8761 while (!ctx->isTestStopped())
8762 {
8763 g_info << "===== loop " << loop << " =====" << endl;
8764
8765 if (loop == 0)
8766 {
8767 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
8768 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
8769 }
8770
8771 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
8772
8773 if (rss_check)
8774 {
8775 g_info << "save all resource usage" << endl;
8776 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
8777 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
8778 }
8779
8780 int dropmin = 1000;
8781 int dropmax = 2000;
8782 int dropms = dropmin + rand() % (dropmax - dropmin + 1);
8783 int stopms = dropms;
8784
8785 sync_main_step(ctx, step, "Start");
8786 if (ctx->isTestStopped())
8787 break;
8788
8789 g_info << "stop in " << stopms << " ms" << endl;
8790 NdbSleep_MilliSleep(stopms);
8791
8792 sync_main_step(ctx, step, "Stop");
8793 if (ctx->isTestStopped())
8794 break;
8795
8796 if (rss_check)
8797 {
8798 g_info << "check all resource usage" << endl;
8799 int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
8800 CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
8801
8802 g_info << "check cluster is up" << endl;
8803 CHK2(restarter.waitClusterStarted() == 0, "failed");
8804 }
8805
8806 if (++loop == loops)
8807 {
8808 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
8809 g_info << "table " << tabname << " dropped" << endl;
8810 break;
8811 }
8812 }
8813
8814 g_info << "stop test at line " << __LINE__ << endl;
8815 ctx->stopTest();
8816 return result;
8817 }
8818
8819 NDBT_TESTSUITE(testDict);
8820 TESTCASE("testDropDDObjects",
8821 "* 1. start cluster\n"
8822 "* 2. Create LFG\n"
8823 "* 3. create TS\n"
8824 "* 4. run DropDDObjects\n"
8825 "* 5. Verify DropDDObjectsRestart worked\n"){
8826 INITIALIZER(runWaitStarted);
8827 INITIALIZER(runDropDDObjects);
8828 INITIALIZER(testDropDDObjectsSetup);
8829 STEP(runDropDDObjects);
8830 FINALIZER(DropDDObjectsVerify);
8831 }
8832
8833 TESTCASE("Bug29501",
8834 "* 1. start cluster\n"
8835 "* 2. Restart 1 node -abort -nostart\n"
8836 "* 3. create LFG\n"
8837 "* 4. Restart data node\n"
8838 "* 5. Restart 1 node -nostart\n"
8839 "* 6. Drop LFG\n"){
8840 INITIALIZER(runWaitStarted);
8841 INITIALIZER(runDropDDObjects);
8842 STEP(runBug29501);
8843 FINALIZER(runDropDDObjects);
8844 }
8845 TESTCASE("CreateAndDrop",
8846 "Try to create and drop the table loop number of times\n"){
8847 INITIALIZER(runCreateAndDrop);
8848 }
8849 TESTCASE("CreateAndDropAtRandom",
8850 "Try to create and drop table at random loop number of times\n"
8851 "Uses all available tables\n"
8852 "Uses error insert 4013 to make TUP verify table descriptor"){
8853 INITIALIZER(runCreateAndDropAtRandom);
8854 }
8855 TESTCASE("CreateAndDropIndexes",
8856 "Like CreateAndDropAtRandom but also creates random ordered\n"
8857 "indexes and loads data as a simple check of index operation"){
8858 TC_PROPERTY("CreateIndexes", 1);
8859 TC_PROPERTY("LoadData", 1);
8860 INITIALIZER(runCreateAndDropAtRandom);
8861 }
8862 TESTCASE("CreateAndDropWithData",
8863 "Try to create and drop the table when it's filled with data\n"
8864 "do this loop number of times\n"){
8865 INITIALIZER(runCreateAndDropWithData);
8866 }
8867 TESTCASE("CreateAndDropDuring",
8868 "Try to create and drop the table when other thread is using it\n"
8869 "do this loop number of times\n"){
8870 STEP(runCreateAndDropDuring);
8871 STEP(runUseTableUntilStopped);
8872 }
8873 TESTCASE("CreateInvalidTables",
8874 "Try to create the invalid tables we have defined\n"){
8875 INITIALIZER(runCreateInvalidTables);
8876 }
8877 TESTCASE("CreateTableWhenDbIsFull",
8878 "Try to create a new table when db already is full\n"){
8879 INITIALIZER(runCreateTheTable);
8880 INITIALIZER(runFillTable);
8881 INITIALIZER(runCreateTableWhenDbIsFull);
8882 INITIALIZER(runDropTableWhenDbIsFull);
8883 FINALIZER(runDropTheTable);
8884 }
8885 TESTCASE("FragmentTypeSingle",
8886 "Create the table with fragment type Single\n"){
8887 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragSingle);
8888 INITIALIZER(runTestFragmentTypes);
8889 }
8890 TESTCASE("FragmentTypeAllSmall",
8891 "Create the table with fragment type AllSmall\n"){
8892 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllSmall);
8893 INITIALIZER(runTestFragmentTypes);
8894 }
8895 TESTCASE("FragmentTypeAllMedium",
8896 "Create the table with fragment type AllMedium\n"){
8897 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllMedium);
8898 INITIALIZER(runTestFragmentTypes);
8899 }
8900 TESTCASE("FragmentTypeAllLarge",
8901 "Create the table with fragment type AllLarge\n"){
8902 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllLarge);
8903 INITIALIZER(runTestFragmentTypes);
8904 }
8905 TESTCASE("TemporaryTables",
8906 "Create the table as temporary and make sure it doesn't\n"
8907 "contain any data when system is restarted\n"){
8908 INITIALIZER(runTestTemporaryTables);
8909 }
8910 TESTCASE("CreateMaxTables",
8911 "Create tables until db says that it can't create any more\n"){
8912 TC_PROPERTY("tables", 1000);
8913 INITIALIZER(runCreateMaxTables);
8914 INITIALIZER(runDropMaxTables);
8915 }
8916 TESTCASE("PkSizes",
8917 "Create tables with all different primary key sizes.\n"\
8918 "Test all data operations insert, update, delete etc.\n"\
8919 "Drop table."){
8920 INITIALIZER(runPkSizes);
8921 }
8922 TESTCASE("StoreFrm",
8923 "Test that a frm file can be properly stored as part of the\n"
8924 "data in Dict."){
8925 INITIALIZER(runStoreFrm);
8926 }
8927 TESTCASE("GetPrimaryKey",
8928 "Test the function NdbDictionary::Column::getPrimaryKey\n"
8929 "It should return true only if the column is part of \n"
8930 "the primary key in the table"){
8931 INITIALIZER(runGetPrimaryKey);
8932 }
8933 TESTCASE("StoreFrmError",
8934 "Test that a frm file with too long length can't be stored."){
8935 INITIALIZER(runStoreFrmError);
8936 }
8937 TESTCASE("TableRename",
8938 "Test basic table rename"){
8939 INITIALIZER(runTableRename);
8940 }
8941 TESTCASE("TableRenameSR",
8942 "Test that table rename can handle system restart"){
8943 INITIALIZER(runTableRenameSR);
8944 }
8945 TESTCASE("DictionaryPerf",
8946 ""){
8947 INITIALIZER(runTestDictionaryPerf);
8948 }
8949 TESTCASE("CreateLogfileGroup", ""){
8950 INITIALIZER(runCreateLogfileGroup);
8951 }
8952 TESTCASE("CreateTablespace", ""){
8953 INITIALIZER(runCreateTablespace);
8954 }
8955 TESTCASE("CreateDiskTable", ""){
8956 INITIALIZER(runCreateDiskTable);
8957 }
8958 TESTCASE("FailAddFragment",
8959 "Fail add fragment or attribute in ACC or TUP or TUX\n"){
8960 INITIALIZER(runFailAddFragment);
8961 }
8962 TESTCASE("Restart_NF1",
8963 "DICT ops during node graceful shutdown (not master)"){
8964 TC_PROPERTY("Restart_NF_ops", 1);
8965 TC_PROPERTY("Restart_NF_type", 1);
8966 STEP(runRestarts);
8967 STEP(runDictOps);
8968 }
8969 TESTCASE("Restart_NF2",
8970 "DICT ops during node shutdown abort (not master)"){
8971 TC_PROPERTY("Restart_NF_ops", 1);
8972 TC_PROPERTY("Restart_NF_type", 2);
8973 STEP(runRestarts);
8974 STEP(runDictOps);
8975 }
8976 TESTCASE("Restart_NR1",
8977 "DICT ops during node startup (not master)"){
8978 TC_PROPERTY("Restart_NR_ops", 1);
8979 STEP(runRestarts);
8980 STEP(runDictOps);
8981 }
8982 TESTCASE("Restart_NR2",
8983 "DICT ops during node startup with crash inserts (not master)"){
8984 TC_PROPERTY("Restart_NR_ops", 1);
8985 TC_PROPERTY("Restart_NR_error", 1);
8986 STEP(runRestarts);
8987 STEP(runDictOps);
8988 }
8989 TESTCASE("TableAddAttrs",
8990 "Add attributes to an existing table using alterTable()"){
8991 INITIALIZER(runTableAddAttrs);
8992 }
8993 TESTCASE("TableAddAttrsDuring",
8994 "Try to add attributes to the table when other thread is using it\n"
8995 "do this loop number of times\n"){
8996 INITIALIZER(runCreateTheTable);
8997 STEP(runTableAddAttrsDuring);
8998 STEP(runUseTableUntilStopped2);
8999 STEP(runUseTableUntilStopped3);
9000 FINALIZER(runDropTheTable);
9001 }
9002 TESTCASE("TableAddAttrsDuringError",
9003 "Try to add attributes to the table when other thread is using it\n"
9004 "do this loop number of times\n"){
9005 TC_PROPERTY("AbortAlter", 1);
9006 INITIALIZER(runCreateTheTable);
9007 STEP(runTableAddAttrsDuring);
9008 STEP(runUseTableUntilStopped2);
9009 STEP(runUseTableUntilStopped3);
9010 FINALIZER(runDropTheTable);
9011 }
9012 TESTCASE("Bug21755",
9013 ""){
9014 INITIALIZER(runBug21755);
9015 }
9016 TESTCASE("DictRestart",
9017 ""){
9018 INITIALIZER(runDictRestart);
9019 }
9020 TESTCASE("Bug24631",
9021 ""){
9022 INITIALIZER(runBug24631);
9023 }
9024 TESTCASE("Bug36702", "")
9025 {
9026 INITIALIZER(runDropDDObjects);
9027 INITIALIZER(runBug36072);
9028 FINALIZER(restartClusterInitial);
9029 }
9030 TESTCASE("Bug29186",
9031 ""){
9032 INITIALIZER(runBug29186);
9033 }
9034 TESTCASE("Bug48604",
9035 "Online ordered index build.\n"
9036 "Complements testOIBasic -case f"){
9037 STEP(runBug48604);
9038 STEP(runBug48604ops);
9039 #if 0 // for future MT test
9040 STEP(runBug48604ops);
9041 STEP(runBug48604ops);
9042 STEP(runBug48604ops);
9043 #endif
9044 }
9045 TESTCASE("Bug54651", ""){
9046 INITIALIZER(runBug54651);
9047 }
9048 /** telco-6.4 **/
9049 TESTCASE("SchemaTrans",
9050 "Schema transactions"){
9051 ALL_TABLES();
9052 STEP(runSchemaTrans);
9053 }
9054 TESTCASE("FailCreateHashmap",
9055 "Fail create hashmap")
9056 {
9057 INITIALIZER(runFailCreateHashmap);
9058 }
9059 TESTCASE("FailAddPartition",
9060 "Fail add partition")
9061 {
9062 INITIALIZER(runFailAddPartition);
9063 }
9064 TESTCASE("TableAddPartitions",
9065 "Add partitions to an existing table using alterTable()"){
9066 INITIALIZER(runTableAddPartition);
9067 }
9068 TESTCASE("Bug41905",
9069 ""){
9070 STEP(runBug41905);
9071 STEP(runBug41905getTable);
9072 }
9073 TESTCASE("Bug46552", "")
9074 {
9075 INITIALIZER(runBug46552);
9076 }
9077 TESTCASE("Bug46585", "")
9078 {
9079 INITIALIZER(runWaitStarted);
9080 INITIALIZER(runBug46585);
9081 }
9082 TESTCASE("Bug53944", "")
9083 {
9084 INITIALIZER(runBug53944);
9085 }
9086 TESTCASE("Bug58277",
9087 "Dropping busy ordered index can crash data node.\n"
9088 "Give any tablename as argument (T1)"){
9089 TC_PROPERTY("RSS_CHECK", (Uint32)true);
9090 TC_PROPERTY("RANGE_MAX", (Uint32)5);
9091 INITIALIZER(runBug58277errtest);
9092 STEP(runBug58277);
9093 // sub-steps 2-8 synced with main step
9094 TC_PROPERTY("SubSteps", 7);
9095 STEP(runBug58277drop);
9096 /*
9097 * A single scan update can show the bug but this is not likely.
9098 * Add more scan updates. Also add PK ops for other asserts.
9099 */
9100 STEP(runBug58277scan);
9101 STEP(runBug58277scan);
9102 STEP(runBug58277scan);
9103 STEP(runBug58277scan);
9104 STEP(runBug58277pk);
9105 STEP(runBug58277pk);
9106 // kernel side scans (eg. LCP) for resource usage check
9107 STEP(runBug58277rand);
9108 }
9109 TESTCASE("Bug57057",
9110 "MRR + delete leaks stored procs (fixed under Bug58277).\n"
9111 "Give any tablename as argument (T1)"){
9112 TC_PROPERTY("RSS_CHECK", (Uint32)true);
9113 TC_PROPERTY("RANGE_MAX", (Uint32)100);
9114 TC_PROPERTY("SCAN_DELETE", (Uint32)1);
9115 STEP(runBug57057);
9116 TC_PROPERTY("SubSteps", 1);
9117 STEP(runBug58277scan);
9118 }
9119 NDBT_TESTSUITE_END(testDict);
9120
main(int argc,const char ** argv)9121 int main(int argc, const char** argv){
9122 ndb_init();
9123 NDBT_TESTSUITE_INSTANCE(testDict);
9124 // Tables should not be auto created
9125 testDict.setCreateTable(false);
9126 myRandom48Init((long)NdbTick_CurrentMillisecond());
9127 return testDict.execute(argc, argv);
9128 }
9129