1 /*
2 Copyright (c) 2003, 2021, Oracle and/or its affiliates.
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 #include <../src/kernel/ndbd.hpp>
43
44 #define ERR_INSERT_MASTER_FAILURE1 6013
45 #define ERR_INSERT_MASTER_FAILURE2 6014
46 #define ERR_INSERT_MASTER_FAILURE3 6015
47
48 #define ERR_INSERT_PARTIAL_START_FAIL 6140
49 #define ERR_INSERT_PARTIAL_PARSE_FAIL 6141
50 #define ERR_INSERT_PARTIAL_FLUSH_PREPARE_FAIL 6142
51 #define ERR_INSERT_PARTIAL_PREPARE_FAIL 6143
52 #define ERR_INSERT_PARTIAL_ABORT_PARSE_FAIL 6144
53 #define ERR_INSERT_PARTIAL_ABORT_PREPARE_FAIL 6145
54 #define ERR_INSERT_PARTIAL_FLUSH_COMMIT_FAIL 6146
55 #define ERR_INSERT_PARTIAL_COMMIT_FAIL 6147
56 #define ERR_INSERT_PARTIAL_FLUSH_COMPLETE_FAIL 6148
57 #define ERR_INSERT_PARTIAL_COMPLETE_FAIL 6149
58 #define ERR_INSERT_PARTIAL_END_FAIL 6150
59
60 #define FAIL_BEGIN 0
61 #define FAIL_CREATE 1
62 #define FAIL_END 2
63 #define SUCCEED_COMMIT 3
64 #define SUCCEED_ABORT 4
65
66 #define ndb_master_failure 1
67
68 char f_tablename[256];
69
70 #define CHECK(b) if (!(b)) { \
71 g_err << "ERR: "<< step->getName() \
72 << " failed on line " << __LINE__ << endl; \
73 result = NDBT_FAILED; \
74 break; }
75
76 #define CHECK2(b, c) if (!(b)) { \
77 g_err << "ERR: "<< step->getName() \
78 << " failed on line " << __LINE__ << ": " << c << endl; \
79 result = NDBT_FAILED; \
80 goto end; }
81
runLoadTable(NDBT_Context * ctx,NDBT_Step * step)82 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
83 Ndb* pNdb = GETNDB(step);
84 int records = ctx->getNumRecords();
85 HugoTransactions hugoTrans(*ctx->getTab());
86 if (hugoTrans.loadTable(pNdb, records) != 0){
87 return NDBT_FAILED;
88 }
89 return NDBT_OK;
90 }
91
runCreateInvalidTables(NDBT_Context * ctx,NDBT_Step * step)92 int runCreateInvalidTables(NDBT_Context* ctx, NDBT_Step* step){
93 Ndb* pNdb = GETNDB(step);
94 int result = NDBT_OK;
95
96 char failTabName[256];
97
98 const int expectedDictErrors[6]= {720,
99 4317,
100 737,
101 739,
102 736,
103 740 };
104
105 for (int i = 0; i < 10; i++){
106 BaseString::snprintf(failTabName, 256, "F%d", i);
107
108 const NdbDictionary::Table* pFailTab = NDBT_Tables::getTable(failTabName);
109 if (pFailTab != NULL){
110 ndbout << "|- " << failTabName << endl;
111
112 // Try to create table in db
113 if (pFailTab->createTableInDb(pNdb) == 0){
114 ndbout << failTabName << " created, this was not expected"<< endl;
115 result = NDBT_FAILED;
116 }
117
118 // Ensure any error is roughly as expected
119 int errorCode=pNdb->getDictionary()->getNdbError().code;
120 bool errorOk= false;
121 for (int e=0; e < 6; e++)
122 errorOk |= (errorCode == expectedDictErrors[e]);
123
124 if (!errorOk)
125 {
126 ndbout << "Failure, got dict error : " << pNdb->getDictionary()->
127 getNdbError().code << endl;
128 return NDBT_FAILED;
129 }
130
131 // Verify that table is not in db
132 const NdbDictionary::Table* pTab2 =
133 NDBT_Table::discoverTableFromDb(pNdb, failTabName) ;
134 if (pTab2 != NULL){
135 ndbout << failTabName << " was found in DB, this was not expected"<< endl;
136 result = NDBT_FAILED;
137 if (pFailTab->equal(*pTab2) == true){
138 ndbout << "It was equal" << endl;
139 } else {
140 ndbout << "It was not equal" << endl;
141 }
142 int records = 1000;
143 HugoTransactions hugoTrans(*pTab2);
144 if (hugoTrans.loadTable(pNdb, records) != 0){
145 ndbout << "It can NOT be loaded" << endl;
146 } else{
147 ndbout << "It can be loaded" << endl;
148
149 UtilTransactions utilTrans(*pTab2);
150 if (utilTrans.clearTable(pNdb, records, 64) != 0){
151 ndbout << "It can NOT be cleared" << endl;
152 } else{
153 ndbout << "It can be cleared" << endl;
154 }
155 }
156
157 if (pNdb->getDictionary()->dropTable(pTab2->getName()) == -1){
158 ndbout << "It can NOT be dropped" << endl;
159 } else {
160 ndbout << "It can be dropped" << endl;
161 }
162 }
163 }
164 }
165 return result;
166 }
167
runCreateTheTable(NDBT_Context * ctx,NDBT_Step * step)168 int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
169 Ndb* pNdb = GETNDB(step);
170 const NdbDictionary::Table* pTab = ctx->getTab();
171
172 // Try to create table in db
173 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
174 return NDBT_FAILED;
175 }
176
177 // Verify that table is in db
178 const NdbDictionary::Table* pTab2 =
179 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
180 if (pTab2 == NULL){
181 ndbout << pTab->getName() << " was not found in DB"<< endl;
182 return NDBT_FAILED;
183 }
184 ctx->setTab(pTab2);
185
186 BaseString::snprintf(f_tablename, sizeof(f_tablename),
187 "%s", pTab->getName());
188
189 return NDBT_OK;
190 }
191
runDropTheTable(NDBT_Context * ctx,NDBT_Step * step)192 int runDropTheTable(NDBT_Context* ctx, NDBT_Step* step){
193 Ndb* pNdb = GETNDB(step);
194
195 // Drop table
196 pNdb->getDictionary()->dropTable(f_tablename);
197
198 return NDBT_OK;
199 }
200
runSetDropTableConcurrentLCP(NDBT_Context * ctx,NDBT_Step * step)201 int runSetDropTableConcurrentLCP(NDBT_Context *ctx, NDBT_Step *step)
202 {
203 NdbRestarter restarter;
204 if(restarter.insertErrorInAllNodes(5088) != 0)
205 {
206 g_err << "failed to set error insert"<< endl;
207 return NDBT_FAILED;
208 }
209 return NDBT_OK;
210 }
211
runSetMinTimeBetweenLCP(NDBT_Context * ctx,NDBT_Step * step)212 int runSetMinTimeBetweenLCP(NDBT_Context *ctx, NDBT_Step *step)
213 {
214 NdbRestarter restarter;
215 int result;
216 int val = DumpStateOrd::DihMinTimeBetweenLCP;
217 if (restarter.dumpStateAllNodes(&val, 1) != 0)
218 {
219 do { CHECK(0); } while(0);
220 g_err << "Failed to set LCP to min value" << endl;
221 return NDBT_FAILED;
222 }
223 return NDBT_OK;
224 }
225
runResetMinTimeBetweenLCP(NDBT_Context * ctx,NDBT_Step * step)226 int runResetMinTimeBetweenLCP(NDBT_Context *ctx, NDBT_Step *step)
227 {
228 NdbRestarter restarter;
229 int result;
230 int val2[] = { DumpStateOrd::DihMinTimeBetweenLCP, 0 };
231 if (restarter.dumpStateAllNodes(val2, 2) != 0)
232 {
233 do { CHECK(0); } while(0);
234 g_err << "Failed to set LCP to min value" << endl;
235 return NDBT_FAILED;
236 }
237 return NDBT_OK;
238 }
239
runSetDropTableConcurrentLCP2(NDBT_Context * ctx,NDBT_Step * step)240 int runSetDropTableConcurrentLCP2(NDBT_Context *ctx, NDBT_Step *step)
241 {
242 NdbRestarter restarter;
243 if(restarter.insertErrorInAllNodes(5089) != 0)
244 {
245 g_err << "failed to set error insert"<< endl;
246 return NDBT_FAILED;
247 }
248 return NDBT_OK;
249 }
250
251 /*******
252 * Precondition:
253 * 'DataMemory' has been filled until insertion failed
254 * due to 'DbIsFull'. The table 'TRANSACTION' should
255 * not exist in the DB
256 *
257 * Test:
258 * Creation of the (empty) table 'TRANSACTION'
259 * should succeed even if 'DbIsFull'. However,
260 * insertion of the first row should fail.
261 *
262 * Postcond:
263 * The created table 'TRANSACTION is removed.
264 * DataMemory is still full.
265 */
runCreateTableWhenDbIsFull(NDBT_Context * ctx,NDBT_Step * step)266 int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
267 Ndb* pNdb = GETNDB(step);
268 int result = NDBT_OK;
269 const char* tabName = "TRANSACTION"; //Use a util table
270
271 // Precondition is that 'DataMemory' filled to max.
272 // So we skip test if a DiskStorage table was filled
273 for (Uint32 i = 0; i<(Uint32)ctx->getTab()->getNoOfColumns(); i++)
274 {
275 if (ctx->getTab()->getColumn(i)->getStorageType() ==
276 NdbDictionary::Column::StorageTypeDisk)
277 {
278 ndbout << "Skip test for *disk* tables" << endl;
279 return NDBT_OK;
280 }
281 }
282
283 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
284 while (pTab != NULL){ //Always 'break' without looping
285 ndbout << "|- " << tabName << endl;
286
287 // Verify that table is not in db
288 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
289 ndbout << tabName << " was found in DB"<< endl;
290 result = NDBT_FAILED;
291 break;
292 }
293
294 // Create (empty) table in db, should succeed even if 'DbIsFull'
295 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
296 ndbout << tabName << " was not created when DB is full"<< endl;
297 result = NDBT_FAILED;
298 break;
299 }
300
301 // Verify that table is now in db
302 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) == NULL){
303 ndbout << tabName << " was not visible in DB"<< endl;
304 result = NDBT_FAILED;
305 break;
306 }
307
308 // As 'DbIsFull', insert of a single record should fail
309 HugoOperations hugoOps(*pTab);
310 CHECK(hugoOps.startTransaction(pNdb) == 0);
311 CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
312 CHECK(hugoOps.execute_Commit(pNdb) != 0); //Should fail
313 CHECK(hugoOps.closeTransaction(pNdb) == 0);
314
315 break;
316 }
317
318 // Drop table (if exist, so we dont care about errors)
319 pNdb->getDictionary()->dropTable(tabName);
320 return result;
321 }
322
runDropTableWhenDbIsFull(NDBT_Context * ctx,NDBT_Step * step)323 int runDropTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
324 Ndb* pNdb = GETNDB(step);
325 int result = NDBT_OK;
326 const char* tabName = "TRANSACTION"; //Use a util table
327
328 const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(pNdb, tabName);
329 if (pTab != NULL){
330 ndbout << "|- TRANSACTION" << endl;
331
332 // Try to drop table in db
333 if (pNdb->getDictionary()->dropTable(pTab->getName()) == -1){
334 result = NDBT_FAILED;
335 }
336
337 // Verify that table is not in db
338 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
339 ndbout << tabName << " was found in DB"<< endl;
340 result = NDBT_FAILED;
341 }
342 }
343
344 return result;
345
346 }
347
348
runCreateAndDrop(NDBT_Context * ctx,NDBT_Step * step)349 int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
350 Ndb* pNdb = GETNDB(step);
351 int loops = ctx->getNumLoops();
352 int i = 0;
353
354 const NdbDictionary::Table* pTab = ctx->getTab();
355 ndbout << "|- " << pTab->getName() << endl;
356
357 while (i < loops){
358
359 ndbout << i << ": ";
360 // Try to create table in db
361 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
362 return NDBT_FAILED;
363 }
364
365 // Verify that table is in db
366 const NdbDictionary::Table* pTab2 =
367 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
368 if (pTab2 == NULL){
369 ndbout << pTab->getName() << " was not found in DB"<< endl;
370 return NDBT_FAILED;
371 }
372
373 if (pNdb->getDictionary()->dropTable(pTab2->getName())){
374 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
375 return NDBT_FAILED;
376 }
377
378 // Verify that table is not in db
379 const NdbDictionary::Table* pTab3 =
380 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
381 if (pTab3 != NULL){
382 ndbout << pTab3->getName() << " was found in DB"<< endl;
383 return NDBT_FAILED;
384 }
385 i++;
386 }
387
388 return NDBT_OK;
389 }
390
runCreateAndDropAtRandom(NDBT_Context * ctx,NDBT_Step * step)391 int runCreateAndDropAtRandom(NDBT_Context* ctx, NDBT_Step* step)
392 {
393 myRandom48Init((long)NdbTick_CurrentMillisecond());
394 Ndb* pNdb = GETNDB(step);
395 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
396 int loops = ctx->getNumLoops();
397 int records = ctx->getNumRecords();
398
399 int numAllTables = NDBT_Tables::getNumTables();
400 struct TabList {
401 int exists; // -1 = skip, 0 = no, 1 = yes
402 const NdbDictionary::Table* pTab; // retrieved
403 TabList() { exists = -1; pTab = 0; }
404 };
405 TabList* tabList = new TabList [ numAllTables ];
406 int numTables = 0;
407 int num;
408 for (num = 0; num < numAllTables; num++) {
409 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num);
410 if (pTab->checkColumns(0, 0) & 2) // skip disk
411 continue;
412 tabList[num].exists = 0;
413 (void)pDic->dropTable(pTab->getName());
414 numTables++;
415 }
416 int numExists = 0;
417
418 const bool createIndexes = ctx->getProperty("CreateIndexes");
419 const bool loadData = ctx->getProperty("LoadData");
420
421 NdbRestarter restarter;
422 int result = NDBT_OK;
423 int bias = 1; // 0-less 1-more
424 int i = 0;
425
426 while (i < loops && result == NDBT_OK) {
427 num = myRandom48(numAllTables);
428 if (tabList[num].exists == -1)
429 continue;
430 g_info << "loop " << i << " tabs " << numExists << "/" << numTables << endl;
431 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num);
432 char tabName[200];
433 strcpy(tabName, pTab->getName());
434
435 if (tabList[num].exists == 0) {
436 if (bias == 0 && myRandom48(100) < 80)
437 continue;
438 g_info << tabName << ": create" << endl;
439 if (pDic->createTable(*pTab) != 0) {
440 const NdbError err = pDic->getNdbError();
441 g_err << tabName << ": create failed: " << err << endl;
442 result = NDBT_FAILED;
443 break;
444 }
445 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
446 if (pTab2 == NULL) {
447 const NdbError err = pDic->getNdbError();
448 g_err << tabName << ": verify create failed: " << err << endl;
449 result = NDBT_FAILED;
450 break;
451 }
452 tabList[num].pTab = pTab2;
453 if (loadData) {
454 g_info << tabName << ": load data" << endl;
455 HugoTransactions hugoTrans(*pTab2);
456 if (hugoTrans.loadTable(pNdb, records) != 0) {
457 g_err << tabName << ": loadTable failed" << endl;
458 result = NDBT_FAILED;
459 break;
460 }
461 }
462 if (createIndexes) {
463 int icount = myRandom48(10);
464 int inum;
465 for (inum = 0; inum < icount; inum++) {
466 const int tcols = pTab2->getNoOfColumns();
467 require(tcols != 0);
468 int icols = 1 + myRandom48(tcols);
469 if (icols > NDB_MAX_ATTRIBUTES_IN_INDEX)
470 icols = NDB_MAX_ATTRIBUTES_IN_INDEX;
471 char indName[200];
472 sprintf(indName, "%s_X%d", tabName, inum);
473 NdbDictionary::Index ind(indName);
474 ind.setTable(tabName);
475 ind.setType(NdbDictionary::Index::OrderedIndex);
476 ind.setLogging(false);
477 Bitmask<MAX_ATTRIBUTES_IN_TABLE> mask;
478 char ilist[200];
479 ilist[0] = 0;
480 int ic;
481 for (ic = 0; ic < icols; ic++) {
482 int tc = myRandom48(tcols);
483 const NdbDictionary::Column* c = pTab2->getColumn(tc);
484 require(c != 0);
485 if (mask.get(tc) ||
486 c->getType() == NdbDictionary::Column::Blob ||
487 c->getType() == NdbDictionary::Column::Text ||
488 c->getType() == NdbDictionary::Column::Bit ||
489 c->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
490 continue;
491 ind.addColumn(*c);
492 mask.set(tc);
493 sprintf(ilist + strlen(ilist), " %d", tc);
494 }
495 if (mask.isclear())
496 continue;
497 g_info << indName << ": columns:" << ilist << endl;
498 if (pDic->createIndex(ind) == 0) {
499 g_info << indName << ": created" << endl;
500 } else {
501 const NdbError err = pDic->getNdbError();
502 g_err << indName << ": create index failed: " << err << endl;
503 if (err.code != 826 && // Too many tables and attributes..
504 err.code != 903 && // Too many ordered indexes..
505 err.code != 904 && // Out of fragment records..
506 err.code != 905 && // Out of attribute records..
507 err.code != 707 && // No more table metadata records..
508 err.code != 708) // No more attribute metadata records..
509 {
510 result = NDBT_FAILED;
511 break;
512 }
513 }
514 }
515 }
516 if (loadData) {
517 // first update a random table to flush global variables
518 int num3 = 0;
519 while (1) {
520 num3 = myRandom48(numAllTables);
521 if (num == num3 || tabList[num3].exists == 1)
522 break;
523 }
524 const NdbDictionary::Table* pTab3 = tabList[num3].pTab;
525 require(pTab3 != 0);
526 char tabName3[200];
527 strcpy(tabName3, pTab3->getName());
528 HugoTransactions hugoTrans(*pTab3);
529 g_info << tabName3 << ": update data" << endl;
530 if (hugoTrans.pkUpdateRecords(pNdb, records) != 0) {
531 g_err << tabName3 << ": pkUpdateRecords failed" << endl;
532 result = NDBT_FAILED;
533 break;
534 }
535 }
536 if (loadData) {
537 HugoTransactions hugoTrans(*pTab2);
538 g_info << tabName << ": update data" << endl;
539 if (hugoTrans.pkUpdateRecords(pNdb, records) != 0) {
540 g_err << "pkUpdateRecords failed" << endl;
541 result = NDBT_FAILED;
542 break;
543 }
544 }
545 tabList[num].exists = 1;
546 require(numExists < numTables);
547 numExists++;
548 if (numExists == numTables)
549 bias = 0;
550 }
551 else if (tabList[num].exists == 1) {
552 if (bias == 1 && myRandom48(100) < 80)
553 continue;
554 g_info << tabName << ": drop" << endl;
555 if (restarter.insertErrorInAllNodes(4013) != 0) {
556 g_err << "error insert failed" << endl;
557 result = NDBT_FAILED;
558 break;
559 }
560 if (pDic->dropTable(tabName) != 0) {
561 const NdbError err = pDic->getNdbError();
562 g_err << tabName << ": drop failed: " << err << endl;
563 result = NDBT_FAILED;
564 break;
565 }
566 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
567 if (pTab2 != NULL) {
568 g_err << tabName << ": verify drop: table exists" << endl;
569 result = NDBT_FAILED;
570 break;
571 }
572 if (pDic->getNdbError().code != 709 &&
573 pDic->getNdbError().code != 723) {
574 const NdbError err = pDic->getNdbError();
575 g_err << tabName << ": verify drop: " << err << endl;
576 result = NDBT_FAILED;
577 break;
578 }
579 tabList[num].exists = 0;
580 require(numExists > 0);
581 numExists--;
582 if (numExists == 0)
583 bias = 1;
584 }
585 i++;
586 }
587
588 for (num = 0; num < numAllTables; num++)
589 if (tabList[num].exists == 1)
590 pDic->dropTable(NDBT_Tables::getTable(num)->getName());
591
592 delete [] tabList;
593 return result;
594 }
595
596
runCreateAndDropWithData(NDBT_Context * ctx,NDBT_Step * step)597 int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
598 Ndb* pNdb = GETNDB(step);
599 int loops = ctx->getNumLoops();
600 int records = ctx->getNumRecords();
601 int i = 0;
602
603 NdbRestarter restarter;
604 int val = DumpStateOrd::DihMinTimeBetweenLCP;
605 if(restarter.dumpStateAllNodes(&val, 1) != 0){
606 int result;
607 do { CHECK(0); } while (0);
608 g_err << "Unable to change timebetween LCP" << endl;
609 return NDBT_FAILED;
610 }
611
612 const NdbDictionary::Table* pTab = ctx->getTab();
613 ndbout << "|- " << pTab->getName() << endl;
614
615 while (i < loops){
616 ndbout << i << ": ";
617 // Try to create table in db
618
619 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
620 return NDBT_FAILED;
621 }
622
623 // Verify that table is in db
624 const NdbDictionary::Table* pTab2 =
625 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
626 if (pTab2 == NULL){
627 ndbout << pTab->getName() << " was not found in DB"<< endl;
628 return NDBT_FAILED;
629 }
630
631 HugoTransactions hugoTrans(*pTab2);
632 if (hugoTrans.loadTable(pNdb, records) != 0){
633 return NDBT_FAILED;
634 }
635
636 int count = 0;
637 UtilTransactions utilTrans(*pTab2);
638 if (utilTrans.selectCount(pNdb, 64, &count) != 0){
639 return NDBT_FAILED;
640 }
641 if (count != records){
642 ndbout << count <<" != "<<records << endl;
643 return NDBT_FAILED;
644 }
645
646 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
647 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
648 return NDBT_FAILED;
649 }
650
651 // Verify that table is not in db
652 const NdbDictionary::Table* pTab3 =
653 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
654 if (pTab3 != NULL){
655 ndbout << pTab3->getName() << " was found in DB"<< endl;
656 return NDBT_FAILED;
657 }
658
659
660 i++;
661 }
662
663 return NDBT_OK;
664 }
665
runFillTable(NDBT_Context * ctx,NDBT_Step * step)666 int runFillTable(NDBT_Context* ctx, NDBT_Step* step){
667 Ndb* pNdb = GETNDB(step);
668 HugoTransactions hugoTrans(*ctx->getTab());
669 if (hugoTrans.fillTable(pNdb) != 0){
670 return NDBT_FAILED;
671 }
672 return NDBT_OK;
673 }
674
runClearTable(NDBT_Context * ctx,NDBT_Step * step)675 int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
676 Ndb* pNdb = GETNDB(step);
677 int records = ctx->getNumRecords();
678
679 UtilTransactions utilTrans(*ctx->getTab());
680 if (utilTrans.clearTable(pNdb, records) != 0){
681 return NDBT_FAILED;
682 }
683 return NDBT_OK;
684 }
685
runCreateAndDropDuring(NDBT_Context * ctx,NDBT_Step * step)686 int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
687 int result = NDBT_OK;
688 int loops = ctx->getNumLoops();
689 int i = 0;
690
691 const NdbDictionary::Table* pTab = ctx->getTab();
692 ndbout << "|- " << pTab->getName() << endl;
693
694 while (i < loops && result == NDBT_OK){
695 ndbout << i << ": " << endl;
696 // Try to create table in db
697
698 Ndb* pNdb = GETNDB(step);
699 g_debug << "Creating table" << endl;
700
701 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
702 g_err << "createTableInDb failed" << endl;
703 result = NDBT_FAILED;
704 continue;
705 }
706
707 g_debug << "Verifying creation of table" << endl;
708
709 // Verify that table is in db
710 const NdbDictionary::Table* pTab2 =
711 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
712 if (pTab2 == NULL){
713 g_err << pTab->getName() << " was not found in DB"<< endl;
714 result = NDBT_FAILED;
715 continue;
716 }
717
718 NdbSleep_MilliSleep(3000);
719
720 g_debug << "Dropping table" << endl;
721
722 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
723 g_err << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
724 result = NDBT_FAILED;
725 continue;
726 }
727
728 g_debug << "Verifying dropping of table" << endl;
729
730 // Verify that table is not in db
731 const NdbDictionary::Table* pTab3 =
732 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
733 if (pTab3 != NULL){
734 g_err << pTab3->getName() << " was found in DB"<< endl;
735 result = NDBT_FAILED;
736 continue;
737 }
738 i++;
739 }
740 ctx->stopTest();
741
742 return result;
743 }
744
745
runUseTableUntilStopped(NDBT_Context * ctx,NDBT_Step * step)746 int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
747 int records = ctx->getNumRecords();
748
749 const NdbDictionary::Table* pTab = ctx->getTab();
750
751 while (ctx->isTestStopped() == false) {
752 // g_info << i++ << ": ";
753
754
755 // Delete and recreate Ndb object
756 // Otherwise you always get Invalid Schema Version
757 // It would be a nice feature to remove this two lines
758 //step->tearDown();
759 //step->setUp();
760
761 Ndb* pNdb = GETNDB(step);
762
763 const NdbDictionary::Table* pTab2 =
764 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
765 if (pTab2 == NULL)
766 continue;
767
768 int res;
769 HugoTransactions hugoTrans(*pTab2);
770 if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
771 NdbError err = pNdb->getNdbError(res);
772 if(err.classification == NdbError::SchemaError){
773 pNdb->getDictionary()->invalidateTable(pTab->getName());
774 }
775 continue;
776 }
777
778 if ((res = hugoTrans.clearTable(pNdb, records)) != 0){
779 NdbError err = pNdb->getNdbError(res);
780 if(err.classification == NdbError::SchemaError){
781 pNdb->getDictionary()->invalidateTable(pTab->getName());
782 }
783 continue;
784 }
785 }
786 g_info << endl;
787 return NDBT_OK;
788 }
789
runUseTableUntilStopped2(NDBT_Context * ctx,NDBT_Step * step)790 int runUseTableUntilStopped2(NDBT_Context* ctx, NDBT_Step* step){
791 int records = ctx->getNumRecords();
792
793 Ndb* pNdb = GETNDB(step);
794 const NdbDictionary::Table* pTab = ctx->getTab();
795 const NdbDictionary::Table* pTab2 =
796 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
797
798 if (pTab2 == NULL) {
799 g_err << "Table: " << pTab->getName()
800 << ", not 'discovered' on line " << __LINE__
801 << endl;
802 return NDBT_FAILED;
803 }
804 HugoTransactions hugoTrans(*pTab2);
805
806 int i = 0;
807 while (ctx->isTestStopped() == false)
808 {
809 ndbout_c("loop: %u", i++);
810
811
812 // Delete and recreate Ndb object
813 // Otherwise you always get Invalid Schema Version
814 // It would be a nice feature to remove this two lines
815 //step->tearDown();
816 //step->setUp();
817
818
819 int res;
820 if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
821 NdbError err = pNdb->getNdbError(res);
822 if(err.classification == NdbError::SchemaError){
823 pNdb->getDictionary()->invalidateTable(pTab->getName());
824 }
825 continue;
826 }
827
828 if ((res = hugoTrans.scanUpdateRecords(pNdb, records)) != 0)
829 {
830 NdbError err = pNdb->getNdbError(res);
831 if(err.classification == NdbError::SchemaError){
832 pNdb->getDictionary()->invalidateTable(pTab->getName());
833 }
834 continue;
835 }
836
837 if ((res = hugoTrans.clearTable(pNdb, records)) != 0){
838 NdbError err = pNdb->getNdbError(res);
839 if(err.classification == NdbError::SchemaError){
840 pNdb->getDictionary()->invalidateTable(pTab->getName());
841 }
842 continue;
843 }
844 }
845 g_info << endl;
846 return NDBT_OK;
847 }
848
runUseTableUntilStopped3(NDBT_Context * ctx,NDBT_Step * step)849 int runUseTableUntilStopped3(NDBT_Context* ctx, NDBT_Step* step){
850 int records = ctx->getNumRecords();
851
852 Ndb* pNdb = GETNDB(step);
853 const NdbDictionary::Table* pTab = ctx->getTab();
854 const NdbDictionary::Table* pTab2 =
855 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
856 if (pTab2 == NULL) {
857 g_err << "Table : " << pTab->getName()
858 << ", not 'discovered' on line " << __LINE__
859 << endl;
860 return NDBT_FAILED;
861 }
862 HugoTransactions hugoTrans(*pTab2);
863
864 int i = 0;
865 while (ctx->isTestStopped() == false)
866 {
867 ndbout_c("loop: %u", i++);
868
869
870 // Delete and recreate Ndb object
871 // Otherwise you always get Invalid Schema Version
872 // It would be a nice feature to remove this two lines
873 //step->tearDown();
874 //step->setUp();
875
876
877 int res;
878 if ((res = hugoTrans.scanUpdateRecords(pNdb, records)) != 0)
879 {
880 NdbError err = pNdb->getNdbError(res);
881 if(err.classification == NdbError::SchemaError){
882 pNdb->getDictionary()->invalidateTable(pTab->getName());
883 }
884 continue;
885 }
886 }
887 g_info << endl;
888 return NDBT_OK;
889 }
890
891 /**
892 * This is a regression test for bug 14190114
893 * "CLUSTER CRASH DUE TO NDBREQUIRE IN ./LOCALPROXY.HPP DBLQH (LINE: 234)".
894 * This bug occurs if there is a takeover (i.e. the master node crashes)
895 * while an LQH block is executing a DROP_TAB_REQ signal. It only affects
896 * multi-threaded ndb.
897 */
898 static int
runDropTakeoverTest(NDBT_Context * ctx,NDBT_Step * step)899 runDropTakeoverTest(NDBT_Context* ctx, NDBT_Step* step)
900 {
901 NdbRestarter restarter;
902 if (restarter.getNumDbNodes() == 1)
903 {
904 g_info << "Cannot do this test with just one datanode." << endl;
905 return NDBT_OK;
906 }
907
908 Ndb* const ndb = GETNDB(step);
909 NdbDictionary::Dictionary* const dict = ndb->getDictionary();
910
911 // First we create a table that is a copy of ctx->getTab().
912 NdbDictionary::Table copyTab(*ctx->getTab());
913 const char* copyName = "copyTab";
914
915 copyTab.setName(copyName);
916 if (dict->createTable(copyTab) != 0)
917 {
918 g_err << "Failed to create table " << copyName << endl
919 << dict->getNdbError() << endl;
920 return NDBT_FAILED;
921 }
922
923 /**
924 * Find the node id of the master node and another data node that is not
925 * the master.
926 */
927 const int masterNodeId = restarter.getMasterNodeId();
928 const int nonMasterNodeId =
929 masterNodeId == restarter.getDbNodeId(0) ?
930 restarter.getDbNodeId(1) :
931 restarter.getDbNodeId(0);
932
933 /**
934 * This error insert makes LQH resend the DROP_TAB_REQ to itself (with a
935 * long delay) rather than executing it.
936 * This makes it appear as if though the LQH block spends a long time
937 * executing the DROP_TAB_REQ signal.
938 */
939 g_info << "Insert error 5076 in node " << nonMasterNodeId << endl;
940 restarter.insertErrorInNode(nonMasterNodeId, 5076);
941 /**
942 * This error insert makes the master node crash when one of its LQH
943 * blocks tries to execute a DROP_TAB_REQ signal. This will then trigger
944 * a takeover.
945 */
946 g_info << "Insert error 5077 in node " << masterNodeId << endl;
947 restarter.insertErrorInNode(masterNodeId, 5077);
948
949 // dropTable should succeed with the new master.
950 g_info << "Trying to drop table " << copyName << endl;
951 if (dict->dropTable(copyName))
952 {
953 g_err << "Unexpectedly failed to drop table " << copyName << endl;
954 return NDBT_FAILED;
955 }
956
957 /**
958 * Check that only old master is dead. Bug 14190114 would cause other nodes
959 * to die as well.
960 */
961 const int deadNodeId = restarter.checkClusterAlive(&masterNodeId, 1);
962 if (deadNodeId != 0)
963 {
964 g_err << "NodeId " << deadNodeId << " is down." << endl;
965 return NDBT_FAILED;
966 }
967
968 // Verify that old master comes back up, and that no other node crashed.
969 g_info << "Waiting for all nodes to be up." << endl;
970 if (restarter.waitClusterStarted() != 0)
971 {
972 g_err << "One or more cluster nodes are not up." << endl;
973 return NDBT_FAILED;
974 }
975
976 /**
977 * The 'drop table' operation should have been rolled forward, since the
978 * node crash happened in the complete phase. Verify that the table is
979 * gone.
980 */
981 g_info << "Verifying that table " << copyName << " was deleted." << endl;
982 if (dict->getTable(copyName) == NULL)
983 {
984 if (dict->getNdbError().code != 723) // 723 = no such table existed.
985 {
986 g_err << "dict->getTable() for " << copyName
987 << " failed in unexpedted way:" << endl
988 << dict->getNdbError() << endl;
989 return NDBT_FAILED;
990 }
991 }
992 else
993 {
994 g_err << "Transaction dropping " << copyName << " was not rolled forward"
995 << endl;
996 return NDBT_FAILED;
997 }
998
999 /**
1000 * Do another dictionary transaction, to verify that the cluster allows that.
1001 */
1002 NdbDictionary::Table extraTab(*ctx->getTab());
1003 const char* extraName = "extraTab";
1004
1005 extraTab.setName(extraName);
1006 g_info << "Trying to create table " << extraName << endl;
1007 if (dict->createTable(extraTab) != 0)
1008 {
1009 g_err << "Failed to create table " << extraName << endl
1010 << dict->getNdbError() << endl;
1011 return NDBT_FAILED;
1012 }
1013
1014 // Clean up by dropping extraTab.
1015 g_info << "Trying to drop table " << extraName << endl;
1016 if (dict->dropTable(extraName) != 0)
1017 {
1018 g_err << "Failed to drop table " << extraName << endl
1019 << dict->getNdbError() << endl;
1020 return NDBT_FAILED;
1021 }
1022
1023 return NDBT_OK;
1024 }
1025
1026 int
runCreateMaxTables(NDBT_Context * ctx,NDBT_Step * step)1027 runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step)
1028 {
1029 char tabName[256];
1030 int numTables = ctx->getProperty("tables", 1000);
1031 Ndb* pNdb = GETNDB(step);
1032 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
1033 int i = 0;
1034 for (i = 0; i < numTables; i++) {
1035 BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
1036 if (pNdb->waitUntilReady(30) != 0) {
1037 // Db is not ready, return with failure
1038 return NDBT_FAILED;
1039 }
1040 const NdbDictionary::Table* pTab = ctx->getTab();
1041 //ndbout << "|- " << tabName << endl;
1042 // Set new name for T1
1043 NdbDictionary::Table newTab(* pTab);
1044 newTab.setName(tabName);
1045 // Drop any old (or try to)
1046 (void)pDic->dropTable(newTab.getName());
1047 // Try to create table in db
1048 if (newTab.createTableInDb(pNdb) != 0) {
1049 ndbout << tabName << " could not be created: "
1050 << pDic->getNdbError() << endl;
1051 if (pDic->getNdbError().code == 707 ||
1052 pDic->getNdbError().code == 708 ||
1053 pDic->getNdbError().code == 826 ||
1054 pDic->getNdbError().code == 827)
1055 break;
1056 return NDBT_FAILED;
1057 }
1058 // Verify that table exists in db
1059 const NdbDictionary::Table* pTab3 =
1060 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
1061 if (pTab3 == NULL){
1062 ndbout << tabName << " was not found in DB: "
1063 << pDic->getNdbError() << endl;
1064 return NDBT_FAILED;
1065 }
1066 if (! newTab.equal(*pTab3)) {
1067 ndbout << "It was not equal" << endl; abort();
1068 return NDBT_FAILED;
1069 }
1070 int records = ctx->getNumRecords();
1071 HugoTransactions hugoTrans(*pTab3);
1072 if (hugoTrans.loadTable(pNdb, records) != 0) {
1073 ndbout << "It can NOT be loaded" << endl;
1074 return NDBT_FAILED;
1075 }
1076 UtilTransactions utilTrans(*pTab3);
1077 if (utilTrans.clearTable(pNdb, records, 64) != 0) {
1078 ndbout << "It can NOT be cleared" << endl;
1079 return NDBT_FAILED;
1080 }
1081 }
1082 if (pNdb->waitUntilReady(30) != 0) {
1083 // Db is not ready, return with failure
1084 return NDBT_FAILED;
1085 }
1086 ctx->setProperty("maxtables", i);
1087 // HURRAAA!
1088 return NDBT_OK;
1089 }
1090
runDropMaxTables(NDBT_Context * ctx,NDBT_Step * step)1091 int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step)
1092 {
1093 char tabName[256];
1094 int numTables = ctx->getProperty("maxtables", (Uint32)0);
1095 Ndb* pNdb = GETNDB(step);
1096 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
1097 for (int i = 0; i < numTables; i++) {
1098 BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
1099 if (pNdb->waitUntilReady(30) != 0) {
1100 // Db is not ready, return with failure
1101 return NDBT_FAILED;
1102 }
1103 // Verify that table exists in db
1104 const NdbDictionary::Table* pTab3 =
1105 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
1106 if (pTab3 == NULL) {
1107 ndbout << tabName << " was not found in DB: "
1108 << pDic->getNdbError() << endl;
1109 return NDBT_FAILED;
1110 }
1111 // Try to drop table in db
1112 if (pDic->dropTable(pTab3->getName()) != 0) {
1113 ndbout << tabName << " could not be dropped: "
1114 << pDic->getNdbError() << endl;
1115 return NDBT_FAILED;
1116 }
1117 }
1118 return NDBT_OK;
1119 }
1120
runTestFragmentTypes(NDBT_Context * ctx,NDBT_Step * step)1121 int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
1122 int records = ctx->getNumRecords();
1123 int fragTtype = ctx->getProperty("FragmentType");
1124 Ndb* pNdb = GETNDB(step);
1125 int result = NDBT_OK;
1126 NdbRestarter restarter;
1127
1128 if (pNdb->waitUntilReady(30) != 0){
1129 // Db is not ready, return with failure
1130 return NDBT_FAILED;
1131 }
1132
1133 const NdbDictionary::Table* pTab = ctx->getTab();
1134 pNdb->getDictionary()->dropTable(pTab->getName());
1135
1136 NdbDictionary::Table newTab(* pTab);
1137 // Set fragment type for table
1138 newTab.setFragmentType((NdbDictionary::Object::FragmentType)fragTtype);
1139
1140 // Try to create table in db
1141 if (newTab.createTableInDb(pNdb) != 0){
1142 ndbout << newTab.getName() << " could not be created"
1143 << ", fragmentType = "<<fragTtype <<endl;
1144 ndbout << pNdb->getDictionary()->getNdbError() << endl;
1145 return NDBT_FAILED;
1146 }
1147
1148 // Verify that table exists in db
1149 const NdbDictionary::Table* pTab3 =
1150 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName()) ;
1151 if (pTab3 == NULL){
1152 ndbout << pTab->getName() << " was not found in DB"<< endl;
1153 return NDBT_FAILED;
1154
1155 }
1156
1157 if (pTab3->getFragmentType() != fragTtype){
1158 ndbout << pTab->getName() << " fragmentType error "<< endl;
1159 result = NDBT_FAILED;
1160 goto drop_the_tab;
1161 }
1162 /**
1163 This test does not work since fragmentation is
1164 decided by the kernel, hence the fragementation
1165 attribute on the column will differ
1166
1167 if (newTab.equal(*pTab3) == false){
1168 ndbout << "It was not equal" << endl;
1169 result = NDBT_FAILED;
1170 goto drop_the_tab;
1171 }
1172 */
1173 do {
1174
1175 HugoTransactions hugoTrans(*pTab3);
1176 UtilTransactions utilTrans(*pTab3);
1177 int count;
1178 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1179 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1180 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1181 CHECK(count == records);
1182 CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1183 CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
1184 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1185 CHECK(count == (records/2));
1186
1187 // restart all
1188 ndbout << "Restarting cluster" << endl;
1189 CHECK(restarter.restartAll() == 0);
1190 int timeout = 120;
1191 CHECK(restarter.waitClusterStarted(timeout) == 0);
1192 CHECK(pNdb->waitUntilReady(timeout) == 0);
1193
1194 // Verify content
1195 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1196 CHECK(count == (records/2));
1197
1198 CHECK(utilTrans.clearTable(pNdb, records) == 0);
1199 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1200 CHECK(utilTrans.clearTable(pNdb, records) == 0);
1201 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1202 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1203 CHECK(utilTrans.clearTable(pNdb, records, 64) == 0);
1204
1205 } while(false);
1206
1207 drop_the_tab:
1208
1209 // Try to drop table in db
1210 if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
1211 ndbout << pTab3->getName() << " could not be dropped"<< endl;
1212 result = NDBT_FAILED;
1213 }
1214
1215 return result;
1216 }
1217
1218
runTestTemporaryTables(NDBT_Context * ctx,NDBT_Step * step)1219 int runTestTemporaryTables(NDBT_Context* ctx, NDBT_Step* step){
1220 int result = NDBT_OK;
1221 int loops = ctx->getNumLoops();
1222 int records = ctx->getNumRecords();
1223 Ndb* pNdb = GETNDB(step);
1224 int i = 0;
1225 NdbRestarter restarter;
1226
1227 const NdbDictionary::Table* pTab = ctx->getTab();
1228 ndbout << "|- " << pTab->getName() << endl;
1229
1230 NdbDictionary::Table newTab(* pTab);
1231 // Set table as temporary
1232 newTab.setStoredTable(false);
1233
1234 // Try to create table in db
1235 if (newTab.createTableInDb(pNdb) != 0){
1236 return NDBT_FAILED;
1237 }
1238
1239 // Verify that table is in db
1240 const NdbDictionary::Table* pTab2 =
1241 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1242 if (pTab2 == NULL){
1243 ndbout << pTab->getName() << " was not found in DB"<< endl;
1244 return NDBT_FAILED;
1245 }
1246
1247 if (pTab2->getStoredTable() != false){
1248 ndbout << pTab->getName() << " was not temporary in DB"<< endl;
1249 result = NDBT_FAILED;
1250 goto drop_the_tab;
1251 }
1252
1253
1254 while (i < loops && result == NDBT_OK){
1255 ndbout << i << ": ";
1256
1257 HugoTransactions hugoTrans(*pTab2);
1258 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1259
1260 int count = 0;
1261 UtilTransactions utilTrans(*pTab2);
1262 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1263 CHECK(count == records);
1264
1265 // restart all
1266 ndbout << "Restarting cluster" << endl;
1267 CHECK(restarter.restartAll() == 0);
1268 int timeout = 120;
1269 CHECK(restarter.waitClusterStarted(timeout) == 0);
1270 CHECK(pNdb->waitUntilReady(timeout) == 0);
1271
1272 ndbout << "Verifying records..." << endl;
1273 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1274 CHECK(count == 0);
1275
1276 i++;
1277 }
1278
1279 drop_the_tab:
1280
1281
1282 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1283 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
1284 result = NDBT_FAILED;
1285 }
1286
1287 // Verify that table is not in db
1288 const NdbDictionary::Table* pTab3 =
1289 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1290 if (pTab3 != NULL){
1291 ndbout << pTab3->getName() << " was found in DB"<< endl;
1292 result = NDBT_FAILED;
1293 }
1294
1295 return result;
1296 }
1297
runPkSizes(NDBT_Context * ctx,NDBT_Step * step)1298 int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){
1299 int result = NDBT_OK;
1300 char tabName[256];
1301 int minPkSize = 1;
1302 ndbout << "minPkSize=" <<minPkSize<<endl;
1303 int maxPkSize = MAX_KEY_SIZE_IN_WORDS * 4;
1304 ndbout << "maxPkSize=" <<maxPkSize<<endl;
1305 Ndb* pNdb = GETNDB(step);
1306 int numRecords = ctx->getNumRecords();
1307
1308 for (int i = minPkSize; i < maxPkSize; i++){
1309 BaseString::snprintf(tabName, 256, "TPK_%d", i);
1310
1311 int records = numRecords;
1312 int max = ~0;
1313 // Limit num records for small PKs
1314 if (i == 1)
1315 max = 99;
1316 if (i == 2)
1317 max = 999;
1318 if (i == 3)
1319 max = 9999;
1320 if (records > max)
1321 records = max;
1322 ndbout << "records =" << records << endl;
1323
1324 if (pNdb->waitUntilReady(30) != 0){
1325 // Db is not ready, return with failure
1326 return NDBT_FAILED;
1327 }
1328
1329 ndbout << "|- " << tabName << endl;
1330
1331 if (NDBT_Tables::createTable(pNdb, tabName) != 0){
1332 ndbout << tabName << " could not be created"<< endl;
1333 return NDBT_FAILED;
1334 }
1335
1336 // Verify that table exists in db
1337 const NdbDictionary::Table* pTab3 =
1338 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
1339 if (pTab3 == NULL){
1340 g_err << tabName << " was not found in DB"<< endl;
1341 return NDBT_FAILED;
1342 }
1343
1344 // ndbout << *pTab3 << endl;
1345
1346 if (pTab3->equal(*NDBT_Tables::getTable(tabName)) == false){
1347 g_err << "It was not equal" << endl;
1348 return NDBT_FAILED;
1349 }
1350
1351 do {
1352 // Do it all
1353 HugoTransactions hugoTrans(*pTab3);
1354 UtilTransactions utilTrans(*pTab3);
1355 int count;
1356 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1357 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1358 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1359 CHECK(count == records);
1360 CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1361 CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
1362 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1363 CHECK(count == (records/2));
1364 CHECK(utilTrans.clearTable(pNdb, records) == 0);
1365
1366 #if 0
1367 // Fill table
1368 CHECK(hugoTrans.fillTable(pNdb) == 0);
1369 CHECK(utilTrans.clearTable2(pNdb, records) == 0);
1370 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1371 CHECK(count == 0);
1372 #endif
1373 } while(false);
1374
1375 // Drop table
1376 if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
1377 ndbout << "Failed to drop "<<pTab3->getName()<<" in db" << endl;
1378 return NDBT_FAILED;
1379 }
1380 }
1381 return result;
1382 }
1383
runStoreFrm(NDBT_Context * ctx,NDBT_Step * step)1384 int runStoreFrm(NDBT_Context* ctx, NDBT_Step* step){
1385 Ndb* pNdb = GETNDB(step);
1386 const NdbDictionary::Table* pTab = ctx->getTab();
1387 int result = NDBT_OK;
1388 int loops = ctx->getNumLoops();
1389
1390 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1391
1392 Uint32 dataLen = (Uint32)myRandom48(MAX_FRM_DATA_SIZE);
1393 // size_t dataLen = 10;
1394 unsigned char data[MAX_FRM_DATA_SIZE];
1395
1396 char start = l + 248;
1397 for(Uint32 i = 0; i < dataLen; i++){
1398 data[i] = start;
1399 start++;
1400 }
1401 #if 0
1402 ndbout << "dataLen="<<dataLen<<endl;
1403 for (Uint32 i = 0; i < dataLen; i++){
1404 unsigned char c = data[i];
1405 ndbout << hex << c << ", ";
1406 }
1407 ndbout << endl;
1408 #endif
1409
1410 NdbDictionary::Table newTab(* pTab);
1411 void* pData = &data;
1412 newTab.setFrm(pData, dataLen);
1413
1414 // Try to create table in db
1415 if (newTab.createTableInDb(pNdb) != 0){
1416 result = NDBT_FAILED;
1417 continue;
1418 }
1419
1420 // Verify that table is in db
1421 const NdbDictionary::Table* pTab2 =
1422 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1423 if (pTab2 == NULL){
1424 g_err << pTab->getName() << " was not found in DB"<< endl;
1425 result = NDBT_FAILED;
1426 continue;
1427 }
1428
1429 const void* pData2 = pTab2->getFrmData();
1430 Uint32 resultLen = pTab2->getFrmLength();
1431 if (dataLen != resultLen){
1432 g_err << "Length of data failure" << endl
1433 << " expected = " << dataLen << endl
1434 << " got = " << resultLen << endl;
1435 result = NDBT_FAILED;
1436 }
1437
1438 // Verfiy the frm data
1439 if (memcmp(pData, pData2, resultLen) != 0){
1440 g_err << "Wrong data received" << endl;
1441 for (size_t i = 0; i < dataLen; i++){
1442 unsigned char c = ((unsigned char*)pData2)[i];
1443 g_err << hex << c << ", ";
1444 }
1445 g_err << endl;
1446 result = NDBT_FAILED;
1447 }
1448
1449 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1450 g_err << "It can NOT be dropped" << endl;
1451 result = NDBT_FAILED;
1452 }
1453 }
1454
1455 return result;
1456 }
1457
runStoreFrmError(NDBT_Context * ctx,NDBT_Step * step)1458 int runStoreFrmError(NDBT_Context* ctx, NDBT_Step* step){
1459 Ndb* pNdb = GETNDB(step);
1460 const NdbDictionary::Table* pTab = ctx->getTab();
1461 int result = NDBT_OK;
1462 int loops = ctx->getNumLoops();
1463
1464 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1465
1466 const Uint32 dataLen = MAX_FRM_DATA_SIZE + 10;
1467 unsigned char data[dataLen];
1468
1469 char start = l + 248;
1470 for(Uint32 i = 0; i < dataLen; i++){
1471 data[i] = start;
1472 start++;
1473 }
1474 #if 0
1475 ndbout << "dataLen="<<dataLen<<endl;
1476 for (Uint32 i = 0; i < dataLen; i++){
1477 unsigned char c = data[i];
1478 ndbout << hex << c << ", ";
1479 }
1480 ndbout << endl;
1481 #endif
1482
1483 NdbDictionary::Table newTab(* pTab);
1484
1485 void* pData = &data;
1486 newTab.setFrm(pData, dataLen);
1487
1488 // Try to create table in db
1489 if (newTab.createTableInDb(pNdb) == 0){
1490 result = NDBT_FAILED;
1491 continue;
1492 }
1493
1494 const NdbDictionary::Table* pTab2 =
1495 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1496 if (pTab2 != NULL){
1497 g_err << pTab->getName() << " was found in DB"<< endl;
1498 result = NDBT_FAILED;
1499 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1500 g_err << "It can NOT be dropped" << endl;
1501 result = NDBT_FAILED;
1502 }
1503
1504 continue;
1505 }
1506
1507 }
1508
1509 return result;
1510 }
1511
verifyTablesAreEqual(const NdbDictionary::Table * pTab,const NdbDictionary::Table * pTab2)1512 int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary::Table* pTab2){
1513 // Verify that getPrimaryKey only returned true for primary keys
1514 for (int i = 0; i < pTab2->getNoOfColumns(); i++){
1515 const NdbDictionary::Column* col = pTab->getColumn(i);
1516 const NdbDictionary::Column* col2 = pTab2->getColumn(i);
1517 if (col->getPrimaryKey() != col2->getPrimaryKey()){
1518 g_err << "col->getPrimaryKey() != col2->getPrimaryKey()" << endl;
1519 return NDBT_FAILED;
1520 }
1521 }
1522
1523 if (!pTab->equal(*pTab2)){
1524 g_err << "equal failed" << endl;
1525 g_info << *(NDBT_Table*)pTab; // gcc-4.1.2
1526 g_info << *(NDBT_Table*)pTab2;
1527 return NDBT_FAILED;
1528 }
1529 return NDBT_OK;
1530 }
1531
runGetPrimaryKey(NDBT_Context * ctx,NDBT_Step * step)1532 int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
1533 Ndb* pNdb = GETNDB(step);
1534 const NdbDictionary::Table* pTab = ctx->getTab();
1535 ndbout << "|- " << pTab->getName() << endl;
1536 g_info << *(NDBT_Table*)pTab;
1537 // Try to create table in db
1538 if (pTab->createTableInDb(pNdb) != 0){
1539 return NDBT_FAILED;
1540 }
1541
1542 const NdbDictionary::Table* pTab2 =
1543 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1544 if (pTab2 == NULL){
1545 ndbout << pTab->getName() << " was not found in DB"<< endl;
1546 return NDBT_FAILED;
1547 }
1548
1549 int result = NDBT_OK;
1550 if (verifyTablesAreEqual(pTab, pTab2) != NDBT_OK)
1551 result = NDBT_FAILED;
1552
1553
1554 #if 0
1555 // Create an index on the table and see what
1556 // the function returns now
1557 char name[200];
1558 sprintf(name, "%s_X007", pTab->getName());
1559 NDBT_Index* pInd = new NDBT_Index(name);
1560 pInd->setTable(pTab->getName());
1561 pInd->setType(NdbDictionary::Index::UniqueHashIndex);
1562 // pInd->setLogging(false);
1563 for (int i = 0; i < 2; i++){
1564 const NDBT_Attribute* pAttr = pTab->getAttribute(i);
1565 pInd->addAttribute(*pAttr);
1566 }
1567 g_info << "Create index:" << endl << *pInd;
1568 if (pInd->createIndexInDb(pNdb, false) != 0){
1569 result = NDBT_FAILED;
1570 }
1571 delete pInd;
1572
1573 const NdbDictionary::Table* pTab3 =
1574 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1575 if (pTab3 == NULL){
1576 ndbout << pTab->getName() << " was not found in DB"<< endl;
1577 return NDBT_FAILED;
1578 }
1579
1580 if (verifyTablesAreEqual(pTab, pTab3) != NDBT_OK)
1581 result = NDBT_FAILED;
1582 if (verifyTablesAreEqual(pTab2, pTab3) != NDBT_OK)
1583 result = NDBT_FAILED;
1584 #endif
1585
1586 #if 0
1587 if (pTab2->getDictionary()->dropTable(pNdb) != 0){
1588 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
1589 return NDBT_FAILED;
1590 }
1591
1592 // Verify that table is not in db
1593 const NdbDictionary::Table* pTab4 =
1594 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1595 if (pTab4 != NULL){
1596 ndbout << pTab4->getName() << " was found in DB"<< endl;
1597 return NDBT_FAILED;
1598 }
1599 #endif
1600
1601 return result;
1602 }
1603
1604 #define APIERROR(error) \
1605 { g_err << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
1606 << error.code << ", msg: " << error.message << "." << endl; \
1607 }
1608
1609 int
runCreateAutoincrementTable(NDBT_Context * ctx,NDBT_Step * step)1610 runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){
1611
1612 Uint32 startvalues[5] = {256-2, 0, 256*256-2, ~Uint32(0), 256*256*256-2};
1613
1614 int ret = NDBT_OK;
1615
1616 for (int jj = 0; jj < 5 && ret == NDBT_OK; jj++) {
1617 char tabname[] = "AUTOINCTAB";
1618 Uint32 startvalue = startvalues[jj];
1619
1620 NdbDictionary::Table myTable;
1621 NdbDictionary::Column myColumn;
1622
1623 Ndb* myNdb = GETNDB(step);
1624 NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
1625
1626
1627 if (myDict->getTable(tabname) != NULL) {
1628 g_err << "NDB already has example table: " << tabname << endl;
1629 APIERROR(myNdb->getNdbError());
1630 return NDBT_FAILED;
1631 }
1632
1633 myTable.setName(tabname);
1634
1635 myColumn.setName("ATTR1");
1636 myColumn.setType(NdbDictionary::Column::Unsigned);
1637 myColumn.setLength(1);
1638 myColumn.setPrimaryKey(true);
1639 myColumn.setNullable(false);
1640 myColumn.setAutoIncrement(true);
1641 if (startvalue != ~Uint32(0)) // check that default value starts with 1
1642 myColumn.setAutoIncrementInitialValue(startvalue);
1643 myTable.addColumn(myColumn);
1644
1645 if (myDict->createTable(myTable) == -1) {
1646 g_err << "Failed to create table " << tabname << endl;
1647 APIERROR(myNdb->getNdbError());
1648 return NDBT_FAILED;
1649 }
1650
1651
1652 if (startvalue == ~Uint32(0)) // check that default value starts with 1
1653 startvalue = 1;
1654
1655 for (int i = 0; i < 16; i++) {
1656
1657 Uint64 value;
1658 if (myNdb->getAutoIncrementValue(tabname, value, 1) == -1) {
1659 g_err << "getAutoIncrementValue failed on " << tabname << endl;
1660 APIERROR(myNdb->getNdbError());
1661 return NDBT_FAILED;
1662 }
1663 else if (value != (startvalue+i)) {
1664 g_err << "value = " << value << " expected " << startvalue+i << endl;;
1665 APIERROR(myNdb->getNdbError());
1666 // ret = NDBT_FAILED;
1667 // break;
1668 }
1669 }
1670
1671 if (myDict->dropTable(tabname) == -1) {
1672 g_err << "Failed to drop table " << tabname << endl;
1673 APIERROR(myNdb->getNdbError());
1674 ret = NDBT_FAILED;
1675 }
1676 }
1677
1678 return ret;
1679 }
1680
1681 int
runTableRename(NDBT_Context * ctx,NDBT_Step * step)1682 runTableRename(NDBT_Context* ctx, NDBT_Step* step){
1683
1684 int result = NDBT_OK;
1685
1686 Ndb* pNdb = GETNDB(step);
1687 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1688 int records = ctx->getNumRecords();
1689 const int loops = ctx->getNumLoops();
1690
1691 ndbout << "|- " << ctx->getTab()->getName() << endl;
1692
1693 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1694 const NdbDictionary::Table* pTab = ctx->getTab();
1695
1696 // Try to create table in db
1697 if (pTab->createTableInDb(pNdb) != 0){
1698 return NDBT_FAILED;
1699 }
1700
1701 // Verify that table is in db
1702 const NdbDictionary::Table* pTab2 =
1703 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1704 if (pTab2 == NULL){
1705 ndbout << pTab->getName() << " was not found in DB"<< endl;
1706 return NDBT_FAILED;
1707 }
1708 ctx->setTab(pTab2);
1709
1710 // Load table
1711 HugoTransactions hugoTrans(*ctx->getTab());
1712 if (hugoTrans.loadTable(pNdb, records) != 0){
1713 return NDBT_FAILED;
1714 }
1715
1716 // Rename table
1717 BaseString pTabName(pTab->getName());
1718 BaseString pTabNewName(pTabName);
1719 pTabNewName.append("xx");
1720
1721 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
1722 if (oldTable) {
1723 NdbDictionary::Table newTable = *oldTable;
1724 newTable.setName(pTabNewName.c_str());
1725 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1726 "TableRename failed");
1727 }
1728 else {
1729 result = NDBT_FAILED;
1730 }
1731
1732 // Verify table contents
1733 NdbDictionary::Table pNewTab(pTabNewName.c_str());
1734
1735 UtilTransactions utilTrans(pNewTab);
1736 if (utilTrans.clearTable(pNdb, records) != 0){
1737 continue;
1738 }
1739
1740 // Drop table
1741 dict->dropTable(pNewTab.getName());
1742 }
1743 end:
1744
1745 return result;
1746 }
1747
1748 int
runTableRenameSR(NDBT_Context * ctx,NDBT_Step * step)1749 runTableRenameSR(NDBT_Context* ctx, NDBT_Step* step){
1750 NdbRestarter restarter;
1751 if(restarter.getNumDbNodes() < 2)
1752 return NDBT_OK;
1753
1754 int result = NDBT_OK;
1755
1756 Ndb* pNdb = GETNDB(step);
1757 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1758 int records = ctx->getNumRecords();
1759 const int loops = ctx->getNumLoops();
1760
1761 ndbout << "|- " << ctx->getTab()->getName() << endl;
1762
1763 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1764 // Rename table
1765 const NdbDictionary::Table* pTab = ctx->getTab();
1766
1767 // Try to create table in db
1768 if (pTab->createTableInDb(pNdb) != 0){
1769 return NDBT_FAILED;
1770 }
1771
1772 // Verify that table is in db
1773 const NdbDictionary::Table* pTab2 =
1774 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1775 if (pTab2 == NULL){
1776 ndbout << pTab->getName() << " was not found in DB"<< endl;
1777 return NDBT_FAILED;
1778 }
1779 ctx->setTab(pTab2);
1780
1781 // Load table
1782 HugoTransactions hugoTrans(*ctx->getTab());
1783 if (hugoTrans.loadTable(pNdb, records) != 0){
1784 return NDBT_FAILED;
1785 }
1786
1787 BaseString pTabName(pTab->getName());
1788 BaseString pTabNewName(pTabName);
1789 pTabNewName.append("xx");
1790
1791 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
1792 if (oldTable) {
1793 NdbDictionary::Table newTable = *oldTable;
1794 newTable.setName(pTabNewName.c_str());
1795 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1796 "TableRename failed");
1797 }
1798 else {
1799 result = NDBT_FAILED;
1800 }
1801
1802 // Restart cluster
1803
1804 /**
1805 * Need to run LCP at high rate otherwise
1806 * packed replicas become "to many"
1807 */
1808 int val = DumpStateOrd::DihMinTimeBetweenLCP;
1809 if(restarter.dumpStateAllNodes(&val, 1) != 0){
1810 do { CHECK(0); } while(0);
1811 g_err << "Failed to set LCP to min value" << endl;
1812 return NDBT_FAILED;
1813 }
1814
1815 CHECK2(restarter.restartAll() == 0,
1816 "failed to set restartOneDbNode");
1817
1818 CHECK2(restarter.waitClusterStarted() == 0,
1819 "waitClusterStarted failed");
1820
1821 // Verify table contents
1822 NdbDictionary::Table pNewTab(pTabNewName.c_str());
1823
1824 UtilTransactions utilTrans(pNewTab);
1825 if (utilTrans.clearTable(pNdb, records) != 0){
1826 continue;
1827 }
1828
1829 // Drop table
1830 dict->dropTable(pTabNewName.c_str());
1831 }
1832 end:
1833 return result;
1834 }
1835
1836 /*
1837 Run online alter table add attributes.
1838 */
1839 int
runTableAddAttrs(NDBT_Context * ctx,NDBT_Step * step)1840 runTableAddAttrs(NDBT_Context* ctx, NDBT_Step* step){
1841
1842 int result = NDBT_OK;
1843
1844 Ndb* pNdb = GETNDB(step);
1845 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1846 int records = ctx->getNumRecords();
1847 const int loops = ctx->getNumLoops();
1848
1849 ndbout << "|- " << ctx->getTab()->getName() << endl;
1850
1851 NdbDictionary::Table myTab= *(ctx->getTab());
1852
1853 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1854 // Try to create table in db
1855
1856 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
1857 return NDBT_FAILED;
1858 }
1859
1860 // Verify that table is in db
1861 const NdbDictionary::Table* pTab2 =
1862 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
1863 if (pTab2 == NULL){
1864 ndbout << myTab.getName() << " was not found in DB"<< endl;
1865 return NDBT_FAILED;
1866 }
1867 ctx->setTab(pTab2);
1868
1869 /*
1870 Check that table already has a varpart, otherwise add attr is
1871 not possible.
1872 */
1873 if (pTab2->getForceVarPart() == false)
1874 {
1875 const NdbDictionary::Column *col;
1876 for (Uint32 i= 0; (col= pTab2->getColumn(i)) != 0; i++)
1877 {
1878 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
1879 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
1880 break;
1881 }
1882 if (col == 0)
1883 {
1884 /* Alter table add attribute not applicable, just mark success. */
1885 dict->dropTable(pTab2->getName());
1886 break;
1887 }
1888 }
1889
1890 // Load table
1891 HugoTransactions beforeTrans(*ctx->getTab());
1892 if (beforeTrans.loadTable(pNdb, records) != 0){
1893 return NDBT_FAILED;
1894 }
1895
1896 // Add attributes to table.
1897 BaseString pTabName(pTab2->getName());
1898
1899 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
1900 if (oldTable) {
1901 NdbDictionary::Table newTable= *oldTable;
1902
1903 NDBT_Attribute newcol1("NEWKOL1", NdbDictionary::Column::Unsigned, 1,
1904 false, true, 0,
1905 NdbDictionary::Column::StorageTypeMemory, true);
1906 newTable.addColumn(newcol1);
1907 NDBT_Attribute newcol2("NEWKOL2", NdbDictionary::Column::Char, 14,
1908 false, true, 0,
1909 NdbDictionary::Column::StorageTypeMemory, true);
1910 newTable.addColumn(newcol2);
1911 NDBT_Attribute newcol3("NEWKOL3", NdbDictionary::Column::Bit, 20,
1912 false, true, 0,
1913 NdbDictionary::Column::StorageTypeMemory, true);
1914 newTable.addColumn(newcol3);
1915 NDBT_Attribute newcol4("NEWKOL4", NdbDictionary::Column::Varbinary, 42,
1916 false, true, 0,
1917 NdbDictionary::Column::StorageTypeMemory, true);
1918 newTable.addColumn(newcol4);
1919
1920 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1921 "TableAddAttrs failed");
1922 /* Need to purge old version and reload new version after alter table. */
1923 dict->invalidateTable(pTabName.c_str());
1924 }
1925 else {
1926 result = NDBT_FAILED;
1927 }
1928
1929 {
1930 const NdbDictionary::Table* pTab = dict->getTable(pTabName.c_str());
1931 CHECK2(pTab != NULL, "Table not found");
1932 HugoTransactions afterTrans(*pTab);
1933
1934 ndbout << "delete...";
1935 if (afterTrans.clearTable(pNdb) != 0)
1936 {
1937 return NDBT_FAILED;
1938 }
1939 ndbout << endl;
1940
1941 ndbout << "insert...";
1942 if (afterTrans.loadTable(pNdb, records) != 0){
1943 return NDBT_FAILED;
1944 }
1945 ndbout << endl;
1946
1947 ndbout << "update...";
1948 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
1949 {
1950 return NDBT_FAILED;
1951 }
1952 ndbout << endl;
1953
1954 ndbout << "delete...";
1955 if (afterTrans.clearTable(pNdb) != 0)
1956 {
1957 return NDBT_FAILED;
1958 }
1959 ndbout << endl;
1960 }
1961
1962 // Drop table.
1963 dict->dropTable(pTabName.c_str());
1964 }
1965 end:
1966
1967 return result;
1968 }
1969
1970 /*
1971 Run online alter table add attributes while running simultaneous
1972 transactions on it in separate thread.
1973 */
1974 int
runTableAddAttrsDuring(NDBT_Context * ctx,NDBT_Step * step)1975 runTableAddAttrsDuring(NDBT_Context* ctx, NDBT_Step* step){
1976
1977 int result = NDBT_OK;
1978 int abortAlter = ctx->getProperty("AbortAlter", Uint32(0));
1979
1980 int records = ctx->getNumRecords();
1981 const int loops = ctx->getNumLoops();
1982 NdbRestarter res;
1983
1984 ndbout << "|- " << ctx->getTab()->getName() << endl;
1985
1986 NdbDictionary::Table myTab= *(ctx->getTab());
1987
1988 if (myTab.getForceVarPart() == false)
1989 {
1990 const NdbDictionary::Column *col;
1991 for (Uint32 i= 0; (col= myTab.getColumn(i)) != 0; i++)
1992 {
1993 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
1994 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
1995 break;
1996 }
1997 if (col == 0)
1998 {
1999 ctx->stopTest();
2000 return NDBT_OK;
2001 }
2002 }
2003
2004 //if
2005
2006 for (int l = 0; l < loops && result == NDBT_OK ; l++){
2007 ndbout << l << ": " << endl;
2008
2009 Ndb* pNdb = GETNDB(step);
2010 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
2011
2012 /*
2013 Check that table already has a varpart, otherwise add attr is
2014 not possible.
2015 */
2016
2017 // Add attributes to table.
2018 ndbout << "Altering table" << endl;
2019
2020 const NdbDictionary::Table * oldTable = dict->getTable(myTab.getName());
2021 if (oldTable) {
2022 NdbDictionary::Table newTable= *oldTable;
2023
2024 char name[256];
2025 BaseString::snprintf(name, sizeof(name), "NEWCOL%d", l);
2026 NDBT_Attribute newcol1(name, NdbDictionary::Column::Unsigned, 1,
2027 false, true, 0,
2028 NdbDictionary::Column::StorageTypeMemory, true);
2029 newTable.addColumn(newcol1);
2030 //ToDo: check #loops, how many columns l
2031
2032 if (abortAlter == 0)
2033 {
2034 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2035 "TableAddAttrsDuring failed");
2036 }
2037 else
2038 {
2039 int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
2040 res.insertErrorInNode(nodeId, 4029);
2041 CHECK2(dict->alterTable(*oldTable, newTable) != 0,
2042 "TableAddAttrsDuring failed");
2043 }
2044
2045 dict->invalidateTable(myTab.getName());
2046 const NdbDictionary::Table * newTab = dict->getTable(myTab.getName());
2047 CHECK2(newTab != NULL, "'newTab' not found");
2048 HugoTransactions hugoTrans(* newTab);
2049 hugoTrans.scanUpdateRecords(pNdb, records);
2050 }
2051 else {
2052 result= NDBT_FAILED;
2053 break;
2054 }
2055 }
2056 end:
2057
2058 ctx->stopTest();
2059
2060 return result;
2061 }
2062
2063 static void
f(const NdbDictionary::Column * col)2064 f(const NdbDictionary::Column * col){
2065 if(col == 0){
2066 abort();
2067 }
2068 }
2069
2070 int
runTestDictionaryPerf(NDBT_Context * ctx,NDBT_Step * step)2071 runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
2072 Vector<char*> cols;
2073 Vector<const NdbDictionary::Table*> tabs;
2074 int i;
2075
2076 Ndb* pNdb = GETNDB(step);
2077
2078 const Uint32 count = NDBT_Tables::getNumTables();
2079 for (i=0; i < (int)count; i++){
2080 const NdbDictionary::Table * tab = NDBT_Tables::getTable(i);
2081 pNdb->getDictionary()->createTable(* tab);
2082
2083 const NdbDictionary::Table * tab2 = pNdb->getDictionary()->getTable(tab->getName());
2084
2085 for(int j = 0; j<tab->getNoOfColumns(); j++){
2086 cols.push_back((char*)tab2);
2087 cols.push_back(strdup(tab->getColumn(j)->getName()));
2088 }
2089 }
2090
2091 const Uint32 times = 10000000;
2092
2093 ndbout_c("%d tables and %d columns",
2094 NDBT_Tables::getNumTables(), cols.size()/2);
2095
2096 char ** tcols = cols.getBase();
2097
2098 srand((unsigned int)time(0));
2099 Uint32 size = cols.size() / 2;
2100 //char ** columns = &cols[0];
2101 Uint64 start = NdbTick_CurrentMillisecond();
2102 for(i = 0; i<(int)times; i++){
2103 int j = 2 * (rand() % size);
2104 const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j];
2105 const char * col = tcols[j+1];
2106 const NdbDictionary::Column* column = tab->getColumn(col);
2107 f(column);
2108 }
2109 Uint64 stop = NdbTick_CurrentMillisecond();
2110 stop -= start;
2111
2112 Uint64 per = stop;
2113 per *= 1000;
2114 per /= times;
2115
2116 ndbout_c("%d random getColumn(name) in %lld ms -> %u us/get",
2117 times, stop, Uint32(per));
2118
2119 return NDBT_OK;
2120 }
2121
2122 int
runCreateLogfileGroup(NDBT_Context * ctx,NDBT_Step * step)2123 runCreateLogfileGroup(NDBT_Context* ctx, NDBT_Step* step){
2124 Ndb* pNdb = GETNDB(step);
2125 NdbDictionary::LogfileGroup lg;
2126 lg.setName("DEFAULT-LG");
2127 lg.setUndoBufferSize(8*1024*1024);
2128
2129 int res;
2130 res = pNdb->getDictionary()->createLogfileGroup(lg);
2131 if(res != 0){
2132 g_err << "Failed to create logfilegroup:"
2133 << endl << pNdb->getDictionary()->getNdbError() << endl;
2134 return NDBT_FAILED;
2135 }
2136
2137 NdbDictionary::Undofile uf;
2138 uf.setPath("undofile01.dat");
2139 uf.setSize(5*1024*1024);
2140 uf.setLogfileGroup("DEFAULT-LG");
2141
2142 res = pNdb->getDictionary()->createUndofile(uf);
2143 if(res != 0){
2144 g_err << "Failed to create undofile:"
2145 << endl << pNdb->getDictionary()->getNdbError() << endl;
2146 return NDBT_FAILED;
2147 }
2148
2149 uf.setPath("undofile02.dat");
2150 uf.setSize(5*1024*1024);
2151 uf.setLogfileGroup("DEFAULT-LG");
2152
2153 res = pNdb->getDictionary()->createUndofile(uf);
2154 if(res != 0){
2155 g_err << "Failed to create undofile:"
2156 << endl << pNdb->getDictionary()->getNdbError() << endl;
2157 return NDBT_FAILED;
2158 }
2159
2160 return NDBT_OK;
2161 }
2162
2163 int
runCreateTablespace(NDBT_Context * ctx,NDBT_Step * step)2164 runCreateTablespace(NDBT_Context* ctx, NDBT_Step* step){
2165 Ndb* pNdb = GETNDB(step);
2166 NdbDictionary::Tablespace lg;
2167 lg.setName("DEFAULT-TS");
2168 lg.setExtentSize(1024*1024);
2169 lg.setDefaultLogfileGroup("DEFAULT-LG");
2170
2171 int res;
2172 res = pNdb->getDictionary()->createTablespace(lg);
2173 if(res != 0){
2174 g_err << "Failed to create tablespace:"
2175 << endl << pNdb->getDictionary()->getNdbError() << endl;
2176 return NDBT_FAILED;
2177 }
2178
2179 NdbDictionary::Datafile uf;
2180 uf.setPath("datafile01.dat");
2181 uf.setSize(10*1024*1024);
2182 uf.setTablespace("DEFAULT-TS");
2183
2184 res = pNdb->getDictionary()->createDatafile(uf);
2185 if(res != 0){
2186 g_err << "Failed to create datafile:"
2187 << endl << pNdb->getDictionary()->getNdbError() << endl;
2188 return NDBT_FAILED;
2189 }
2190
2191 return NDBT_OK;
2192 }
2193 int
runCreateDiskTable(NDBT_Context * ctx,NDBT_Step * step)2194 runCreateDiskTable(NDBT_Context* ctx, NDBT_Step* step){
2195 Ndb* pNdb = GETNDB(step);
2196
2197 NdbDictionary::Table tab = *ctx->getTab();
2198 tab.setTablespaceName("DEFAULT-TS");
2199
2200 for(Uint32 i = 0; i<(Uint32)tab.getNoOfColumns(); i++)
2201 if(!tab.getColumn(i)->getPrimaryKey())
2202 tab.getColumn(i)->setStorageType(NdbDictionary::Column::StorageTypeDisk);
2203
2204 int res;
2205 res = pNdb->getDictionary()->createTable(tab);
2206 if(res != 0){
2207 g_err << "Failed to create table:"
2208 << endl << pNdb->getDictionary()->getNdbError() << endl;
2209 return NDBT_FAILED;
2210 }
2211
2212 return NDBT_OK;
2213 }
2214
getColumnMaxLength(const NdbDictionary::Column * c)2215 int getColumnMaxLength(const NdbDictionary::Column* c)
2216 {
2217 int length= c->getLength();
2218 if (c->getArrayType() == NDB_ARRAYTYPE_FIXED)
2219 {
2220 /* Not yet set - need to calculate from type etc. */
2221 DictTabInfo::Attribute attrDesc;
2222
2223 attrDesc.init();
2224 attrDesc.AttributeExtType= c->getType();
2225 attrDesc.AttributeExtLength= c->getLength();
2226 attrDesc.AttributeExtPrecision= c->getPrecision();
2227 attrDesc.AttributeExtScale= c->getScale();
2228
2229 if (!attrDesc.translateExtType())
2230 {
2231 return 0;
2232 }
2233
2234 if (attrDesc.AttributeSize == 0)
2235 {
2236 // bits...
2237 length = 4 * ((c->getLength() + 31) / 32);
2238 }
2239 else
2240 {
2241 length = ((1 << attrDesc.AttributeSize) * c->getLength()) >> 3;
2242 }
2243 }
2244
2245 return length;
2246 }
2247
2248 #include <NDBT_Tables.hpp>
2249
2250 #define SAFTY 300
2251
runFailAddFragment(NDBT_Context * ctx,NDBT_Step * step)2252 int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
2253 static int acclst[] = { 3001, 6200, 6202 };
2254 static int tuplst[] = { 4007, 4008, 4009, 4010, 4032, 4033, 4034 };
2255 static int tuxlst[] = { 12001, 12002, 12003, 12004,
2256 6201, 6203 };
2257 static unsigned acccnt = sizeof(acclst)/sizeof(acclst[0]);
2258 static unsigned tupcnt = sizeof(tuplst)/sizeof(tuplst[0]);
2259 static unsigned tuxcnt = sizeof(tuxlst)/sizeof(tuxlst[0]);
2260
2261 NdbRestarter restarter;
2262 int nodeId = restarter.getMasterNodeId();
2263 Ndb* pNdb = GETNDB(step);
2264 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2265 NdbDictionary::Table tab(*ctx->getTab());
2266 tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
2267
2268 int errNo = 0;
2269 #ifdef NDB_USE_GET_ENV
2270 char buf[100];
2271 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
2272 {
2273 errNo = atoi(buf);
2274 ndbout_c("Using errno: %u", errNo);
2275 }
2276 #endif
2277 const NdbDictionary::Table* origTab= ctx->getTab();
2278 HugoCalculator calc(*origTab);
2279
2280 // Add defaults to some columns
2281 for (int colNum= 0; colNum < tab.getNoOfColumns(); colNum++)
2282 {
2283 const NdbDictionary::Column* origCol= origTab->getColumn(colNum);
2284 NdbDictionary::Column* col= tab.getColumn(colNum);
2285 if (!origCol->getPrimaryKey())
2286 {
2287 if (myRandom48(2) == 0)
2288 {
2289 char defaultBuf[ NDB_MAX_TUPLE_SIZE ];
2290 Uint32 real_len;
2291 Uint32 updatesVal = myRandom48(1 << 16);
2292 const char* def= calc.calcValue(0, colNum, updatesVal,
2293 defaultBuf,
2294 getColumnMaxLength(origCol),
2295 &real_len);
2296 if (col->setDefaultValue(def, real_len) != 0)
2297 {
2298 ndbout_c("Error setting default value\n");
2299 return NDBT_FAILED;
2300 }
2301 NdbDictionary::NdbDataPrintFormat dpf;
2302 ndbout << "Set default for column " << origCol->getName()
2303 << " to ";
2304
2305 NdbDictionary::printFormattedValue(ndbout,
2306 dpf,
2307 col,
2308 def);
2309 ndbout << endl;
2310 }
2311 }
2312 }
2313
2314 // ordered index on first few columns
2315 NdbDictionary::Index idx("X");
2316 idx.setTable(tab.getName());
2317 idx.setType(NdbDictionary::Index::OrderedIndex);
2318 idx.setLogging(false);
2319 for (int cnt = 0, i_hate_broken_compilers = 0;
2320 cnt < 3 &&
2321 i_hate_broken_compilers < tab.getNoOfColumns();
2322 i_hate_broken_compilers++) {
2323 if (NdbSqlUtil::check_column_for_ordered_index
2324 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
2325 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
2326 NdbDictionary::Column::StorageTypeDisk)
2327 {
2328 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
2329 cnt++;
2330 }
2331 }
2332
2333 for (Uint32 i = 0; i<(Uint32)tab.getNoOfColumns(); i++)
2334 {
2335 if (tab.getColumn(i)->getStorageType() ==
2336 NdbDictionary::Column::StorageTypeDisk)
2337 {
2338 NDBT_Tables::create_default_tablespace(pNdb);
2339 break;
2340 }
2341 }
2342
2343 const int loops = ctx->getNumLoops();
2344 int result = NDBT_OK;
2345 (void)pDic->dropTable(tab.getName());
2346
2347 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
2348 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
2349
2350 for (int l = 0; l < loops; l++) {
2351 for (unsigned i0 = 0; i0 < acccnt; i0++) {
2352 unsigned j = (l == 0 ? i0 : myRandom48(acccnt));
2353 int errval = acclst[j];
2354 if (errNo != 0 && errNo != errval)
2355 continue;
2356 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
2357 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
2358 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
2359 "failed to set error insert");
2360 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2361 CHECK2(pDic->createTable(tab) != 0,
2362 "failed to fail after error insert " << errval);
2363 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
2364 "failed to clean error insert value");
2365 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
2366 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2367 CHECK2(pDic->createTable(tab) == 0,
2368 pDic->getNdbError());
2369 CHECK2(pDic->dropTable(tab.getName()) == 0,
2370 pDic->getNdbError());
2371 }
2372 for (unsigned i1 = 0; i1 < tupcnt; i1++) {
2373 unsigned j = (l == 0 ? i1 : myRandom48(tupcnt));
2374 int errval = tuplst[j];
2375 if (errNo != 0 && errNo != errval)
2376 continue;
2377 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
2378 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
2379 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
2380 "failed to set error insert");
2381 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2382 CHECK2(pDic->createTable(tab) != 0,
2383 "failed to fail after error insert " << errval);
2384 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
2385 "failed to clean error insert value");
2386 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
2387 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2388 CHECK2(pDic->createTable(tab) == 0,
2389 pDic->getNdbError());
2390 CHECK2(pDic->dropTable(tab.getName()) == 0,
2391 pDic->getNdbError());
2392 }
2393 for (unsigned i2 = 0; i2 < tuxcnt; i2++) {
2394 unsigned j = (l == 0 ? i2 : myRandom48(tuxcnt));
2395 int errval = tuxlst[j];
2396 if (errNo != 0 && errNo != errval)
2397 continue;
2398 CHECK2(pDic->createTable(tab) == 0,
2399 pDic->getNdbError());
2400
2401 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
2402 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
2403 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
2404 "failed to set error insert");
2405 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2406
2407 CHECK2(pDic->createIndex(idx) != 0,
2408 "failed to fail after error insert " << errval);
2409 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
2410 "failed to clean error insert value");
2411 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
2412 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2413 CHECK2(pDic->createIndex(idx) == 0,
2414 pDic->getNdbError());
2415 CHECK2(pDic->dropTable(tab.getName()) == 0,
2416 pDic->getNdbError());
2417 }
2418 }
2419 end:
2420 return result;
2421 }
2422
2423 // NFNR
2424
2425 // Restarter controls dict ops : 1-run 2-pause 3-stop
2426 // synced by polling...
2427
2428 static bool
send_dict_ops_cmd(NDBT_Context * ctx,Uint32 cmd)2429 send_dict_ops_cmd(NDBT_Context* ctx, Uint32 cmd)
2430 {
2431 ctx->setProperty("DictOps_CMD", cmd);
2432 while (1) {
2433 if (ctx->isTestStopped())
2434 return false;
2435 if (ctx->getProperty("DictOps_ACK") == cmd)
2436 break;
2437 NdbSleep_MilliSleep(100);
2438 }
2439 return true;
2440 }
2441
2442 static bool
recv_dict_ops_run(NDBT_Context * ctx)2443 recv_dict_ops_run(NDBT_Context* ctx)
2444 {
2445 while (1) {
2446 if (ctx->isTestStopped())
2447 return false;
2448 Uint32 cmd = ctx->getProperty("DictOps_CMD");
2449 ctx->setProperty("DictOps_ACK", cmd);
2450 if (cmd == 1)
2451 break;
2452 if (cmd == 3)
2453 return false;
2454 NdbSleep_MilliSleep(100);
2455 }
2456 return true;
2457 }
2458
2459 int
runRestarts(NDBT_Context * ctx,NDBT_Step * step)2460 runRestarts(NDBT_Context* ctx, NDBT_Step* step)
2461 {
2462 static int errlst_master[] = { // non-crashing
2463 7175, // send one fake START_PERMREF
2464 0
2465 };
2466 static int errlst_node[] = {
2467 7174, // crash before sending DICT_LOCK_REQ
2468 7176, // pretend master does not support DICT lock
2469 7121, // crash at receive START_PERMCONF
2470 0
2471 };
2472 const uint errcnt_master = sizeof(errlst_master)/sizeof(errlst_master[0]);
2473 const uint errcnt_node = sizeof(errlst_node)/sizeof(errlst_node[0]);
2474
2475 myRandom48Init((long)NdbTick_CurrentMillisecond());
2476 NdbRestarter restarter;
2477 int result = NDBT_OK;
2478 const int loops = ctx->getNumLoops();
2479
2480 for (int l = 0; l < loops && result == NDBT_OK; l++) {
2481 g_info << "1: === loop " << l << " ===" << endl;
2482
2483 // assuming 2-way replicated
2484
2485 int numnodes = restarter.getNumDbNodes();
2486 CHECK(numnodes >= 1);
2487 if (numnodes == 1)
2488 break;
2489
2490 int masterNodeId = restarter.getMasterNodeId();
2491 CHECK(masterNodeId != -1);
2492
2493 // for more complex cases need more restarter support methods
2494
2495 int nodeIdList[2] = { 0, 0 };
2496 int nodeIdCnt = 0;
2497
2498 if (numnodes >= 2) {
2499 int rand = myRandom48(numnodes);
2500 int nodeId = restarter.getRandomNotMasterNodeId(rand);
2501 CHECK(nodeId != -1);
2502 nodeIdList[nodeIdCnt++] = nodeId;
2503 }
2504
2505 if (numnodes >= 4 && myRandom48(2) == 0) {
2506 int rand = myRandom48(numnodes);
2507 int nodeId = restarter.getRandomNodeOtherNodeGroup(nodeIdList[0], rand);
2508 CHECK(nodeId != -1);
2509 if (nodeId != masterNodeId)
2510 nodeIdList[nodeIdCnt++] = nodeId;
2511 }
2512
2513 g_info << "1: master=" << masterNodeId << " nodes=" << nodeIdList[0] << "," << nodeIdList[1] << endl;
2514
2515 const uint timeout = 60; //secs for node wait
2516 const unsigned maxsleep = 2000; //ms
2517
2518 bool NF_ops = ctx->getProperty("Restart_NF_ops");
2519 uint NF_type = ctx->getProperty("Restart_NF_type");
2520 bool NR_ops = ctx->getProperty("Restart_NR_ops");
2521 bool NR_error = ctx->getProperty("Restart_NR_error");
2522
2523 g_info << "1: " << (NF_ops ? "run" : "pause") << " dict ops" << endl;
2524 if (! send_dict_ops_cmd(ctx, NF_ops ? 1 : 2))
2525 break;
2526 NdbSleep_MilliSleep(myRandom48(maxsleep));
2527
2528 {
2529 for (int i = 0; i < nodeIdCnt; i++) {
2530 int nodeId = nodeIdList[i];
2531
2532 bool nostart = true;
2533 bool abort = NF_type == 0 ? myRandom48(2) : (NF_type == 2);
2534 bool initial = myRandom48(2);
2535
2536 char flags[40];
2537 strcpy(flags, "flags: nostart");
2538 if (abort)
2539 strcat(flags, ",abort");
2540 if (initial)
2541 strcat(flags, ",initial");
2542
2543 g_info << "1: restart " << nodeId << " " << flags << endl;
2544 CHECK(restarter.restartOneDbNode(nodeId, initial, nostart, abort) == 0);
2545 }
2546 }
2547
2548 g_info << "1: wait for nostart" << endl;
2549 CHECK(restarter.waitNodesNoStart(nodeIdList, nodeIdCnt, timeout) == 0);
2550 NdbSleep_MilliSleep(myRandom48(maxsleep));
2551
2552 int err_master = 0;
2553 int err_node[2] = { 0, 0 };
2554
2555 if (NR_error) {
2556 err_master = errlst_master[l % errcnt_master];
2557
2558 // limitation: cannot have 2 node restarts and crash_insert
2559 // one node may die for real (NF during startup)
2560
2561 for (int i = 0; i < nodeIdCnt && nodeIdCnt == 1; i++) {
2562 err_node[i] = errlst_node[l % errcnt_node];
2563
2564 // 7176 - no DICT lock protection
2565
2566 if (err_node[i] == 7176) {
2567 g_info << "1: no dict ops due to error insert "
2568 << err_node[i] << endl;
2569 NR_ops = false;
2570 }
2571 }
2572 }
2573
2574 g_info << "1: " << (NR_ops ? "run" : "pause") << " dict ops" << endl;
2575 if (! send_dict_ops_cmd(ctx, NR_ops ? 1 : 2))
2576 break;
2577 NdbSleep_MilliSleep(myRandom48(maxsleep));
2578
2579 g_info << "1: start nodes" << endl;
2580 CHECK(restarter.startNodes(nodeIdList, nodeIdCnt) == 0);
2581
2582 if (NR_error) {
2583 {
2584 int err = err_master;
2585 if (err != 0) {
2586 g_info << "1: insert master error " << err << endl;
2587 CHECK(restarter.insertErrorInNode(masterNodeId, err) == 0);
2588 }
2589 }
2590
2591 for (int i = 0; i < nodeIdCnt; i++) {
2592 int nodeId = nodeIdList[i];
2593
2594 int err = err_node[i];
2595 if (err != 0) {
2596 g_info << "1: insert node " << nodeId << " error " << err << endl;
2597 CHECK(restarter.insertErrorInNode(nodeId, err) == 0);
2598 }
2599 }
2600 }
2601 NdbSleep_MilliSleep(myRandom48(maxsleep));
2602
2603 g_info << "1: wait cluster started" << endl;
2604 CHECK(restarter.waitClusterStarted(timeout) == 0);
2605 NdbSleep_MilliSleep(myRandom48(maxsleep));
2606
2607 g_info << "1: restart done" << endl;
2608 }
2609
2610 g_info << "1: stop dict ops" << endl;
2611 send_dict_ops_cmd(ctx, 3);
2612
2613 return result;
2614 }
2615
2616 int
runDictOps(NDBT_Context * ctx,NDBT_Step * step)2617 runDictOps(NDBT_Context* ctx, NDBT_Step* step)
2618 {
2619 myRandom48Init((long)NdbTick_CurrentMillisecond());
2620 int result = NDBT_OK;
2621
2622 for (int l = 0; result == NDBT_OK; l++) {
2623 if (! recv_dict_ops_run(ctx))
2624 break;
2625
2626 g_info << "2: === loop " << l << " ===" << endl;
2627
2628 Ndb* pNdb = GETNDB(step);
2629 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2630 const NdbDictionary::Table* pTab = ctx->getTab();
2631 //const char* tabName = pTab->getName(); //XXX what goes on?
2632 char tabName[40];
2633 strcpy(tabName, pTab->getName());
2634
2635 const unsigned long maxsleep = 100; //ms
2636
2637 g_info << "2: create table" << endl;
2638 {
2639 uint count = 0;
2640 try_create:
2641 count++;
2642 if (pDic->createTable(*pTab) != 0) {
2643 const NdbError err = pDic->getNdbError();
2644 if (count == 1)
2645 g_err << "2: " << tabName << ": create failed: " << err << endl;
2646 if (err.code != 711) {
2647 result = NDBT_FAILED;
2648 break;
2649 }
2650 NdbSleep_MilliSleep(myRandom48(maxsleep));
2651 goto try_create;
2652 }
2653 }
2654 NdbSleep_MilliSleep(myRandom48(maxsleep));
2655
2656 g_info << "2: verify create" << endl;
2657 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
2658 if (pTab2 == NULL) {
2659 const NdbError err = pDic->getNdbError();
2660 g_err << "2: " << tabName << ": verify create: " << err << endl;
2661 result = NDBT_FAILED;
2662 break;
2663 }
2664 NdbSleep_MilliSleep(myRandom48(maxsleep));
2665
2666 // replace by the Retrieved table
2667 pTab = pTab2;
2668
2669 // create indexes
2670 const char** indlist = NDBT_Tables::getIndexes(tabName);
2671 uint indnum = 0;
2672 while (indlist != 0 && *indlist != 0) {
2673 uint count = 0;
2674 try_create_index:
2675 count++;
2676 if (count == 1)
2677 g_info << "2: create index " << indnum << " " << *indlist << endl;
2678 NdbDictionary::Index ind;
2679 char indName[200];
2680 sprintf(indName, "%s_X%u", tabName, indnum);
2681 ind.setName(indName);
2682 ind.setTable(tabName);
2683 if (strcmp(*indlist, "UNIQUE") == 0) {
2684 ind.setType(NdbDictionary::Index::UniqueHashIndex);
2685 ind.setLogging(pTab->getLogging());
2686 } else if (strcmp(*indlist, "ORDERED") == 0) {
2687 ind.setType(NdbDictionary::Index::OrderedIndex);
2688 ind.setLogging(false);
2689 } else {
2690 require(false);
2691 }
2692 const char** indtemp = indlist;
2693 while (*++indtemp != 0) {
2694 ind.addColumn(*indtemp);
2695 }
2696 if (pDic->createIndex(ind) != 0) {
2697 const NdbError err = pDic->getNdbError();
2698 if (count == 1)
2699 g_err << "2: " << indName << ": create failed: " << err << endl;
2700 if (err.code != 711) {
2701 result = NDBT_FAILED;
2702 break;
2703 }
2704 NdbSleep_MilliSleep(myRandom48(maxsleep));
2705 goto try_create_index;
2706 }
2707 indlist = ++indtemp;
2708 indnum++;
2709 }
2710 if (result == NDBT_FAILED)
2711 break;
2712
2713 uint indcount = indnum;
2714
2715 int records = myRandom48(ctx->getNumRecords());
2716 g_info << "2: load " << records << " records" << endl;
2717 HugoTransactions hugoTrans(*pTab);
2718 if (hugoTrans.loadTable(pNdb, records) != 0) {
2719 // XXX get error code from hugo
2720 g_err << "2: " << tabName << ": load failed" << endl;
2721 result = NDBT_FAILED;
2722 break;
2723 }
2724 NdbSleep_MilliSleep(myRandom48(maxsleep));
2725
2726 // drop indexes
2727 indnum = 0;
2728 while (indnum < indcount) {
2729 uint count = 0;
2730 try_drop_index:
2731 count++;
2732 if (count == 1)
2733 g_info << "2: drop index " << indnum << endl;
2734 char indName[200];
2735 sprintf(indName, "%s_X%u", tabName, indnum);
2736 if (pDic->dropIndex(indName, tabName) != 0) {
2737 const NdbError err = pDic->getNdbError();
2738 if (count == 1)
2739 g_err << "2: " << indName << ": drop failed: " << err << endl;
2740 if (err.code != 711) {
2741 result = NDBT_FAILED;
2742 break;
2743 }
2744 NdbSleep_MilliSleep(myRandom48(maxsleep));
2745 goto try_drop_index;
2746 }
2747 indnum++;
2748 }
2749 if (result == NDBT_FAILED)
2750 break;
2751
2752 g_info << "2: drop" << endl;
2753 {
2754 uint count = 0;
2755 try_drop:
2756 count++;
2757 if (pDic->dropTable(tabName) != 0) {
2758 const NdbError err = pDic->getNdbError();
2759 if (count == 1)
2760 g_err << "2: " << tabName << ": drop failed: " << err << endl;
2761 if (err.code != 711) {
2762 result = NDBT_FAILED;
2763 break;
2764 }
2765 NdbSleep_MilliSleep(myRandom48(maxsleep));
2766 goto try_drop;
2767 }
2768 }
2769 NdbSleep_MilliSleep(myRandom48(maxsleep));
2770
2771 g_info << "2: verify drop" << endl;
2772 const NdbDictionary::Table* pTab3 = pDic->getTable(tabName);
2773 if (pTab3 != NULL) {
2774 g_err << "2: " << tabName << ": verify drop: table exists" << endl;
2775 result = NDBT_FAILED;
2776 break;
2777 }
2778 if (pDic->getNdbError().code != 709 &&
2779 pDic->getNdbError().code != 723) {
2780 const NdbError err = pDic->getNdbError();
2781 g_err << "2: " << tabName << ": verify drop: " << err << endl;
2782 result = NDBT_FAILED;
2783 break;
2784 }
2785 NdbSleep_MilliSleep(myRandom48(maxsleep));
2786 }
2787
2788 return result;
2789 }
2790
2791 int
runBug21755(NDBT_Context * ctx,NDBT_Step * step)2792 runBug21755(NDBT_Context* ctx, NDBT_Step* step)
2793 {
2794 char buf[256];
2795 NdbRestarter res;
2796 NdbDictionary::Table pTab0 = * ctx->getTab();
2797 NdbDictionary::Table pTab1 = pTab0;
2798
2799 if (res.getNumDbNodes() < 2)
2800 return NDBT_OK;
2801
2802 Ndb* pNdb = GETNDB(step);
2803 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2804
2805 if (pDic->createTable(pTab0))
2806 {
2807 ndbout << pDic->getNdbError() << endl;
2808 return NDBT_FAILED;
2809 }
2810
2811 NdbDictionary::Index idx0;
2812 BaseString::snprintf(buf, sizeof(buf), "%s-idx", pTab0.getName());
2813 idx0.setName(buf);
2814 idx0.setType(NdbDictionary::Index::OrderedIndex);
2815 idx0.setTable(pTab0.getName());
2816 idx0.setStoredIndex(false);
2817 for (Uint32 i = 0; i<(Uint32)pTab0.getNoOfColumns(); i++)
2818 {
2819 const NdbDictionary::Column * col = pTab0.getColumn(i);
2820 if(col->getPrimaryKey()){
2821 idx0.addIndexColumn(col->getName());
2822 }
2823 }
2824
2825 if (pDic->createIndex(idx0))
2826 {
2827 ndbout << pDic->getNdbError() << endl;
2828 return NDBT_FAILED;
2829 }
2830
2831 BaseString::snprintf(buf, sizeof(buf), "%s-2", pTab1.getName());
2832 pTab1.setName(buf);
2833
2834 if (pDic->createTable(pTab1))
2835 {
2836 ndbout << pDic->getNdbError() << endl;
2837 return NDBT_FAILED;
2838 }
2839
2840 {
2841 const NdbDictionary::Table* pTab = pDic->getTable(pTab0.getName());
2842 if (pTab == NULL) {
2843 g_err << "Table 'pTab0': " << pTab0.getName()
2844 << ", not found on line " << __LINE__
2845 <<", error: " << pDic->getNdbError()
2846 << endl;
2847 return NDBT_FAILED;
2848 }
2849 HugoTransactions t0 (*pTab);
2850 t0.loadTable(pNdb, 1000);
2851 }
2852
2853 {
2854 const NdbDictionary::Table* pTab = pDic->getTable(pTab1.getName());
2855 if (pTab == NULL) {
2856 g_err << "Table 'pTab1': " << pTab1.getName()
2857 << ", not found on line " << __LINE__
2858 <<", error: " << pDic->getNdbError()
2859 << endl;
2860 return NDBT_FAILED;
2861 }
2862 HugoTransactions t1 (*pTab);
2863 t1.loadTable(pNdb, 1000);
2864 }
2865
2866 int node = res.getRandomNotMasterNodeId(rand());
2867 res.restartOneDbNode(node, false, true, true);
2868
2869 if (pDic->dropTable(pTab1.getName()))
2870 {
2871 ndbout << pDic->getNdbError() << endl;
2872 return NDBT_FAILED;
2873 }
2874
2875 BaseString::snprintf(buf, sizeof(buf), "%s-idx2", pTab0.getName());
2876 idx0.setName(buf);
2877 if (pDic->createIndex(idx0))
2878 {
2879 ndbout << pDic->getNdbError() << endl;
2880 return NDBT_FAILED;
2881 }
2882
2883 res.waitNodesNoStart(&node, 1);
2884 res.startNodes(&node, 1);
2885
2886 if (res.waitClusterStarted())
2887 {
2888 return NDBT_FAILED;
2889 }
2890
2891 if (pDic->dropTable(pTab0.getName()))
2892 {
2893 ndbout << pDic->getNdbError() << endl;
2894 return NDBT_FAILED;
2895 }
2896
2897 return NDBT_OK;
2898 }
2899
2900 static
2901 int
create_tablespace(NdbDictionary::Dictionary * pDict,const char * lgname,const char * tsname,const char * dfname)2902 create_tablespace(NdbDictionary::Dictionary* pDict,
2903 const char * lgname,
2904 const char * tsname,
2905 const char * dfname)
2906 {
2907 NdbDictionary::Tablespace ts;
2908 ts.setName(tsname);
2909 ts.setExtentSize(1024*1024);
2910 ts.setDefaultLogfileGroup(lgname);
2911
2912 if(pDict->createTablespace(ts) != 0)
2913 {
2914 g_err << "Failed to create tablespace:"
2915 << endl << pDict->getNdbError() << endl;
2916 return NDBT_FAILED;
2917 }
2918
2919 NdbDictionary::Datafile df;
2920 df.setPath(dfname);
2921 df.setSize(1*1024*1024);
2922 df.setTablespace(tsname);
2923
2924 if(pDict->createDatafile(df) != 0)
2925 {
2926 g_err << "Failed to create datafile:"
2927 << endl << pDict->getNdbError() << endl;
2928 return NDBT_FAILED;
2929 }
2930 return 0;
2931 }
2932
2933 int
runBug24631(NDBT_Context * ctx,NDBT_Step * step)2934 runBug24631(NDBT_Context* ctx, NDBT_Step* step)
2935 {
2936 char tsname[256];
2937 char dfname[256];
2938 char lgname[256];
2939 char ufname[256];
2940 NdbRestarter res;
2941
2942 if (res.getNumDbNodes() < 2)
2943 return NDBT_OK;
2944
2945 Ndb* pNdb = GETNDB(step);
2946 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
2947
2948 NdbDictionary::Dictionary::List list;
2949 if (pDict->listObjects(list) == -1)
2950 return NDBT_FAILED;
2951
2952 const char * lgfound = 0;
2953
2954 for (Uint32 i = 0; i<list.count; i++)
2955 {
2956 switch(list.elements[i].type){
2957 case NdbDictionary::Object::LogfileGroup:
2958 lgfound = list.elements[i].name;
2959 break;
2960 default:
2961 break;
2962 }
2963 if (lgfound)
2964 break;
2965 }
2966
2967 if (lgfound == 0)
2968 {
2969 BaseString::snprintf(lgname, sizeof(lgname), "LG-%u", rand());
2970 NdbDictionary::LogfileGroup lg;
2971
2972 lg.setName(lgname);
2973 lg.setUndoBufferSize(8*1024*1024);
2974 if(pDict->createLogfileGroup(lg) != 0)
2975 {
2976 g_err << "Failed to create logfilegroup:"
2977 << endl << pDict->getNdbError() << endl;
2978 return NDBT_FAILED;
2979 }
2980
2981 NdbDictionary::Undofile uf;
2982 BaseString::snprintf(ufname, sizeof(ufname), "%s-%u", lgname, rand());
2983 uf.setPath(ufname);
2984 uf.setSize(2*1024*1024);
2985 uf.setLogfileGroup(lgname);
2986
2987 if(pDict->createUndofile(uf) != 0)
2988 {
2989 g_err << "Failed to create undofile:"
2990 << endl << pDict->getNdbError() << endl;
2991 return NDBT_FAILED;
2992 }
2993 }
2994 else
2995 {
2996 BaseString::snprintf(lgname, sizeof(lgname), "%s", lgfound);
2997 }
2998
2999 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
3000 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u.dat", tsname, rand());
3001
3002 if (create_tablespace(pDict, lgname, tsname, dfname))
3003 return NDBT_FAILED;
3004
3005
3006 int node = res.getRandomNotMasterNodeId(rand());
3007 res.restartOneDbNode(node, false, true, true);
3008 NdbSleep_SecSleep(3);
3009
3010 if (pDict->dropDatafile(pDict->getDatafile(0, dfname)) != 0)
3011 {
3012 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
3013 return NDBT_FAILED;
3014 }
3015
3016 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
3017 {
3018 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3019 return NDBT_FAILED;
3020 }
3021
3022 if (res.waitNodesNoStart(&node, 1))
3023 return NDBT_FAILED;
3024
3025 res.startNodes(&node, 1);
3026 if (res.waitClusterStarted())
3027 return NDBT_FAILED;
3028
3029 if (create_tablespace(pDict, lgname, tsname, dfname))
3030 return NDBT_FAILED;
3031
3032 if (pDict->dropDatafile(pDict->getDatafile(0, dfname)) != 0)
3033 {
3034 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
3035 return NDBT_FAILED;
3036 }
3037
3038 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
3039 {
3040 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3041 return NDBT_FAILED;
3042 }
3043
3044 if (lgfound == 0)
3045 {
3046 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgname)) != 0)
3047 return NDBT_FAILED;
3048 }
3049
3050 return NDBT_OK;
3051 }
3052
3053 int
runBug29186(NDBT_Context * ctx,NDBT_Step * step)3054 runBug29186(NDBT_Context* ctx, NDBT_Step* step)
3055 {
3056 int lgError = 15000;
3057 int tsError = 16000;
3058 char lgname[256];
3059 char ufname[256];
3060 char tsname[256];
3061 char dfname[256];
3062
3063 NdbRestarter restarter;
3064
3065 if (restarter.getNumDbNodes() < 2){
3066 ctx->stopTest();
3067 return NDBT_OK;
3068 }
3069
3070 Ndb* pNdb = GETNDB(step);
3071 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3072 NdbDictionary::Dictionary::List list;
3073
3074 if (pDict->listObjects(list) == -1)
3075 return NDBT_FAILED;
3076
3077 // 1.create logfile group
3078 const char * lgfound = 0;
3079
3080 for (Uint32 i = 0; i<list.count; i++)
3081 {
3082 switch(list.elements[i].type){
3083 case NdbDictionary::Object::LogfileGroup:
3084 lgfound = list.elements[i].name;
3085 break;
3086 default:
3087 break;
3088 }
3089 if (lgfound)
3090 break;
3091 }
3092
3093 if (lgfound == 0)
3094 {
3095 BaseString::snprintf(lgname, sizeof(lgname), "LG-%u", rand());
3096 NdbDictionary::LogfileGroup lg;
3097
3098 lg.setName(lgname);
3099 lg.setUndoBufferSize(8*1024*1024);
3100 if(pDict->createLogfileGroup(lg) != 0)
3101 {
3102 g_err << "Failed to create logfilegroup:"
3103 << endl << pDict->getNdbError() << endl;
3104 return NDBT_FAILED;
3105 }
3106 }
3107 else
3108 {
3109 BaseString::snprintf(lgname, sizeof(lgname), "%s", lgfound);
3110 }
3111
3112 if(restarter.waitClusterStarted(60)){
3113 g_err << "waitClusterStarted failed"<< endl;
3114 return NDBT_FAILED;
3115 }
3116
3117 if(restarter.insertErrorInAllNodes(lgError) != 0){
3118 g_err << "failed to set error insert"<< endl;
3119 return NDBT_FAILED;
3120 }
3121
3122 g_info << "error inserted" << endl;
3123 g_info << "waiting some before add log file" << endl;
3124 g_info << "starting create log file group" << endl;
3125
3126 NdbDictionary::Undofile uf;
3127 BaseString::snprintf(ufname, sizeof(ufname), "%s-%u", lgname, rand());
3128 uf.setPath(ufname);
3129 uf.setSize(2*1024*1024);
3130 uf.setLogfileGroup(lgname);
3131
3132 if(pDict->createUndofile(uf) == 0)
3133 {
3134 g_err << "Create log file group should fail on error_insertion " << lgError << endl;
3135 return NDBT_FAILED;
3136 }
3137
3138 //clear lg error
3139 if(restarter.insertErrorInAllNodes(15099) != 0){
3140 g_err << "failed to set error insert"<< endl;
3141 return NDBT_FAILED;
3142 }
3143 NdbSleep_SecSleep(5);
3144
3145 //lg error has been cleared, so we can add undo file
3146 if(pDict->createUndofile(uf) != 0)
3147 {
3148 g_err << "Failed to create undofile:"
3149 << endl << pDict->getNdbError() << endl;
3150 return NDBT_FAILED;
3151 }
3152
3153 if(restarter.waitClusterStarted(60)){
3154 g_err << "waitClusterStarted failed"<< endl;
3155 return NDBT_FAILED;
3156 }
3157
3158 if(restarter.insertErrorInAllNodes(tsError) != 0){
3159 g_err << "failed to set error insert"<< endl;
3160 return NDBT_FAILED;
3161 }
3162 g_info << "error inserted" << endl;
3163 g_info << "waiting some before create table space" << endl;
3164 g_info << "starting create table space" << endl;
3165
3166 //r = runCreateTablespace(ctx, step);
3167 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
3168 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u-1.dat", tsname, rand());
3169
3170 NdbDictionary::Tablespace ts;
3171 ts.setName(tsname);
3172 ts.setExtentSize(1024*1024);
3173 ts.setDefaultLogfileGroup(lgname);
3174
3175 if(pDict->createTablespace(ts) != 0)
3176 {
3177 g_err << "Failed to create tablespace:"
3178 << endl << pDict->getNdbError() << endl;
3179 return NDBT_FAILED;
3180 }
3181
3182 NdbDictionary::Datafile df;
3183 df.setPath(dfname);
3184 df.setSize(1*1024*1024);
3185 df.setTablespace(tsname);
3186
3187 if(pDict->createDatafile(df) == 0)
3188 {
3189 g_err << "Create table space should fail on error_insertion " << tsError << endl;
3190 return NDBT_FAILED;
3191 }
3192 //Clear the inserted error
3193 if(restarter.insertErrorInAllNodes(16099) != 0){
3194 g_err << "failed to set error insert"<< endl;
3195 return NDBT_FAILED;
3196 }
3197 NdbSleep_SecSleep(5);
3198
3199 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
3200 {
3201 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3202 return NDBT_FAILED;
3203 }
3204
3205 if (lgfound == 0)
3206 {
3207 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgname)) != 0)
3208 return NDBT_FAILED;
3209 }
3210
3211 return NDBT_OK;
3212 }
3213
3214 struct RandSchemaOp
3215 {
RandSchemaOpRandSchemaOp3216 RandSchemaOp(unsigned * randseed = 0) {
3217 if (randseed == 0)
3218 {
3219 ownseed = (unsigned)NdbTick_CurrentMillisecond();
3220 seed = &ownseed;
3221 }
3222 else
3223 {
3224 seed = randseed;
3225 }
3226 }
3227 struct Obj
3228 {
3229 BaseString m_name;
3230 Uint32 m_type;
3231 struct Obj* m_parent;
3232 Vector<Obj*> m_dependant;
3233 };
3234
3235 Vector<Obj*> m_objects;
3236
3237 int schema_op(Ndb*);
3238 int validate(Ndb*);
3239 int cleanup(Ndb*);
3240
3241 Obj* get_obj(Uint32 mask);
3242 int create_table(Ndb*);
3243 int create_index(Ndb*, Obj*);
3244 int alter_table(Ndb*, Obj*);
3245 int drop_obj(Ndb*, Obj*);
3246
3247 void remove_obj(Obj*);
3248 private:
3249 unsigned * seed;
3250 unsigned ownseed;
3251 };
3252
3253 template class Vector<RandSchemaOp::Obj*>;
3254
3255 int
schema_op(Ndb * ndb)3256 RandSchemaOp::schema_op(Ndb* ndb)
3257 {
3258 struct Obj* obj = 0;
3259 Uint32 type = 0;
3260 loop:
3261 switch(ndb_rand_r(seed) % 5){
3262 case 0:
3263 return create_table(ndb);
3264 case 1:
3265 if ((obj = get_obj(1 << NdbDictionary::Object::UserTable)) == 0)
3266 goto loop;
3267 return create_index(ndb, obj);
3268 case 2:
3269 type = (1 << NdbDictionary::Object::UserTable);
3270 goto drop_object;
3271 case 3:
3272 type =
3273 (1 << NdbDictionary::Object::UniqueHashIndex) |
3274 (1 << NdbDictionary::Object::OrderedIndex);
3275 goto drop_object;
3276 case 4:
3277 if ((obj = get_obj(1 << NdbDictionary::Object::UserTable)) == 0)
3278 goto loop;
3279 return alter_table(ndb, obj);
3280 default:
3281 goto loop;
3282 }
3283
3284 drop_object:
3285 if ((obj = get_obj(type)) == 0)
3286 goto loop;
3287 return drop_obj(ndb, obj);
3288 }
3289
3290 RandSchemaOp::Obj*
get_obj(Uint32 mask)3291 RandSchemaOp::get_obj(Uint32 mask)
3292 {
3293 Vector<Obj*> tmp;
3294 for (Uint32 i = 0; i<m_objects.size(); i++)
3295 {
3296 if ((1 << m_objects[i]->m_type) & mask)
3297 tmp.push_back(m_objects[i]);
3298 }
3299
3300 if (tmp.size())
3301 {
3302 return tmp[ndb_rand_r(seed)%tmp.size()];
3303 }
3304 return 0;
3305 }
3306
3307 int
create_table(Ndb * ndb)3308 RandSchemaOp::create_table(Ndb* ndb)
3309 {
3310 int numTables = NDBT_Tables::getNumTables();
3311 int num = ndb_rand_r(seed) % numTables;
3312 NdbDictionary::Table pTab = * NDBT_Tables::getTable(num);
3313
3314 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3315 pTab.setForceVarPart(true);
3316
3317 if (pDict->getTable(pTab.getName()))
3318 {
3319 char buf[100];
3320 BaseString::snprintf(buf, sizeof(buf), "%s-%d",
3321 pTab.getName(), ndb_rand_r(seed));
3322 pTab.setName(buf);
3323 if (pDict->createTable(pTab))
3324 return NDBT_FAILED;
3325 }
3326 else
3327 {
3328 if (NDBT_Tables::createTable(ndb, pTab.getName()))
3329 {
3330 return NDBT_FAILED;
3331 }
3332 }
3333
3334 ndbout_c("create table %s", pTab.getName());
3335 const NdbDictionary::Table* tab2 = pDict->getTable(pTab.getName());
3336 if (tab2 == NULL) {
3337 g_err << "Table : " << pTab.getName()
3338 << ", not found on line " << __LINE__
3339 <<", error: " << pDict->getNdbError()
3340 << endl;
3341 return NDBT_FAILED;
3342 }
3343 HugoTransactions trans(*tab2);
3344 trans.loadTable(ndb, 1000);
3345
3346 Obj *obj = new Obj;
3347 obj->m_name.assign(pTab.getName());
3348 obj->m_type = NdbDictionary::Object::UserTable;
3349 obj->m_parent = 0;
3350 m_objects.push_back(obj);
3351
3352 return NDBT_OK;
3353 }
3354
3355 int
create_index(Ndb * ndb,Obj * tab)3356 RandSchemaOp::create_index(Ndb* ndb, Obj* tab)
3357 {
3358 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3359 const NdbDictionary::Table * pTab = pDict->getTable(tab->m_name.c_str());
3360
3361 if (pTab == 0)
3362 {
3363 return NDBT_FAILED;
3364 }
3365
3366 bool ordered = ndb_rand_r(seed) & 1;
3367 bool stored = ndb_rand_r(seed) & 1;
3368
3369 Uint32 type = ordered ?
3370 NdbDictionary::Index::OrderedIndex :
3371 NdbDictionary::Index::UniqueHashIndex;
3372
3373 char buf[255];
3374 BaseString::snprintf(buf, sizeof(buf), "%s-%s",
3375 pTab->getName(),
3376 ordered ? "OI" : "UI");
3377
3378 if (pDict->getIndex(buf, pTab->getName()))
3379 {
3380 // Index exists...let it be ok
3381 return NDBT_OK;
3382 }
3383
3384 ndbout_c("create index %s", buf);
3385 NdbDictionary::Index idx0;
3386 idx0.setName(buf);
3387 idx0.setType((NdbDictionary::Index::Type)type);
3388 idx0.setTable(pTab->getName());
3389 idx0.setStoredIndex(ordered ? false : stored);
3390
3391 for (Uint32 i = 0; i<(Uint32)pTab->getNoOfColumns(); i++)
3392 {
3393 if (pTab->getColumn(i)->getPrimaryKey())
3394 idx0.addColumn(pTab->getColumn(i)->getName());
3395 }
3396 if (pDict->createIndex(idx0))
3397 {
3398 ndbout << pDict->getNdbError() << endl;
3399 return NDBT_FAILED;
3400 }
3401 Obj *obj = new Obj;
3402 obj->m_name.assign(buf);
3403 obj->m_type = type;
3404 obj->m_parent = tab;
3405 m_objects.push_back(obj);
3406
3407 tab->m_dependant.push_back(obj);
3408 return NDBT_OK;
3409 }
3410
3411 int
drop_obj(Ndb * ndb,Obj * obj)3412 RandSchemaOp::drop_obj(Ndb* ndb, Obj* obj)
3413 {
3414 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3415
3416 if (obj->m_type == NdbDictionary::Object::UserTable)
3417 {
3418 ndbout_c("drop table %s", obj->m_name.c_str());
3419 /**
3420 * Drop of table automatically drops all indexes
3421 */
3422 if (pDict->dropTable(obj->m_name.c_str()))
3423 {
3424 return NDBT_FAILED;
3425 }
3426 while(obj->m_dependant.size())
3427 {
3428 remove_obj(obj->m_dependant[0]);
3429 }
3430 remove_obj(obj);
3431 }
3432 else if (obj->m_type == NdbDictionary::Object::UniqueHashIndex ||
3433 obj->m_type == NdbDictionary::Object::OrderedIndex)
3434 {
3435 ndbout_c("drop index %s", obj->m_name.c_str());
3436 if (pDict->dropIndex(obj->m_name.c_str(),
3437 obj->m_parent->m_name.c_str()))
3438 {
3439 return NDBT_FAILED;
3440 }
3441 remove_obj(obj);
3442 }
3443 return NDBT_OK;
3444 }
3445
3446 void
remove_obj(Obj * obj)3447 RandSchemaOp::remove_obj(Obj* obj)
3448 {
3449 Uint32 i;
3450 if (obj->m_parent)
3451 {
3452 bool found = false;
3453 for (i = 0; i<obj->m_parent->m_dependant.size(); i++)
3454 {
3455 if (obj->m_parent->m_dependant[i] == obj)
3456 {
3457 found = true;
3458 obj->m_parent->m_dependant.erase(i);
3459 break;
3460 }
3461 }
3462 require(found);
3463 }
3464
3465 {
3466 bool found = false;
3467 for (i = 0; i<m_objects.size(); i++)
3468 {
3469 if (m_objects[i] == obj)
3470 {
3471 found = true;
3472 m_objects.erase(i);
3473 break;
3474 }
3475 }
3476 require(found);
3477 }
3478 delete obj;
3479 }
3480
3481 int
alter_table(Ndb * ndb,Obj * obj)3482 RandSchemaOp::alter_table(Ndb* ndb, Obj* obj)
3483 {
3484 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3485 const NdbDictionary::Table * pOld = pDict->getTable(obj->m_name.c_str());
3486 NdbDictionary::Table tNew = * pOld;
3487
3488 BaseString ops;
3489 unsigned mask = 3;
3490
3491 unsigned type;
3492 while (ops.length() == 0 && (mask != 0))
3493 {
3494 switch((type = (ndb_rand_r(seed) & 1))){
3495 default:
3496 case 0:{
3497 if ((mask & (1 << type)) == 0)
3498 break;
3499 BaseString name;
3500 name.assfmt("newcol_%d", tNew.getNoOfColumns());
3501 NdbDictionary::Column col(name.c_str());
3502 col.setType(NdbDictionary::Column::Unsigned);
3503 col.setDynamic(true);
3504 col.setPrimaryKey(false);
3505 col.setNullable(true);
3506 NdbDictionary::Table save = tNew;
3507 tNew.addColumn(col);
3508 if (!pDict->supportedAlterTable(* pOld, tNew))
3509 {
3510 ndbout_c("not supported...");
3511 mask &= ~(1 << type);
3512 tNew = save;
3513 break;
3514 }
3515 ops.append(" addcol");
3516 break;
3517 }
3518 case 1:{
3519 BaseString name;
3520 do
3521 {
3522 unsigned no = ndb_rand_r(seed);
3523 name.assfmt("%s_%u", pOld->getName(), no);
3524 } while (pDict->getTable(name.c_str()));
3525 tNew.setName(name.c_str());
3526 ops.appfmt(" rename: %s", name.c_str());
3527 break;
3528 }
3529
3530 }
3531 }
3532
3533 if (ops.length())
3534 {
3535 ndbout_c("altering %s ops: %s", pOld->getName(), ops.c_str());
3536 if (pDict->alterTable(*pOld, tNew) != 0)
3537 {
3538 g_err << pDict->getNdbError() << endl;
3539 return NDBT_FAILED;
3540 }
3541 pDict->invalidateTable(pOld->getName());
3542 if (strcmp(pOld->getName(), tNew.getName()))
3543 {
3544 obj->m_name.assign(tNew.getName());
3545 }
3546 }
3547
3548 return NDBT_OK;
3549 }
3550
3551
3552 int
validate(Ndb * ndb)3553 RandSchemaOp::validate(Ndb* ndb)
3554 {
3555 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3556 for (Uint32 i = 0; i<m_objects.size(); i++)
3557 {
3558 if (m_objects[i]->m_type == NdbDictionary::Object::UserTable)
3559 {
3560 const NdbDictionary::Table* tab2 =
3561 pDict->getTable(m_objects[i]->m_name.c_str());
3562
3563 if (tab2 == NULL) {
3564 g_err << "Table: " << m_objects[i]->m_name.c_str()
3565 << ", not found on line " << __LINE__
3566 <<", error: " << pDict->getNdbError()
3567 << endl;
3568 return NDBT_FAILED;
3569 }
3570 HugoTransactions trans(*tab2);
3571 trans.scanUpdateRecords(ndb, 1000);
3572 trans.clearTable(ndb);
3573 trans.loadTable(ndb, 1000);
3574 }
3575 }
3576
3577 return NDBT_OK;
3578 }
3579
3580 /*
3581 SystemTable = 1, ///< System table
3582 UserTable = 2, ///< User table (may be temporary)
3583 UniqueHashIndex = 3, ///< Unique un-ordered hash index
3584 OrderedIndex = 6, ///< Non-unique ordered index
3585 HashIndexTrigger = 7, ///< Index maintenance, internal
3586 IndexTrigger = 8, ///< Index maintenance, internal
3587 SubscriptionTrigger = 9,///< Backup or replication, internal
3588 ReadOnlyConstraint = 10,///< Trigger, internal
3589 Tablespace = 20, ///< Tablespace
3590 LogfileGroup = 21, ///< Logfile group
3591 Datafile = 22, ///< Datafile
3592 Undofile = 23 ///< Undofile
3593 */
3594
3595 int
cleanup(Ndb * ndb)3596 RandSchemaOp::cleanup(Ndb* ndb)
3597 {
3598 Int32 i;
3599 for (i = m_objects.size() - 1; i >= 0; i--)
3600 {
3601 switch(m_objects[i]->m_type){
3602 case NdbDictionary::Object::UniqueHashIndex:
3603 case NdbDictionary::Object::OrderedIndex:
3604 if (drop_obj(ndb, m_objects[i]))
3605 return NDBT_FAILED;
3606
3607 break;
3608 default:
3609 break;
3610 }
3611 }
3612
3613 for (i = m_objects.size() - 1; i >= 0; i--)
3614 {
3615 switch(m_objects[i]->m_type){
3616 case NdbDictionary::Object::UserTable:
3617 if (drop_obj(ndb, m_objects[i]))
3618 return NDBT_FAILED;
3619 break;
3620 default:
3621 break;
3622 }
3623 }
3624
3625 require(m_objects.size() == 0);
3626 return NDBT_OK;
3627 }
3628
3629 extern unsigned opt_seed;
3630
3631 int
runDictRestart(NDBT_Context * ctx,NDBT_Step * step)3632 runDictRestart(NDBT_Context* ctx, NDBT_Step* step)
3633 {
3634 Ndb* pNdb = GETNDB(step);
3635 int loops = ctx->getNumLoops();
3636
3637 unsigned seed = opt_seed;
3638 NdbMixRestarter res(&seed);
3639 RandSchemaOp dict(&seed);
3640 if (res.getNumDbNodes() < 2)
3641 return NDBT_OK;
3642
3643 if (res.init(ctx, step))
3644 return NDBT_FAILED;
3645
3646 for (int i = 0; i<loops; i++)
3647 {
3648 for (Uint32 j = 0; j<10; j++)
3649 if (dict.schema_op(pNdb))
3650 return NDBT_FAILED;
3651
3652 if (res.dostep(ctx, step))
3653 return NDBT_FAILED;
3654
3655 if (dict.validate(pNdb))
3656 return NDBT_FAILED;
3657 }
3658
3659 if (res.finish(ctx, step))
3660 return NDBT_FAILED;
3661
3662 if (dict.validate(pNdb))
3663 return NDBT_FAILED;
3664
3665 if (dict.cleanup(pNdb))
3666 return NDBT_FAILED;
3667
3668 return NDBT_OK;
3669 }
3670
3671 int
runBug29501(NDBT_Context * ctx,NDBT_Step * step)3672 runBug29501(NDBT_Context* ctx, NDBT_Step* step) {
3673 NdbRestarter res;
3674 NdbDictionary::LogfileGroup lg;
3675 lg.setName("DEFAULT-LG");
3676 lg.setUndoBufferSize(8*1024*1024);
3677
3678 if (res.getNumDbNodes() < 2)
3679 return NDBT_OK;
3680
3681 Ndb* pNdb = GETNDB(step);
3682 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3683
3684 int node = res.getRandomNotMasterNodeId(rand());
3685 res.restartOneDbNode(node, true, true, false);
3686
3687 if(pDict->createLogfileGroup(lg) != 0){
3688 g_err << "Failed to create logfilegroup:"
3689 << endl << pDict->getNdbError() << endl;
3690 return NDBT_FAILED;
3691 }
3692
3693 NdbDictionary::Undofile uf;
3694 uf.setPath("undofile01.dat");
3695 uf.setSize(5*1024*1024);
3696 uf.setLogfileGroup("DEFAULT-LG");
3697
3698 if(pDict->createUndofile(uf) != 0){
3699 g_err << "Failed to create undofile:"
3700 << endl << pDict->getNdbError() << endl;
3701 return NDBT_FAILED;
3702 }
3703
3704 res.waitNodesNoStart(&node, 1);
3705 res.startNodes(&node, 1);
3706
3707 if (res.waitClusterStarted()){
3708 g_err << "Node restart failed"
3709 << endl << pDict->getNdbError() << endl;
3710 return NDBT_FAILED;
3711 }
3712
3713 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lg.getName())) != 0){
3714 g_err << "Drop of LFG Failed"
3715 << endl << pDict->getNdbError() << endl;
3716 return NDBT_FAILED;
3717 }
3718
3719 return NDBT_OK;
3720 }
3721
3722 int
runDropDDObjects(NDBT_Context * ctx,NDBT_Step * step)3723 runDropDDObjects(NDBT_Context* ctx, NDBT_Step* step){
3724 //Purpose is to drop all tables, data files, Table spaces and LFG's
3725 Uint32 i = 0;
3726
3727 Ndb* pNdb = GETNDB(step);
3728 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3729
3730 NdbDictionary::Dictionary::List list;
3731 if (pDict->listObjects(list) == -1)
3732 return NDBT_FAILED;
3733
3734 //Search the list and drop all tables found
3735 const char * tableFound = 0;
3736 for (i = 0; i < list.count; i++){
3737 switch(list.elements[i].type){
3738 case NdbDictionary::Object::UserTable:
3739 tableFound = list.elements[i].name;
3740 if(tableFound != 0){
3741 if(strcmp(list.elements[i].database, "TEST_DB") == 0 &&
3742 !is_prefix(tableFound, "NDB$BLOB"))
3743 {
3744 if(pDict->dropTable(tableFound) != 0){
3745 g_err << "Failed to drop table: " << tableFound << pDict->getNdbError() << endl;
3746 return NDBT_FAILED;
3747 }
3748 }
3749 }
3750 tableFound = 0;
3751 break;
3752 default:
3753 break;
3754 }
3755 }
3756
3757 //Search the list and drop all data file found
3758 const char * dfFound = 0;
3759 for (i = 0; i < list.count; i++){
3760 switch(list.elements[i].type){
3761 case NdbDictionary::Object::Datafile:
3762 dfFound = list.elements[i].name;
3763 if(dfFound != 0){
3764 if(pDict->dropDatafile(pDict->getDatafile(0, dfFound)) != 0){
3765 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
3766 return NDBT_FAILED;
3767 }
3768 }
3769 dfFound = 0;
3770 break;
3771 default:
3772 break;
3773 }
3774 }
3775
3776 //Search the list and drop all Table Spaces Found
3777 const char * tsFound = 0;
3778 for (i = 0; i <list.count; i++){
3779 switch(list.elements[i].type){
3780 case NdbDictionary::Object::Tablespace:
3781 tsFound = list.elements[i].name;
3782 if(tsFound != 0){
3783 if(pDict->dropTablespace(pDict->getTablespace(tsFound)) != 0){
3784 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3785 return NDBT_FAILED;
3786 }
3787 }
3788 tsFound = 0;
3789 break;
3790 default:
3791 break;
3792 }
3793 }
3794
3795 //Search the list and drop all LFG Found
3796 //Currently only 1 LGF is supported, but written for future
3797 //when more then one is supported.
3798 const char * lgFound = 0;
3799 for (i = 0; i < list.count; i++){
3800 switch(list.elements[i].type){
3801 case NdbDictionary::Object::LogfileGroup:
3802 lgFound = list.elements[i].name;
3803 if(lgFound != 0){
3804 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgFound)) != 0){
3805 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3806 return NDBT_FAILED;
3807 }
3808 }
3809 lgFound = 0;
3810 break;
3811 default:
3812 break;
3813 }
3814 }
3815
3816 return NDBT_OK;
3817 }
3818
3819 int
runWaitStarted(NDBT_Context * ctx,NDBT_Step * step)3820 runWaitStarted(NDBT_Context* ctx, NDBT_Step* step){
3821
3822 NdbRestarter restarter;
3823 restarter.waitClusterStarted(300);
3824
3825 NdbSleep_SecSleep(3);
3826 return NDBT_OK;
3827 }
3828
3829 int
testDropDDObjectsSetup(NDBT_Context * ctx,NDBT_Step * step)3830 testDropDDObjectsSetup(NDBT_Context* ctx, NDBT_Step* step){
3831 //Purpose is to setup to test DropDDObjects
3832 char tsname[256];
3833 char dfname[256];
3834
3835 Ndb* pNdb = GETNDB(step);
3836 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3837
3838 NdbDictionary::LogfileGroup lg;
3839 lg.setName("DEFAULT-LG");
3840 lg.setUndoBufferSize(8*1024*1024);
3841
3842
3843 if(pDict->createLogfileGroup(lg) != 0){
3844 g_err << "Failed to create logfilegroup:"
3845 << endl << pDict->getNdbError() << endl;
3846 return NDBT_FAILED;
3847 }
3848
3849 NdbDictionary::Undofile uf;
3850 uf.setPath("undofile01.dat");
3851 uf.setSize(5*1024*1024);
3852 uf.setLogfileGroup("DEFAULT-LG");
3853
3854 if(pDict->createUndofile(uf) != 0){
3855 g_err << "Failed to create undofile:"
3856 << endl << pDict->getNdbError() << endl;
3857 return NDBT_FAILED;
3858 }
3859
3860 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
3861 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u.dat", tsname, rand());
3862
3863 if (create_tablespace(pDict, lg.getName(), tsname, dfname)){
3864 g_err << "Failed to create undofile:"
3865 << endl << pDict->getNdbError() << endl;
3866 return NDBT_FAILED;
3867 }
3868
3869 return NDBT_OK;
3870 }
3871
3872 int
runBug36072(NDBT_Context * ctx,NDBT_Step * step)3873 runBug36072(NDBT_Context* ctx, NDBT_Step* step)
3874 {
3875 Ndb* pNdb = GETNDB(step);
3876 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3877 NdbRestarter res;
3878
3879 int err[] = { 6016,
3880 #if BUG_46856
3881 6017,
3882 #endif
3883 0 };
3884 for (Uint32 i = 0; err[i] != 0; i++)
3885 {
3886 int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
3887
3888 if (res.dumpStateAllNodes(val2, 2))
3889 return NDBT_FAILED;
3890
3891 if (res.insertErrorInAllNodes(932)) // arbit
3892 return NDBT_FAILED;
3893
3894 int code = err[i];
3895
3896 if (code == 6016)
3897 {
3898 if (res.insertErrorInAllNodes(code))
3899 return NDBT_FAILED;
3900 }
3901
3902 NdbDictionary::LogfileGroup lg;
3903 lg.setName("DEFAULT-LG");
3904 lg.setUndoBufferSize(8*1024*1024);
3905
3906 NdbDictionary::Undofile uf;
3907 uf.setPath("undofile01.dat");
3908 uf.setSize(5*1024*1024);
3909 uf.setLogfileGroup("DEFAULT-LG");
3910
3911 int r = pDict->createLogfileGroup(lg);
3912 if (code == 6017)
3913 {
3914 if (r)
3915 {
3916 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3917 return NDBT_FAILED;
3918 }
3919
3920 if (res.insertErrorInAllNodes(err[i]))
3921 return NDBT_FAILED;
3922
3923 pDict->createUndofile(uf);
3924 }
3925
3926 if (res.waitClusterNoStart())
3927 return NDBT_FAILED;
3928
3929 res.startAll();
3930 if (res.waitClusterStarted())
3931 return NDBT_FAILED;
3932
3933 if (code == 6016)
3934 {
3935 NdbDictionary::LogfileGroup lg2 = pDict->getLogfileGroup("DEFAULT-LG");
3936 NdbError err= pDict->getNdbError();
3937 if( (int) err.classification == (int) ndberror_cl_none)
3938 {
3939 ndbout << __LINE__ << endl;
3940 return NDBT_FAILED;
3941 }
3942
3943 if (pDict->createLogfileGroup(lg) != 0)
3944 {
3945 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3946 return NDBT_FAILED;
3947 }
3948 }
3949 else
3950 {
3951 NdbDictionary::Undofile uf2 = pDict->getUndofile(0, "undofile01.dat");
3952 NdbError err= pDict->getNdbError();
3953 if( (int) err.classification == (int) ndberror_cl_none)
3954 {
3955 ndbout << __LINE__ << endl;
3956 return NDBT_FAILED;
3957 }
3958
3959 if (pDict->createUndofile(uf) != 0)
3960 {
3961 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3962 return NDBT_FAILED;
3963 }
3964 }
3965
3966 {
3967 NdbDictionary::LogfileGroup lg2 = pDict->getLogfileGroup("DEFAULT-LG");
3968 NdbError err= pDict->getNdbError();
3969 if( (int) err.classification != (int) ndberror_cl_none)
3970 {
3971 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3972 return NDBT_FAILED;
3973 }
3974
3975 if (pDict->dropLogfileGroup(lg2))
3976 {
3977 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
3978 return NDBT_FAILED;
3979 }
3980 }
3981 }
3982
3983 return NDBT_OK;
3984 }
3985
3986 int
restartClusterInitial(NDBT_Context * ctx,NDBT_Step * step)3987 restartClusterInitial(NDBT_Context* ctx, NDBT_Step* step)
3988 {
3989 NdbRestarter res;
3990
3991 res.restartAll2(NdbRestarter::NRRF_INITIAL |
3992 NdbRestarter::NRRF_NOSTART |
3993 NdbRestarter::NRRF_ABORT);
3994 if (res.waitClusterNoStart())
3995 return NDBT_FAILED;
3996
3997 res.startAll();
3998 if (res.waitClusterStarted())
3999 return NDBT_FAILED;
4000
4001 return NDBT_OK;
4002 }
4003
4004
4005 int
DropDDObjectsVerify(NDBT_Context * ctx,NDBT_Step * step)4006 DropDDObjectsVerify(NDBT_Context* ctx, NDBT_Step* step){
4007 //Purpose is to verify test DropDDObjects worked
4008 Uint32 i = 0;
4009
4010 Ndb* pNdb = GETNDB(step);
4011 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
4012
4013 NdbDictionary::Dictionary::List list;
4014 if (pDict->listObjects(list) == -1)
4015 return NDBT_FAILED;
4016
4017 bool ddFound = false;
4018 for (i = 0; i <list.count; i++){
4019 switch(list.elements[i].type){
4020 case NdbDictionary::Object::Tablespace:
4021 ddFound = true;
4022 break;
4023 case NdbDictionary::Object::LogfileGroup:
4024 ddFound = true;
4025 break;
4026 default:
4027 break;
4028 }
4029 if(ddFound == true){
4030 g_err << "DropDDObjects Failed: DD found:"
4031 << endl;
4032 return NDBT_FAILED;
4033 }
4034 }
4035 return NDBT_OK;
4036 }
4037
4038 // Bug48604
4039
4040 // string messages between local/remote steps identified by stepNo-1
4041 // each Msg<loc><rem> waits for Ack<loc><rem>
4042
4043 static const uint MaxMsg = 100;
4044
4045 static bool
send_msg(NDBT_Context * ctx,int loc,int rem,const char * msg)4046 send_msg(NDBT_Context* ctx, int loc, int rem, const char* msg)
4047 {
4048 char msgName[20], ackName[20];
4049 sprintf(msgName, "Msg%d%d", loc, rem);
4050 sprintf(ackName, "Ack%d%d", loc, rem);
4051 g_info << loc << ": send to:" << rem << " msg:" << msg << endl;
4052 ctx->setProperty(msgName, msg);
4053 int cnt = 0;
4054 while (1)
4055 {
4056 if (ctx->isTestStopped())
4057 return false;
4058 int ret;
4059 if ((ret = ctx->getProperty(ackName, (Uint32)0)) != 0)
4060 break;
4061 if (++cnt % 100 == 0)
4062 g_info << loc << ": send to:" << rem << " wait for ack" << endl;
4063 NdbSleep_MilliSleep(10);
4064 }
4065 ctx->setProperty(ackName, (Uint32)0);
4066 return true;
4067 }
4068
4069 static bool
poll_msg(NDBT_Context * ctx,int loc,int rem,char * msg)4070 poll_msg(NDBT_Context* ctx, int loc, int rem, char* msg)
4071 {
4072 char msgName[20], ackName[20];
4073 sprintf(msgName, "Msg%d%d", rem, loc);
4074 sprintf(ackName, "Ack%d%d", rem, loc);
4075 const char* ptr;
4076 if ((ptr = ctx->getProperty(msgName, (char*)0)) != 0 && ptr[0] != 0)
4077 {
4078 require(strlen(ptr) < MaxMsg);
4079 memset(msg, 0, MaxMsg);
4080 strcpy(msg, ptr);
4081 g_info << loc << ": recv from:" << rem << " msg:" << msg << endl;
4082 ctx->setProperty(msgName, "");
4083 ctx->setProperty(ackName, (Uint32)1);
4084 return true;
4085 }
4086 return false;
4087 }
4088
4089 static int
recv_msg(NDBT_Context * ctx,int loc,int rem,char * msg)4090 recv_msg(NDBT_Context* ctx, int loc, int rem, char* msg)
4091 {
4092 uint cnt = 0;
4093 while (1)
4094 {
4095 if (ctx->isTestStopped())
4096 return false;
4097 if (poll_msg(ctx, loc, rem, msg))
4098 break;
4099 if (++cnt % 100 == 0)
4100 g_info << loc << ": recv from:" << rem << " wait for msg" << endl;
4101 NdbSleep_MilliSleep(10);
4102 }
4103 return true;
4104 }
4105
4106 const char* tabName_Bug48604 = "TBug48604";
4107 const char* indName_Bug48604 = "TBug48604X1";
4108
4109 static const NdbDictionary::Table*
runBug48604createtable(NDBT_Context * ctx,NDBT_Step * step)4110 runBug48604createtable(NDBT_Context* ctx, NDBT_Step* step)
4111 {
4112 Ndb* pNdb = GETNDB(step);
4113 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4114 const NdbDictionary::Table* pTab = 0;
4115 int result = NDBT_OK;
4116 do
4117 {
4118 NdbDictionary::Table tab(tabName_Bug48604);
4119 {
4120 NdbDictionary::Column col("a");
4121 col.setType(NdbDictionary::Column::Unsigned);
4122 col.setPrimaryKey(true);
4123 tab.addColumn(col);
4124 }
4125 {
4126 NdbDictionary::Column col("b");
4127 col.setType(NdbDictionary::Column::Unsigned);
4128 col.setNullable(false);
4129 tab.addColumn(col);
4130 }
4131 CHECK(pDic->createTable(tab) == 0);
4132 CHECK((pTab = pDic->getTable(tabName_Bug48604)) != 0);
4133 }
4134 while (0);
4135 return pTab;
4136 }
4137
4138 static const NdbDictionary::Index*
runBug48604createindex(NDBT_Context * ctx,NDBT_Step * step)4139 runBug48604createindex(NDBT_Context* ctx, NDBT_Step* step)
4140 {
4141 Ndb* pNdb = GETNDB(step);
4142 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4143 const NdbDictionary::Index* pInd = 0;
4144 int result = NDBT_OK;
4145 do {
4146 NdbDictionary::Index ind(indName_Bug48604);
4147 ind.setTable(tabName_Bug48604);
4148 ind.setType(NdbDictionary::Index::OrderedIndex);
4149 ind.setLogging(false);
4150 ind.addColumn("b");
4151 g_info << "index create.." << endl;
4152 CHECK(pDic->createIndex(ind) == 0);
4153 CHECK((pInd = pDic->getIndex(indName_Bug48604, tabName_Bug48604)) != 0);
4154 g_info << "index created" << endl;
4155 return pInd;
4156 }
4157 while (0);
4158 return pInd;
4159 }
4160
4161 int
runBug48604(NDBT_Context * ctx,NDBT_Step * step)4162 runBug48604(NDBT_Context* ctx, NDBT_Step* step)
4163 {
4164 Ndb* pNdb = GETNDB(step);
4165 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4166 const NdbDictionary::Table* pTab = 0;
4167 const NdbDictionary::Index* pInd = 0;
4168 (void)pDic->dropTable(tabName_Bug48604);
4169 int loc = step->getStepNo() - 1;
4170 require(loc == 0);
4171 g_err << "main" << endl;
4172 int result = NDBT_OK;
4173 int loops = ctx->getNumLoops();
4174 char msg[MaxMsg];
4175
4176 do
4177 {
4178 CHECK((pTab = runBug48604createtable(ctx, step)) != 0);
4179 CHECK(send_msg(ctx, 0, 1, "s"));
4180
4181 int loop = 0;
4182 while (result == NDBT_OK && loop++ < loops)
4183 {
4184 g_err << "loop:" << loop << endl;
4185 {
4186 // create index fully while uncommitted ops wait
4187 const char* ops[][3] =
4188 {
4189 { "ozin", "oc", "oa" }, // 0: before 1-2: after
4190 { "oziun", "oc", "oa" },
4191 { "ozidn", "oc", "oa" },
4192 { "ozicun", "oc", "oa" },
4193 { "ozicuuun", "oc", "oa" },
4194 { "ozicdn", "oc", "oa" },
4195 { "ozicdin", "oc", "oa" },
4196 { "ozicdidiuuudidn", "oc", "oa" },
4197 { "ozicdidiuuudidin", "oc", "oa" }
4198 };
4199 const int cnt = sizeof(ops)/sizeof(ops[0]);
4200 int i;
4201 for (i = 0; result == NDBT_OK && i < cnt; i++)
4202 {
4203 int j;
4204 for (j = 1; result == NDBT_OK && j <= 2; j++)
4205 {
4206 if (ops[i][j] == 0)
4207 continue;
4208 CHECK(send_msg(ctx, 0, 1, ops[i][0]));
4209 CHECK(recv_msg(ctx, 0, 1, msg) && msg[0] == 'o');
4210 CHECK((pInd = runBug48604createindex(ctx, step)) != 0);
4211 CHECK(send_msg(ctx, 0, 1, ops[i][j]));
4212 CHECK(recv_msg(ctx, 0, 1, msg) && msg[0] == 'o');
4213
4214 CHECK(pDic->dropIndex(indName_Bug48604, tabName_Bug48604) == 0);
4215 g_info << "index dropped" << endl;
4216 }
4217 }
4218 }
4219 }
4220 }
4221 while (0);
4222
4223 (void)send_msg(ctx, 0, 1, "x");
4224 ctx->stopTest();
4225 g_err << "main: exit:" << result << endl;
4226 return result;
4227 }
4228
4229 int
runBug48604ops(NDBT_Context * ctx,NDBT_Step * step)4230 runBug48604ops(NDBT_Context* ctx, NDBT_Step* step)
4231 {
4232 Ndb* pNdb = GETNDB(step);
4233 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4234 const NdbDictionary::Table* pTab = 0;
4235 //const NdbDictionary::Index* pInd = 0;
4236 int loc = step->getStepNo() - 1;
4237 require(loc > 0);
4238 g_err << "ops: loc:" << loc << endl;
4239 int result = NDBT_OK;
4240 int records = ctx->getNumRecords();
4241 char msg[MaxMsg];
4242
4243 do
4244 {
4245 CHECK(recv_msg(ctx, loc, 0, msg));
4246 require(msg[0] == 's');
4247 CHECK((pTab = pDic->getTable(tabName_Bug48604)) != 0);
4248 HugoOperations ops(*pTab);
4249 bool have_trans = false;
4250 int opseq = 0;
4251
4252 while (result == NDBT_OK && !ctx->isTestStopped())
4253 {
4254 CHECK(recv_msg(ctx, loc, 0, msg));
4255 if (msg[0] == 'x')
4256 break;
4257 if (msg[0] == 'o')
4258 {
4259 char* p = &msg[1];
4260 int c;
4261 while (result == NDBT_OK && (c = *p++) != 0)
4262 {
4263 if (c == 'n')
4264 {
4265 require(have_trans);
4266 CHECK(ops.execute_NoCommit(pNdb) == 0);
4267 g_info << loc << ": not committed" << endl;
4268 continue;
4269 }
4270 if (c == 'c')
4271 {
4272 require(have_trans);
4273 CHECK(ops.execute_Commit(pNdb) == 0);
4274 ops.closeTransaction(pNdb);
4275 have_trans = false;
4276 g_info << loc << ": committed" << endl;
4277 continue;
4278 }
4279 if (c == 'a')
4280 {
4281 require(have_trans);
4282 CHECK(ops.execute_Rollback(pNdb) == 0);
4283 ops.closeTransaction(pNdb);
4284 have_trans = false;
4285 g_info << loc << ": aborted" << endl;
4286 continue;
4287 }
4288 if (c == 'i' || c == 'u' || c == 'd')
4289 {
4290 if (!have_trans)
4291 {
4292 CHECK(ops.startTransaction(pNdb) == 0);
4293 have_trans = true;
4294 g_info << loc << ": trans started" << endl;
4295 }
4296 int i;
4297 for (i = 0; result == NDBT_OK && i < records; i++)
4298 {
4299 if (c == 'i')
4300 CHECK(ops.pkInsertRecord(pNdb, i, 1, opseq) == 0);
4301 if (c == 'u')
4302 CHECK(ops.pkUpdateRecord(pNdb, i, 1, opseq) == 0);
4303 if (c == 'd')
4304 CHECK(ops.pkDeleteRecord(pNdb, i, 1) == 0);
4305 }
4306 char op_str[2];
4307 sprintf(op_str, "%c", c);
4308 g_info << loc << ": op:" << op_str << " records:" << records << endl;
4309 opseq++;
4310 continue;
4311 }
4312 if (c == 'z')
4313 {
4314 CHECK(ops.clearTable(pNdb) == 0);
4315 continue;
4316 }
4317 require(false);
4318 }
4319 CHECK(send_msg(ctx, loc, 0, "o"));
4320 continue;
4321 }
4322 require(false);
4323 }
4324 } while (0);
4325
4326 g_err << "ops: loc:" << loc << " exit:" << result << endl;
4327 if (result != NDBT_OK)
4328 ctx->stopTest();
4329 return result;
4330 }
4331
4332 int
runBug54651(NDBT_Context * ctx,NDBT_Step * step)4333 runBug54651(NDBT_Context* ctx, NDBT_Step* step)
4334 {
4335 Ndb* pNdb = GETNDB(step);
4336 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4337
4338 for (Uint32 j = 0; j< 2; j++)
4339 {
4340 pDic->createTable(* ctx->getTab());
4341
4342 const NdbDictionary::Table * pTab =pDic->getTable(ctx->getTab()->getName());
4343 NdbDictionary::Table copy = * pTab;
4344 BaseString name;
4345 name.assfmt("%s_1", pTab->getName());
4346 copy.setName(name.c_str());
4347
4348 if (pDic->createTable(copy))
4349 {
4350 ndbout_c("Failed to create table...");
4351 ndbout << pDic->getNdbError() << endl;
4352 return NDBT_FAILED;
4353 }
4354
4355 NdbDictionary::Table alter = * pTab;
4356 alter.setName(name.c_str());
4357 for (Uint32 i = 0; i<2; i++)
4358 {
4359 // now rename org table to same name...
4360 if (pDic->alterTable(* pTab, alter) == 0)
4361 {
4362 ndbout << "Alter with duplicate name succeeded!!" << endl;
4363 return NDBT_FAILED;
4364 }
4365
4366 ndbout << "Alter with duplicate name failed...good" << endl
4367 << pDic->getNdbError() << endl;
4368 }
4369
4370 pDic->dropTable(copy.getName());
4371 pDic->dropTable(ctx->getTab()->getName());
4372 }
4373 return NDBT_OK;
4374 }
4375
4376 /** telco-6.4 **/
4377
4378 // begin schema trans
4379
4380 #undef chk1
4381 #undef chk2
4382
4383 static bool st_core_on_err = false;
4384
4385 #define chk1(x) \
4386 do { \
4387 if (x) break; \
4388 g_err << "FAIL " << __LINE__ << " " << #x << endl; \
4389 if (st_core_on_err) abort(); \
4390 goto err; \
4391 } while (0)
4392
4393 #define chk2(x, e) \
4394 do { \
4395 if (x) break; \
4396 g_err << "FAIL " << __LINE__ << " " << #x << ": " << e << endl; \
4397 if (st_core_on_err) abort(); \
4398 goto err; \
4399 } while (0)
4400
4401 static uint
urandom(uint m)4402 urandom(uint m)
4403 {
4404 require(m != 0);
4405 uint n = (uint)ndb_rand();
4406 return n % m;
4407 }
4408
4409 static bool
randomly(uint k,uint m)4410 randomly(uint k, uint m)
4411 {
4412 uint n = urandom(m);
4413 return n < k;
4414 }
4415
4416 // structs
4417
4418 struct ST_Obj;
4419 template class Vector<ST_Obj*>;
4420 typedef Vector<ST_Obj*> ST_Objlist;
4421
4422 static ST_Objlist st_objlist;
4423 #ifndef NDEBUG
4424 static const ST_Obj* st_find_obj(const char* db, const char* name);
4425 #endif
4426
4427 #define ST_MAX_NAME_SIZE (MAX_TAB_NAME_SIZE + 100)
4428
4429 struct ST_Obj {
4430 NdbDictionary::Object::Type type;
4431 char dbname[ST_MAX_NAME_SIZE];
4432 char name[ST_MAX_NAME_SIZE];
4433 int id;
4434 enum { Skip = 0xFFFF }; // mark ignored objects in List
4435 bool create; // true/false = create/drop prepared or committed
4436 bool commit;
existsST_Obj4437 bool exists() const { // visible to trans
4438 return !(!create && commit);
4439 }
is_triggerST_Obj4440 virtual bool is_trigger() const {
4441 return false;
4442 }
is_indexST_Obj4443 virtual bool is_index() const {
4444 return false;
4445 }
is_tableST_Obj4446 virtual bool is_table() const {
4447 return false;
4448 }
realnameST_Obj4449 virtual const char* realname() const {
4450 return name;
4451 }
ST_ObjST_Obj4452 ST_Obj(const char* a_dbname, const char* a_name) {
4453 type = NdbDictionary::Object::TypeUndefined;
4454 strcpy(dbname, a_dbname);
4455 strcpy(name, a_name);
4456 id = -1;
4457 create = false; // init as dropped
4458 commit = true;
4459 assert(st_find_obj(dbname, name) == 0);
4460 st_objlist.push_back(this);
4461 }
~ST_ObjST_Obj4462 virtual ~ST_Obj() {}
4463 };
4464
4465 static NdbOut&
operator <<(NdbOut & out,const ST_Obj & obj)4466 operator<<(NdbOut& out, const ST_Obj& obj)
4467 {
4468 out << obj.name << "[" << obj.id << "]";
4469 return out;
4470 }
4471
4472 struct ST_Trg : public ST_Obj {
4473 struct ST_Ind* ind;
4474 TriggerEvent::Value event;
4475 mutable char realname_buf[ST_MAX_NAME_SIZE];
is_triggerST_Trg4476 virtual bool is_trigger() const {
4477 return true;
4478 }
4479 virtual const char* realname() const;
ST_TrgST_Trg4480 ST_Trg(const char* a_db, const char* a_name) :
4481 ST_Obj(a_db, a_name) {
4482 ind = 0;
4483 }
~ST_TrgST_Trg4484 virtual ~ST_Trg() {};
4485 };
4486
4487 template class Vector<ST_Trg*>;
4488 typedef Vector<ST_Trg*> ST_Trglist;
4489
4490 struct ST_Ind : public ST_Obj {
4491 struct ST_Tab* tab;
4492 const NdbDictionary::Index* ind;
4493 const NdbDictionary::Index* ind_r; // retrieved
4494 BaseString colnames;
4495 ST_Trglist* trglist;
4496 int trgcount;
is_indexST_Ind4497 virtual bool is_index() const {
4498 return true;
4499 }
is_uniqueST_Ind4500 bool is_unique() const {
4501 return type == NdbDictionary::Object::UniqueHashIndex;
4502 }
trgST_Ind4503 const ST_Trg& trg(int k) const {
4504 return *((*trglist)[k]);
4505 }
trgST_Ind4506 ST_Trg& trg(int k) {
4507 return *((*trglist)[k]);
4508 }
ST_IndST_Ind4509 ST_Ind(const char* a_db, const char* a_name) :
4510 ST_Obj(a_db, a_name) {
4511 tab = 0;
4512 ind = 0;
4513 ind_r = 0;
4514 trglist = new ST_Trglist;
4515 trgcount = 0;
4516 };
~ST_IndST_Ind4517 virtual ~ST_Ind() {
4518 delete ind;
4519 delete trglist;
4520 ind = 0;
4521 trglist = 0;
4522 }
4523 };
4524
4525 const char*
realname() const4526 ST_Trg::realname() const
4527 {
4528 if (!exists())
4529 return name;
4530 const char* p = name;
4531 const char* q = strchr(p, '<');
4532 const char* r = strchr(p, '>');
4533 require(q != 0 && r != 0 && q < r);
4534 require(ind->id != -1);
4535 sprintf(realname_buf, "%.*s%d%s", (int)(q - p), p, ind->id, r + 1);
4536 return realname_buf;
4537 }
4538
4539 template class Vector<ST_Ind*>;
4540 typedef Vector<ST_Ind*> ST_Indlist;
4541
4542 struct ST_Tab : public ST_Obj {
4543 const NdbDictionary::Table* tab;
4544 const NdbDictionary::Table* tab_r; // retrieved
4545 ST_Indlist* indlist;
4546 int indcount;
4547 int induniquecount;
4548 int indorderedcount;
is_tableST_Tab4549 virtual bool is_table() const {
4550 return true;
4551 }
indST_Tab4552 const ST_Ind& ind(int j) const {
4553 return *((*indlist)[j]);
4554 }
indST_Tab4555 ST_Ind& ind(int j) {
4556 return *((*indlist)[j]);
4557 }
ST_TabST_Tab4558 ST_Tab(const char* a_db, const char* a_name) :
4559 ST_Obj(a_db, a_name) {
4560 tab = 0;
4561 tab_r = 0;
4562 indlist = new ST_Indlist;
4563 indcount = 0;
4564 induniquecount = 0;
4565 indorderedcount = 0;
4566 }
~ST_TabST_Tab4567 virtual ~ST_Tab() {
4568 delete tab;
4569 delete indlist;
4570 tab = 0;
4571 indlist = 0;
4572 }
4573 };
4574
4575 template class Vector<ST_Tab*>;
4576 typedef Vector<ST_Tab*> ST_Tablist;
4577
4578 struct ST_Restarter : public NdbRestarter {
4579 int get_status();
4580 const ndb_mgm_node_state& get_state(int node_id);
ST_RestarterST_Restarter4581 ST_Restarter() {
4582 int i;
4583 for (i = 0; i < MAX_NODES; i++)
4584 state[i].node_type = NDB_MGM_NODE_TYPE_UNKNOWN;
4585 first_time = true;
4586 }
4587 protected:
4588 void set_state(const ndb_mgm_node_state& state);
4589 ndb_mgm_node_state state[MAX_NODES];
4590 bool first_time;
4591 };
4592
4593 const ndb_mgm_node_state&
get_state(int node_id)4594 ST_Restarter::get_state(int node_id) {
4595 require(node_id > 0 && node_id < MAX_NODES);
4596 require(!first_time);
4597 return state[node_id];
4598 }
4599
4600 void
set_state(const ndb_mgm_node_state & new_state)4601 ST_Restarter::set_state(const ndb_mgm_node_state& new_state)
4602 {
4603 int node_id = new_state.node_id;
4604 require(1 <= node_id && node_id < MAX_NODES);
4605
4606 require(new_state.node_type == NDB_MGM_NODE_TYPE_MGM ||
4607 new_state.node_type == NDB_MGM_NODE_TYPE_NDB ||
4608 new_state.node_type == NDB_MGM_NODE_TYPE_API);
4609
4610 ndb_mgm_node_state& old_state = state[node_id];
4611 if (!first_time)
4612 require(old_state.node_type == new_state.node_type);
4613 old_state = new_state;
4614 }
4615
4616 int
get_status()4617 ST_Restarter::get_status()
4618 {
4619 if (getStatus() == -1)
4620 return -1;
4621 int i;
4622 for (i = 0; i < (int)mgmNodes.size(); i++)
4623 set_state(mgmNodes[i]);
4624 for (i = 0; i < (int)ndbNodes.size(); i++)
4625 set_state(ndbNodes[i]);
4626 for (i = 0; i < (int)apiNodes.size(); i++)
4627 set_state(apiNodes[i]);
4628 first_time = false;
4629 return 0;
4630 }
4631
4632 struct ST_Con {
4633 Ndb_cluster_connection* ncc;
4634 Ndb* ndb;
4635 NdbDictionary::Dictionary* dic;
4636 ST_Restarter* restarter;
4637 int numdbnodes;
4638 char dbname[ST_MAX_NAME_SIZE];
4639 ST_Tablist* tablist;
4640 int tabcount;
4641 bool tx_on;
4642 bool tx_commit;
4643 bool is_xcon;
4644 ST_Con* xcon;
4645 int node_id;
4646 int loop;
tabST_Con4647 const ST_Tab& tab(int i) const {
4648 return *((*tablist)[i]);
4649 }
tabST_Con4650 ST_Tab& tab(int i) {
4651 return *((*tablist)[i]);
4652 }
ST_ConST_Con4653 ST_Con(Ndb_cluster_connection* a_ncc,
4654 Ndb* a_ndb,
4655 ST_Restarter* a_restarter) {
4656 ncc = a_ncc;
4657 ndb = a_ndb;
4658 dic = a_ndb->getDictionary();
4659 restarter = a_restarter;
4660 numdbnodes = restarter->getNumDbNodes();
4661 require(numdbnodes >= 1);
4662 sprintf(dbname, "%s", ndb->getDatabaseName());
4663 tablist = new ST_Tablist;
4664 tabcount = 0;
4665 tx_on = false;
4666 tx_commit = false;
4667 is_xcon = false;
4668 xcon = 0;
4669 node_id = ncc->node_id();
4670 {
4671 require(restarter->get_status() == 0);
4672 const ndb_mgm_node_state& state = restarter->get_state(node_id);
4673 require(state.node_type == NDB_MGM_NODE_TYPE_API);
4674 require(state.version != 0); // means "connected"
4675 g_info << "node_id:" << node_id << endl;
4676 }
4677 loop = -1;
4678 }
~ST_ConST_Con4679 ~ST_Con() {
4680 if (!is_xcon) {
4681 delete tablist;
4682 } else {
4683 delete ndb;
4684 delete ncc;
4685 }
4686 tablist = 0;
4687 ndb = 0;
4688 ncc = 0;
4689 }
4690 };
4691
4692 // initialization
4693
4694 static int
st_drop_all_tables(ST_Con & c)4695 st_drop_all_tables(ST_Con& c)
4696 {
4697 g_info << "st_drop_all_tables" << endl;
4698 NdbDictionary::Dictionary::List list;
4699 chk2(c.dic->listObjects(list) == 0, c.dic->getNdbError());
4700 int n;
4701 for (n = 0; n < (int)list.count; n++) {
4702 const NdbDictionary::Dictionary::List::Element& element =
4703 list.elements[n];
4704 if (element.type == NdbDictionary::Object::UserTable &&
4705 strcmp(element.database, "TEST_DB") == 0) {
4706 chk2(c.dic->dropTable(element.name) == 0, c.dic->getNdbError());
4707 }
4708 }
4709 return 0;
4710 err:
4711 return -1;
4712 }
4713
4714 static void
st_init_objects(ST_Con & c,NDBT_Context * ctx)4715 st_init_objects(ST_Con& c, NDBT_Context* ctx)
4716 {
4717 int numTables = ctx->getNumTables();
4718 c.tabcount = 0;
4719 int i;
4720 for (i = 0; i < numTables; i++) {
4721 const NdbDictionary::Table* pTab = 0;
4722 #if ndb_test_ALL_TABLES_is_fixed
4723 const NdbDictionary::Table** tables = ctx->getTables();
4724 pTab = tables[i];
4725 #else
4726 const Vector<BaseString>& tables = ctx->getSuite()->m_tables_in_test;
4727 pTab = NDBT_Tables::getTable(tables[i].c_str());
4728 #endif
4729 require(pTab != 0 && pTab->getName() != 0);
4730
4731 {
4732 bool ok = true;
4733 int n;
4734 for (n = 0; n < pTab->getNoOfColumns(); n++) {
4735 const NdbDictionary::Column* pCol = pTab->getColumn(n);
4736 require(pCol != 0);
4737 if (pCol->getStorageType() !=
4738 NdbDictionary::Column::StorageTypeMemory) {
4739 g_err << pTab->getName() << ": skip non-mem table for now" << endl;
4740 ok = false;
4741 break;
4742 }
4743 }
4744 if (!ok)
4745 continue;
4746 }
4747
4748 c.tablist->push_back(new ST_Tab(c.dbname, pTab->getName()));
4749 c.tabcount++;
4750 ST_Tab& tab = *c.tablist->back();
4751 tab.type = NdbDictionary::Object::UserTable;
4752 tab.tab = new NdbDictionary::Table(*pTab);
4753
4754 const char** indspec = NDBT_Tables::getIndexes(tab.name);
4755
4756 while (indspec != 0 && *indspec != 0) {
4757 char ind_name[ST_MAX_NAME_SIZE];
4758 sprintf(ind_name, "%sX%d", tab.name, tab.indcount);
4759 tab.indlist->push_back(new ST_Ind("sys", ind_name));
4760 ST_Ind& ind = *tab.indlist->back();
4761 ind.tab = &tab;
4762
4763 NdbDictionary::Index* pInd = new NdbDictionary::Index(ind.name);
4764 pInd->setTable(tab.name);
4765 pInd->setLogging(false);
4766
4767 const char* type = *indspec++;
4768 if (strcmp(type, "UNIQUE") == 0) {
4769 ind.type = NdbDictionary::Object::UniqueHashIndex;
4770 pInd->setType((NdbDictionary::Index::Type)ind.type);
4771 tab.induniquecount++;
4772
4773 { char trg_name[ST_MAX_NAME_SIZE];
4774 sprintf(trg_name, "NDB$INDEX_<%s>_UI", ind.name);
4775 ind.trglist->push_back(new ST_Trg("", trg_name));
4776 ST_Trg& trg = *ind.trglist->back();
4777 trg.ind = &ind;
4778 trg.type = NdbDictionary::Object::HashIndexTrigger;
4779 trg.event = TriggerEvent::TE_INSERT;
4780 }
4781 ind.trgcount = 1;
4782 }
4783 else if (strcmp(type, "ORDERED") == 0) {
4784 ind.type = NdbDictionary::Object::OrderedIndex;
4785 pInd->setType((NdbDictionary::Index::Type)ind.type);
4786 tab.indorderedcount++;
4787
4788 { char trg_name[ST_MAX_NAME_SIZE];
4789 sprintf(trg_name, "NDB$INDEX_<%s>_CUSTOM", ind.name);
4790 ind.trglist->push_back(new ST_Trg("", trg_name));
4791 ST_Trg& trg = *ind.trglist->back();
4792 trg.ind = &ind;
4793 trg.type = NdbDictionary::Object::IndexTrigger;
4794 trg.event = TriggerEvent::TE_CUSTOM;
4795 }
4796 ind.trgcount = 1;
4797 }
4798 else
4799 {
4800 require(false);
4801 }
4802
4803 const char* sep = "";
4804 const char* colname;
4805 while ((colname = *indspec++) != 0) {
4806 const NdbDictionary::Column* col = tab.tab->getColumn(colname);
4807 require(col != 0);
4808 pInd->addColumn(*col);
4809
4810 ind.colnames.appfmt("%s%s", sep, colname);
4811 sep = ",";
4812 }
4813
4814 ind.ind = pInd;
4815 tab.indcount++;
4816 }
4817 }
4818 }
4819
4820 // node states
4821
4822 static int
st_report_db_nodes(ST_Con & c,NdbOut & out)4823 st_report_db_nodes(ST_Con& c, NdbOut& out)
4824 {
4825 chk1(c.restarter->get_status() == 0);
4826 char r1[100]; // up
4827 char r2[100]; // down
4828 char r3[100]; // unknown
4829 r1[0] =r2[0] = r3[0] = 0;
4830 int i;
4831 for (i = 1; i < MAX_NODES; i++) {
4832 const ndb_mgm_node_state& state = c.restarter->get_state(i);
4833 if (state.node_type == NDB_MGM_NODE_TYPE_NDB) {
4834 char* r = 0;
4835 if (state.node_status == NDB_MGM_NODE_STATUS_STARTED)
4836 r = r1;
4837 else if (state.node_status == NDB_MGM_NODE_STATUS_NO_CONTACT)
4838 r = r2;
4839 else
4840 r = r3;
4841 sprintf(r + strlen(r), "%s%d", r[0] == 0 ? "" : ",", i);
4842 }
4843 }
4844 if (r2[0] != 0 || r3[0] != 0) {
4845 out << "nodes up:" << r1 << " down:" << r2 << " unknown:" << r3 << endl;
4846 goto err;
4847 }
4848 out << "nodes up:" << r1 << " (all)" << endl;
4849 return 0;
4850 err:
4851 return -1;
4852 }
4853
4854 static int
st_check_db_nodes(ST_Con & c,int ignore_node_id=-1)4855 st_check_db_nodes(ST_Con& c, int ignore_node_id = -1)
4856 {
4857 chk1(c.restarter->get_status() == 0);
4858 int i;
4859 for (i = 1; i < MAX_NODES; i++) {
4860 const ndb_mgm_node_state& state = c.restarter->get_state(i);
4861 if (state.node_type == NDB_MGM_NODE_TYPE_NDB &&
4862 i != ignore_node_id) {
4863 chk2(state.node_status == NDB_MGM_NODE_STATUS_STARTED, " node:" << i);
4864 }
4865 }
4866 return 0;
4867 err:
4868 return -1;
4869 }
4870
4871 #if 0
4872 static int
4873 st_wait_db_node_up(ST_Con& c, int node_id)
4874 {
4875 int count = 0;
4876 int max_count = 30;
4877 int milli_sleep = 2000;
4878 while (count++ < max_count) {
4879 // get status and check that other db nodes have not crashed
4880 chk1(st_check_db_nodes(c, node_id) == 0);
4881
4882 const ndb_mgm_node_state& state = c.restarter->get_state(node_id);
4883 require(state.node_type == NDB_MGM_NODE_TYPE_NDB);
4884 if (state.node_status == NDB_MGM_NODE_STATUS_STARTED)
4885 break;
4886 g_info << "waiting count:" << count << "/" << max_count << endl;
4887 NdbSleep_MilliSleep(milli_sleep);
4888 }
4889 return 0;
4890 err:
4891 return -1;
4892 }
4893 #endif
4894
4895 // extra connection (separate API node)
4896
4897 static int
st_start_xcon(ST_Con & c)4898 st_start_xcon(ST_Con& c)
4899 {
4900 require(c.xcon == 0);
4901 g_info << "start extra connection" << endl;
4902
4903 do {
4904 int ret;
4905 Ndb_cluster_connection* xncc = new Ndb_cluster_connection;
4906 chk2((ret = xncc->connect(30, 1, 0)) == 0, "ret:" << ret);
4907 chk2((ret = xncc->wait_until_ready(30, 10)) == 0, "ret:" << ret);
4908 Ndb* xndb = new Ndb(xncc, c.dbname);
4909 chk1(xndb->init() == 0);
4910 chk1(xndb->waitUntilReady(30) == 0);
4911 // share restarter
4912 c.xcon = new ST_Con(xncc, xndb, c.restarter);
4913 // share objects
4914 c.xcon->tablist = c.tablist;
4915 c.xcon->tabcount = c.tabcount;
4916 c.xcon->is_xcon = true;
4917 } while (0);
4918 return 0;
4919 err:
4920 return -1;
4921 }
4922
4923 static int
st_stop_xcon(ST_Con & c)4924 st_stop_xcon(ST_Con& c)
4925 {
4926 require(c.xcon != 0);
4927 int node_id = c.xcon->node_id;
4928 g_info << "stop extra connection node_id:" << node_id << endl;
4929
4930 c.xcon->restarter = 0;
4931 c.xcon->tablist = 0;
4932 c.xcon->tabcount = 0;
4933 delete c.xcon;
4934 c.xcon = 0;
4935 int count = 0;
4936 while (1) {
4937 chk1(c.restarter->get_status() == 0);
4938 const ndb_mgm_node_state& state = c.restarter->get_state(node_id);
4939 require(state.node_type == NDB_MGM_NODE_TYPE_API);
4940 if (state.version == 0) // means "disconnected"
4941 break;
4942 g_info << "waiting count:" << ++count << endl;
4943 NdbSleep_MilliSleep(10 * count);
4944 }
4945 return 0;
4946 err:
4947 return -1;
4948 }
4949
4950 // error insert
4951
4952 struct ST_Errins {
4953 int value; // error value to insert
4954 int code; // ndb error code to expect
4955 int master; // insert on master / non-master (-1 = random)
4956 int node; // insert on node id
4957 const ST_Errins* list; // include another list
4958 bool ends; // end list
ST_ErrinsST_Errins4959 ST_Errins() :
4960 value(0), code(0), master(-1), node(0), list(0), ends(true)
4961 {}
ST_ErrinsST_Errins4962 ST_Errins(const ST_Errins* l) :
4963 value(0), code(0), master(-1), node(0), list(l), ends(false)
4964 {}
ST_ErrinsST_Errins4965 ST_Errins(int v, int c, int m = -1) :
4966 value(v), code(c), master(m), node(0), list(0), ends(false)
4967 {}
4968 };
4969
4970 static NdbOut&
operator <<(NdbOut & out,const ST_Errins & errins)4971 operator<<(NdbOut& out, const ST_Errins& errins)
4972 {
4973 out << "value:" << errins.value;
4974 out << " code:" << errins.code;
4975 out << " master:" << errins.master;
4976 out << " node:" << errins.node;
4977 return out;
4978 }
4979
4980 static ST_Errins
st_get_errins(ST_Con & c,const ST_Errins * list)4981 st_get_errins(ST_Con& c, const ST_Errins* list)
4982 {
4983 uint size = 0;
4984 while (!list[size++].ends)
4985 ;
4986 require(size > 1);
4987 uint n = urandom(size - 1);
4988 const ST_Errins& errins = list[n];
4989 if (errins.list == 0) {
4990 require(errins.value != 0);
4991 return errins;
4992 }
4993 return st_get_errins(c, errins.list);
4994 }
4995
4996 static int
st_do_errins(ST_Con & c,ST_Errins & errins)4997 st_do_errins(ST_Con& c, ST_Errins& errins)
4998 {
4999 require(errins.value != 0);
5000 if (c.numdbnodes < 2)
5001 errins.master = 1;
5002 else if (errins.master == -1)
5003 errins.master = randomly(1, 2);
5004 if (errins.master) {
5005 errins.node = c.restarter->getMasterNodeId();
5006 } else {
5007 uint rand = urandom(c.numdbnodes);
5008 errins.node = c.restarter->getRandomNotMasterNodeId(rand);
5009 }
5010 g_info << "errins: " << errins << endl;
5011 chk2(c.restarter->insertErrorInNode(errins.node, errins.value) == 0, errins);
5012 c.restarter->get_status(); // do sync call to ensure error has been inserted
5013 return 0;
5014 err:
5015 return -1;
5016 }
5017
5018 // debug aid
5019 #ifndef NDEBUG
5020 static const ST_Obj*
st_find_obj(const char * dbname,const char * name)5021 st_find_obj(const char* dbname, const char* name)
5022 {
5023 const ST_Obj* ret_objp = 0;
5024 int i;
5025 for (i = 0; i < (int)st_objlist.size(); i++) {
5026 const ST_Obj* objp = st_objlist[i];
5027 if (strcmp(objp->dbname, dbname) == 0 &&
5028 strcmp(objp->name, name) == 0) {
5029 require(ret_objp == 0);
5030 ret_objp = objp;
5031 }
5032 }
5033 return ret_objp;
5034 }
5035 #endif
5036
5037 #if 0
5038 static void
5039 st_print_obj(const char* dbname, const char* name, int line = 0)
5040 {
5041 const ST_Obj* objp = st_find_obj(dbname, name);
5042 g_info << name << ": by name:";
5043 if (objp != 0)
5044 g_info << " create:" << objp->create
5045 << " commit:" << objp->commit
5046 << " exists:" << objp->exists();
5047 else
5048 g_info << " not found";
5049 if (line != 0)
5050 g_info << " line:" << line;
5051 g_info << endl;
5052 }
5053 #endif
5054
5055 // set object state
5056
5057 static void
st_set_commit_obj(ST_Con & c,ST_Obj & obj)5058 st_set_commit_obj(ST_Con& c, ST_Obj& obj)
5059 {
5060 bool create_old = obj.create;
5061 bool commit_old = obj.commit;
5062 if (!c.tx_commit && !obj.commit)
5063 obj.create = !obj.create;
5064 obj.commit = true;
5065 if (create_old != obj.create || commit_old != obj.commit) {
5066 g_info << obj.name << ": set commit:"
5067 << " create:" << create_old << "->" << obj.create
5068 << " commit:" << commit_old << "->" << obj.commit << endl;
5069 }
5070 }
5071
5072 #if 0
5073 static void
5074 st_set_commit_trg(ST_Con& c, ST_Trg& trg)
5075 {
5076 st_set_commit_obj(c, trg);
5077 }
5078 #endif
5079
5080 static void
st_set_commit_ind(ST_Con & c,ST_Ind & ind)5081 st_set_commit_ind(ST_Con& c, ST_Ind& ind)
5082 {
5083 st_set_commit_obj(c, ind);
5084 int k;
5085 for (k = 0; k < ind.trgcount; k++) {
5086 ST_Trg& trg = ind.trg(k);
5087 st_set_commit_obj(c, trg);
5088 }
5089 }
5090
5091 static void
st_set_commit_tab(ST_Con & c,ST_Tab & tab)5092 st_set_commit_tab(ST_Con& c, ST_Tab& tab)
5093 {
5094 st_set_commit_obj(c, tab);
5095 int j;
5096 for (j = 0; j < tab.indcount; j++) {
5097 ST_Ind& ind = tab.ind(j);
5098 st_set_commit_ind(c, ind);
5099 }
5100 }
5101
5102 static void
st_set_commit_all(ST_Con & c)5103 st_set_commit_all(ST_Con& c)
5104 {
5105 int i;
5106 for (i = 0; i < c.tabcount; i++) {
5107 ST_Tab& tab = c.tab(i);
5108 st_set_commit_tab(c, tab);
5109 }
5110 }
5111
5112 static void
st_set_create_obj(ST_Con & c,ST_Obj & obj,bool create)5113 st_set_create_obj(ST_Con& c, ST_Obj& obj, bool create)
5114 {
5115 bool create_old = obj.create;
5116 bool commit_old = obj.commit;
5117 obj.create = create;
5118 obj.commit = !c.tx_on;
5119 if (create_old != obj.create || commit_old != obj.commit) {
5120 g_info << obj.name << ": set create:"
5121 << " create:" << create_old << "->" << obj.create
5122 << " commit:" << commit_old << "->" << obj.commit << endl;
5123 }
5124 }
5125
5126 static void
st_set_create_trg(ST_Con & c,ST_Trg & trg,bool create)5127 st_set_create_trg(ST_Con& c, ST_Trg& trg, bool create)
5128 {
5129 st_set_create_obj(c, trg, create);
5130 }
5131
5132 static void
st_set_create_ind(ST_Con & c,ST_Ind & ind,bool create)5133 st_set_create_ind(ST_Con& c, ST_Ind& ind, bool create)
5134 {
5135 st_set_create_obj(c, ind, create);
5136 int k;
5137 for (k = 0; k < ind.trgcount; k++) {
5138 ST_Trg& trg = ind.trg(k);
5139 st_set_create_trg(c, trg, create);
5140 }
5141 }
5142
5143 static void
st_set_create_tab(ST_Con & c,ST_Tab & tab,bool create)5144 st_set_create_tab(ST_Con& c, ST_Tab& tab, bool create)
5145 {
5146 st_set_create_obj(c, tab, create);
5147 int j;
5148 for (j = 0; j < tab.indcount; j++) {
5149 ST_Ind& ind = tab.ind(j);
5150 if (create == true)
5151 require(!ind.exists());
5152 else {
5153 if (ind.exists())
5154 st_set_create_ind(c, ind, false);
5155 }
5156 }
5157 }
5158
5159 // verify against database listing
5160
5161 static bool
st_known_type(const NdbDictionary::Dictionary::List::Element & element)5162 st_known_type(const NdbDictionary::Dictionary::List::Element& element)
5163 {
5164 return element.id != ST_Obj::Skip;
5165 }
5166
5167 static int
st_find_object(const NdbDictionary::Dictionary::List & list,NdbDictionary::Object::Type type,int id)5168 st_find_object(const NdbDictionary::Dictionary::List& list,
5169 NdbDictionary::Object::Type type, int id)
5170 {
5171 int n;
5172 for (n = 0; n < (int)list.count; n++) {
5173 const NdbDictionary::Dictionary::List::Element& element =
5174 list.elements[n];
5175 if (element.type == type && (int)element.id == id)
5176 return n;
5177 }
5178 return -1;
5179 }
5180
5181 // filter out irrelevant by whatever means (we need listObjects2)
5182 static int
st_list_objects(ST_Con & c,NdbDictionary::Dictionary::List & list)5183 st_list_objects(ST_Con& c, NdbDictionary::Dictionary::List& list)
5184 {
5185 g_info << "st_list_objects" << endl;
5186 int keep[256];
5187 memset(keep, 0, sizeof(keep));
5188 chk2(c.dic->listObjects(list) == 0, c.dic->getNdbError());
5189 int n;
5190 // tables
5191 for (n = 0; n < (int)list.count; n++) {
5192 const NdbDictionary::Dictionary::List::Element& element =
5193 list.elements[n];
5194 if (element.type == NdbDictionary::Object::UserTable) {
5195 int i;
5196 for (i = 0; i < c.tabcount; i++) {
5197 const ST_Tab& tab = c.tab(i);
5198 if (strcmp(element.name, tab.name) == 0)
5199 keep[n]++;
5200 }
5201 }
5202 require(keep[n] <= 1);
5203 }
5204 // indexes
5205 for (n = 0; n < (int)list.count; n++) {
5206 const NdbDictionary::Dictionary::List::Element& element =
5207 list.elements[n];
5208 if (element.type == NdbDictionary::Object::UniqueHashIndex ||
5209 element.type == NdbDictionary::Object::OrderedIndex) {
5210 int i, j;
5211 for (i = 0; i < c.tabcount; i++) {
5212 const ST_Tab& tab = c.tab(i);
5213 for (j = 0; j < tab.indcount; j++) {
5214 const ST_Ind& ind = tab.ind(j);
5215 if (strcmp(element.name, ind.name) == 0)
5216 keep[n]++;
5217 }
5218 }
5219 }
5220 require(keep[n] <= 1);
5221 }
5222 // triggers
5223 for (n = 0; n < (int)list.count; n++) {
5224 const NdbDictionary::Dictionary::List::Element& element =
5225 list.elements[n];
5226 if (element.type == NdbDictionary::Object::HashIndexTrigger) {
5227 int id, n2;
5228 chk2(sscanf(element.name, "NDB$INDEX_%d_UI", &id) == 1,
5229 element.name);
5230 n2 = st_find_object(list, NdbDictionary::Object::UniqueHashIndex, id);
5231 chk2(n2 >= 0, element.name);
5232 if (keep[n2])
5233 keep[n]++;
5234 }
5235 if (element.type == NdbDictionary::Object::IndexTrigger) {
5236 int id, n2;
5237 chk2(sscanf(element.name, "NDB$INDEX_%d_CUSTOM", &id) == 1,
5238 element.name);
5239 n2 = st_find_object(list, NdbDictionary::Object::OrderedIndex, id);
5240 chk2(n2 >= 0, element.name);
5241 if (keep[n2])
5242 keep[n]++;
5243 }
5244 require(keep[n] <= 1);
5245 }
5246 // mark ignored
5247 for (n = 0; n < (int)list.count; n++) {
5248 NdbDictionary::Dictionary::List::Element& element =
5249 list.elements[n];
5250 g_info << "id=" << element.id << " type=" << element.type
5251 << " name=" << element.name << " keep=" << keep[n] << endl;
5252 if (!keep[n]) {
5253 require(element.id != ST_Obj::Skip);
5254 element.id = ST_Obj::Skip;
5255 }
5256 }
5257 return 0;
5258 err:
5259 return -1;
5260 }
5261
5262 static bool
st_match_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element)5263 st_match_obj(const ST_Obj& obj,
5264 const NdbDictionary::Dictionary::List::Element& element)
5265 {
5266 int veryverbose = 0;
5267 if (veryverbose) {
5268 g_info
5269 << "match:"
5270 << " " << obj.type << "-" << element.type
5271 << " " << obj.dbname << "-" << element.database
5272 << " " << obj.realname() << "-" << element.name << endl;
5273 }
5274 return
5275 obj.type == element.type &&
5276 strcmp(obj.dbname, element.database) == 0 &&
5277 strcmp(obj.realname(), element.name) == 0;
5278 }
5279
5280 static int // check state
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element)5281 st_verify_obj(const ST_Obj& obj,
5282 const NdbDictionary::Dictionary::List::Element& element)
5283 {
5284 chk2(obj.exists(), obj.name);
5285
5286 if (obj.commit)
5287 chk2(element.state == NdbDictionary::Object::StateOnline, obj.name);
5288
5289 // other states are inconsistent
5290
5291 else if (obj.create) {
5292 if (obj.is_table() || obj.is_index())
5293 chk2(element.state == NdbDictionary::Object::StateBuilding, obj.name);
5294 if (obj.is_trigger())
5295 chk2(element.state == NdbDictionary::Object::StateBuilding, obj.name);
5296 }
5297 else {
5298 if (obj.is_trigger())
5299 chk2(element.state == NdbDictionary::Object::StateOnline, obj.name);
5300 if (obj.is_table() || obj.is_index())
5301 chk2(element.state == NdbDictionary::Object::StateDropping, obj.name);
5302 }
5303 return 0;
5304 err:
5305 return -1;
5306 }
5307
5308 static int // find on list
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List & list)5309 st_verify_obj(const ST_Obj& obj,
5310 const NdbDictionary::Dictionary::List& list)
5311 {
5312 int found = 0;
5313 int n;
5314 for (n = 0; n < (int)list.count; n++) {
5315 const NdbDictionary::Dictionary::List::Element& element =
5316 list.elements[n];
5317 if (!st_known_type(element))
5318 continue;
5319 if (st_match_obj(obj, element)) {
5320 chk1(st_verify_obj(obj, element) == 0);
5321 found += 1;
5322 }
5323 }
5324 if (obj.exists())
5325 chk2(found == 1, obj.name);
5326 else
5327 chk2(found == 0, obj.name);
5328 return 0;
5329 err:
5330 return -1;
5331 }
5332
5333 static int // possible match
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element,int & found)5334 st_verify_obj(const ST_Obj& obj,
5335 const NdbDictionary::Dictionary::List::Element& element,
5336 int& found)
5337 {
5338 if (obj.exists()) {
5339 if (st_match_obj(obj, element)) {
5340 chk1(st_verify_obj(obj, element) == 0);
5341 found += 1;
5342 }
5343 }
5344 else {
5345 chk2(st_match_obj(obj, element) == false, obj.name);
5346 }
5347 return 0;
5348 err:
5349 return -1;
5350 }
5351
5352 static int
st_verify_list(ST_Con & c)5353 st_verify_list(ST_Con& c)
5354 {
5355 NdbDictionary::Dictionary::List list;
5356 chk1(st_list_objects(c, list) == 0);
5357 int i, j, k, n;
5358 // us vs list
5359 for (i = 0; i < c.tabcount; i++) {
5360 const ST_Tab& tab = c.tab(i);
5361 chk1(st_verify_obj(tab, list) == 0);
5362 for (j = 0; j < tab.indcount; j++) {
5363 const ST_Ind& ind = tab.ind(j);
5364 chk1(st_verify_obj(ind, list) == 0);
5365 for (k = 0; k < ind.trgcount; k++) {
5366 const ST_Trg& trg = ind.trg(k);
5367 chk1(st_verify_obj(trg, list) == 0);
5368 }
5369 }
5370 }
5371 // list vs us
5372 for (n = 0; n < (int)list.count; n++) {
5373 const NdbDictionary::Dictionary::List::Element& element =
5374 list.elements[n];
5375 if (!st_known_type(element))
5376 continue;
5377 int found = 0;
5378 for (i = 0; i < c.tabcount; i++) {
5379 const ST_Tab& tab = c.tab(i);
5380 chk1(st_verify_obj(tab, element, found) == 0);
5381 for (j = 0; j < tab.indcount; j++) {
5382 const ST_Ind& ind = tab.ind(j);
5383 chk1(st_verify_obj(ind, element, found) == 0);
5384 for (k = 0; k < ind.trgcount; k++) {
5385 const ST_Trg& trg = ind.trg(k);
5386 chk1(st_verify_obj(trg, element, found) == 0);
5387 }
5388 }
5389 }
5390 const char* dot = element.database[0] != 0 ? "." : "";
5391 chk2(found == 1, element.database << dot << element.name);
5392 }
5393 return 0;
5394 err:
5395 return -1;
5396 }
5397
5398 // wait for DICT to finish current trans
5399
5400 static int
st_wait_idle(ST_Con & c)5401 st_wait_idle(ST_Con& c)
5402 {
5403 // todo: use try-lock when available
5404 g_info << "st_wait_idle" << endl;
5405 int count = 0;
5406 int max_count = 60;
5407 int milli_sleep = 1000;
5408 while (count++ < max_count) {
5409 NdbDictionary::Dictionary::List list;
5410 chk1(st_list_objects(c, list) == 0);
5411 bool ok = true;
5412 int n;
5413 for (n = 0; n < (int)list.count; n++) {
5414 const NdbDictionary::Dictionary::List::Element& element =
5415 list.elements[n];
5416 if (!st_known_type(element))
5417 continue;
5418 if (element.state != NdbDictionary::Object::StateOnline) {
5419 ok = false;
5420 break;
5421 }
5422 }
5423 if (ok)
5424 return 0;
5425 g_info << "waiting count:" << count << "/" << max_count << endl;
5426 NdbSleep_MilliSleep(milli_sleep);
5427 }
5428 g_err << "st_wait_idle: objects did not become Online" << endl;
5429 err:
5430 return -1;
5431 }
5432
5433 // ndb dict comparisons (non-retrieved vs retrieved)
5434
5435 static int
st_equal_column(const NdbDictionary::Column & c1,const NdbDictionary::Column & c2,NdbDictionary::Object::Type type)5436 st_equal_column(const NdbDictionary::Column& c1,
5437 const NdbDictionary::Column& c2,
5438 NdbDictionary::Object::Type type)
5439 {
5440 chk1(strcmp(c1.getName(), c2.getName()) == 0);
5441 chk1(c1.getNullable() == c2.getNullable());
5442 if (type == NdbDictionary::Object::UserTable) {
5443 chk1(c1.getPrimaryKey() == c2.getPrimaryKey());
5444 }
5445 if (0) { // should fix
5446 chk1(c1.getColumnNo() == c2.getColumnNo());
5447 }
5448 chk1(c1.getType() == c2.getType());
5449 if (c1.getType() == NdbDictionary::Column::Decimal ||
5450 c1.getType() == NdbDictionary::Column::Decimalunsigned) {
5451 chk1(c1.getPrecision() == c2.getPrecision());
5452 chk1(c1.getScale() == c2.getScale());
5453 }
5454 if (c1.getType() != NdbDictionary::Column::Blob &&
5455 c1.getType() != NdbDictionary::Column::Text) {
5456 chk1(c1.getLength() == c2.getLength());
5457 } else {
5458 chk1(c1.getInlineSize() == c2.getInlineSize());
5459 chk1(c1.getPartSize() == c2.getPartSize());
5460 chk1(c1.getStripeSize() == c2.getStripeSize());
5461 }
5462 chk1(c1.getCharset() == c2.getCharset());
5463 if (type == NdbDictionary::Object::UserTable) {
5464 chk1(c1.getPartitionKey() == c2.getPartitionKey());
5465 }
5466 chk1(c1.getArrayType() == c2.getArrayType());
5467 chk1(c1.getStorageType() == c2.getStorageType());
5468 chk1(c1.getDynamic() == c2.getDynamic());
5469 chk1(c1.getAutoIncrement() == c2.getAutoIncrement());
5470 return 0;
5471 err:
5472 return -1;
5473 }
5474
5475 static int
st_equal_table(const NdbDictionary::Table & t1,const NdbDictionary::Table & t2)5476 st_equal_table(const NdbDictionary::Table& t1, const NdbDictionary::Table& t2)
5477 {
5478 chk1(strcmp(t1.getName(), t2.getName()) == 0);
5479 chk1(t1.getLogging() == t2.getLogging());
5480 chk1(t1.getFragmentType() == t2.getFragmentType());
5481 chk1(t1.getKValue() == t2.getKValue());
5482 chk1(t1.getMinLoadFactor() == t2.getMinLoadFactor());
5483 chk1(t1.getMaxLoadFactor() == t2.getMaxLoadFactor());
5484 chk1(t1.getNoOfColumns() == t2.getNoOfColumns());
5485 /*
5486 * There is no method to get type of table...
5487 * On the other hand SystemTable/UserTable should be just Table
5488 * and "System" should be an independent property.
5489 */
5490 NdbDictionary::Object::Type type;
5491 type = NdbDictionary::Object::UserTable;
5492 int n;
5493 for (n = 0; n < t1.getNoOfColumns(); n++) {
5494 const NdbDictionary::Column* c1 = t1.getColumn(n);
5495 const NdbDictionary::Column* c2 = t2.getColumn(n);
5496 require(c1 != 0 && c2 != 0);
5497 chk2(st_equal_column(*c1, *c2, type) == 0, "col:" << n);
5498 }
5499 chk1(t1.getNoOfPrimaryKeys() == t2.getNoOfPrimaryKeys());
5500 chk1(t1.getTemporary() == t2.getTemporary());
5501 chk1(t1.getForceVarPart() == t2.getForceVarPart());
5502 return 0;
5503 err:
5504 return -1;
5505 }
5506
5507 static int
st_equal_index(const NdbDictionary::Index & i1,const NdbDictionary::Index & i2)5508 st_equal_index(const NdbDictionary::Index& i1, const NdbDictionary::Index& i2)
5509 {
5510 chk1(strcmp(i1.getName(), i2.getName()) == 0);
5511 require(i1.getTable() != 0 && i2.getTable() != 0);
5512 chk1(strcmp(i1.getTable(), i2.getTable()) == 0);
5513 chk1(i1.getNoOfColumns() == i2.getNoOfColumns());
5514 chk1(i1.getType() == i2.getType());
5515 NdbDictionary::Object::Type type;
5516 type = (NdbDictionary::Object::Type)i1.getType();
5517 int n;
5518 for (n = 0; n < (int)i1.getNoOfColumns(); n++) {
5519 const NdbDictionary::Column* c1 = i1.getColumn(n);
5520 const NdbDictionary::Column* c2 = i2.getColumn(n);
5521 require(c1 != 0 && c2 != 0);
5522 chk2(st_equal_column(*c1, *c2, type) == 0, "col:" << n);
5523 }
5524 chk1(i1.getLogging() == i2.getLogging());
5525 chk1(i1.getTemporary() == i2.getTemporary());
5526 return 0;
5527 err:
5528 return -1;
5529 }
5530
5531 // verify against database objects (hits all nodes randomly)
5532
5533 static int
st_verify_table(ST_Con & c,ST_Tab & tab)5534 st_verify_table(ST_Con& c, ST_Tab& tab)
5535 {
5536 c.dic->invalidateTable(tab.name);
5537 const NdbDictionary::Table* pTab = c.dic->getTable(tab.name);
5538 tab.tab_r = pTab;
5539 if (tab.exists()) {
5540 chk2(pTab != 0, c.dic->getNdbError());
5541 chk1(st_equal_table(*tab.tab, *pTab) == 0);
5542 tab.id = pTab->getObjectId();
5543 g_info << tab << ": verified exists tx_on:" << c.tx_on << endl;
5544 } else {
5545 chk2(pTab == 0, tab);
5546 chk2(c.dic->getNdbError().code == 723, c.dic->getNdbError());
5547 g_info << tab << ": verified not exists tx_on:" << c.tx_on << endl;
5548 tab.id = -1;
5549 }
5550 return 0;
5551 err:
5552 return -1;
5553 }
5554
5555 static int
st_verify_index(ST_Con & c,ST_Ind & ind)5556 st_verify_index(ST_Con& c, ST_Ind& ind)
5557 {
5558 ST_Tab& tab = *ind.tab;
5559 c.dic->invalidateIndex(ind.name, tab.name);
5560 const NdbDictionary::Index* pInd = c.dic->getIndex(ind.name, tab.name);
5561 ind.ind_r = pInd;
5562 if (ind.exists()) {
5563 chk2(pInd != 0, c.dic->getNdbError());
5564 chk1(st_equal_index(*ind.ind, *pInd) == 0);
5565 ind.id = pInd->getObjectId();
5566 g_info << ind << ": verified exists tx_on:" << c.tx_on << endl;
5567 } else {
5568 chk2(pInd == 0, ind);
5569 chk2(c.dic->getNdbError().code == 4243, c.dic->getNdbError());
5570 g_info << ind << ": verified not exists tx_on:" << c.tx_on << endl;
5571 ind.id = -1;
5572 }
5573 return 0;
5574 err:
5575 return -1;
5576 }
5577
5578 static int
st_verify_all(ST_Con & c)5579 st_verify_all(ST_Con& c)
5580 {
5581 chk1(st_verify_list(c) == 0);
5582 int i, j;
5583 for (i = 0; i < c.tabcount; i++) {
5584 ST_Tab& tab = c.tab(i);
5585 chk1(st_verify_table(c, tab) == 0);
5586 for (j = 0; j < tab.indcount; j++) {
5587 ST_Ind& ind = tab.ind(j);
5588 chk1(st_verify_index(c, ind) == 0);
5589 }
5590 }
5591 return 0;
5592 err:
5593 return -1;
5594 }
5595
5596 // subroutines
5597
5598 static const uint
5599 ST_CommitFlag = 0;
5600
5601 static const uint
5602 ST_AbortFlag = NdbDictionary::Dictionary::SchemaTransAbort;
5603
5604 static const uint
5605 ST_BackgroundFlag = NdbDictionary::Dictionary::SchemaTransBackground;
5606
5607 struct ST_Retry {
5608 int max_tries;
5609 int sleep_ms;
5610 };
5611
5612 static int
st_begin_trans(ST_Con & c,int code=0)5613 st_begin_trans(ST_Con& c, int code = 0)
5614 {
5615 g_info << "begin trans";
5616 if (code == 0) {
5617 g_info << endl;
5618 chk2(c.dic->beginSchemaTrans() == 0, c.dic->getNdbError());
5619 chk1(c.dic->hasSchemaTrans() == true);
5620 c.tx_on = true;
5621 } else {
5622 g_info << " - expect error " << code << endl;
5623 chk1(c.dic->beginSchemaTrans() == -1);
5624 const NdbError& error = c.dic->getNdbError();
5625 chk2(error.code == code, error << " wanted: " << code);
5626 }
5627 return 0;
5628 err:
5629 return -1;
5630 }
5631
5632 static int
st_begin_trans(ST_Con & c,ST_Errins errins)5633 st_begin_trans(ST_Con& c, ST_Errins errins)
5634 {
5635 require(errins.code != 0);
5636 chk1(st_do_errins(c, errins) == 0);
5637 chk1(st_begin_trans(c, errins.code) == 0);
5638 return 0;
5639 err:
5640 return -1;
5641 }
5642
5643 static int
st_begin_trans(ST_Con & c,ST_Retry retry)5644 st_begin_trans(ST_Con& c, ST_Retry retry)
5645 {
5646 int tries = 0;
5647 while (++tries <= retry.max_tries) {
5648 int code = 0;
5649 if (c.dic->beginSchemaTrans() == -1) {
5650 code = c.dic->getNdbError().code;
5651 require(code != 0);
5652 }
5653 chk2(code == 0 || code == 780 || code == 701, c.dic->getNdbError());
5654 if (code == 0) {
5655 chk1(c.dic->hasSchemaTrans() == true);
5656 g_info << "begin trans at try " << tries << endl;
5657 break;
5658 }
5659 NdbSleep_MilliSleep(retry.sleep_ms);
5660 }
5661 return 0;
5662 err:
5663 return -1;
5664 }
5665
5666 static int
st_end_trans(ST_Con & c,uint flags)5667 st_end_trans(ST_Con& c, uint flags)
5668 {
5669 g_info << "end trans flags:" << hex << flags << endl;
5670 int res= c.dic->endSchemaTrans(flags);
5671 g_info << "end trans result:" << res << endl;
5672 chk2(res == 0, c.dic->getNdbError());
5673 c.tx_on = false;
5674 c.tx_commit = !(flags & ST_AbortFlag);
5675 st_set_commit_all(c);
5676 return 0;
5677 err:
5678 return -1;
5679 }
5680
5681 static int
st_end_trans_aborted(ST_Con & c,uint flags)5682 st_end_trans_aborted(ST_Con& c, uint flags)
5683 {
5684 g_info << "end trans flags:" << hex << flags << endl;
5685 int res= c.dic->endSchemaTrans(flags);
5686 g_info << "end trans result:" << res << endl;
5687 if (flags & ST_AbortFlag)
5688 chk1(res == 0);
5689 else
5690 chk1(res != 0);
5691 c.tx_on = false;
5692 c.tx_commit = (flags & ST_AbortFlag);
5693 return 0;
5694 err:
5695 return -1;
5696 }
5697
5698 static int
st_end_trans(ST_Con & c,ST_Errins errins,uint flags)5699 st_end_trans(ST_Con& c, ST_Errins errins, uint flags)
5700 {
5701 chk1(st_do_errins(c, errins) == 0);
5702 chk1(st_end_trans(c, flags) == 0);
5703 return 0;
5704 err:
5705 return -1;
5706 }
5707
5708 static int
st_end_trans_aborted(ST_Con & c,ST_Errins errins,uint flags)5709 st_end_trans_aborted(ST_Con& c, ST_Errins errins, uint flags)
5710 {
5711 chk1(st_do_errins(c, errins) == 0);
5712 chk1(st_end_trans_aborted(c, flags) == 0);
5713 return 0;
5714 err:
5715 return -1;
5716 }
5717
5718 static int
st_load_table(ST_Con & c,ST_Tab & tab,int rows=1000)5719 st_load_table(ST_Con& c, ST_Tab& tab, int rows = 1000)
5720 {
5721 g_info << tab.name << ": load data rows:" << rows << endl;
5722 chk1(tab.tab_r != NULL);
5723 {
5724 HugoTransactions ht(*tab.tab_r);
5725 chk1(ht.loadTable(c.ndb, rows) == 0);
5726 }
5727 return 0;
5728 err:
5729 return -1;
5730 }
5731
5732 static int
st_create_table(ST_Con & c,ST_Tab & tab,int code=0)5733 st_create_table(ST_Con& c, ST_Tab& tab, int code = 0)
5734 {
5735 g_info << tab.name << ": create table";
5736 if (code == 0) {
5737 g_info << endl;
5738 require(!tab.exists());
5739 chk2(c.dic->createTable(*tab.tab) == 0, c.dic->getNdbError());
5740 g_info << tab.name << ": created" << endl;
5741 st_set_create_tab(c, tab, true);
5742 }
5743 else {
5744 g_info << " - expect error " << code << endl;
5745 chk1(c.dic->createTable(*tab.tab) == -1);
5746 const NdbError& error = c.dic->getNdbError();
5747 chk2(error.code == code, error << " wanted: " << code);
5748 }
5749 chk1(st_verify_table(c, tab) == 0);
5750 return 0;
5751 err:
5752 return -1;
5753 }
5754
5755 static int
st_create_table(ST_Con & c,ST_Tab & tab,ST_Errins errins)5756 st_create_table(ST_Con& c, ST_Tab& tab, ST_Errins errins)
5757 {
5758 require(errins.code != 0);
5759 chk1(st_do_errins(c, errins) == 0);
5760 chk1(st_create_table(c, tab, errins.code) == 0);
5761 return 0;
5762 err:
5763 return -1;
5764 }
5765
5766 static int
st_drop_table(ST_Con & c,ST_Tab & tab,int code=0)5767 st_drop_table(ST_Con& c, ST_Tab& tab, int code = 0)
5768 {
5769 g_info << tab.name << ": drop table";
5770 if (code == 0) {
5771 g_info << endl;
5772 require(tab.exists());
5773 c.dic->invalidateTable(tab.name);
5774 chk2(c.dic->dropTable(tab.name) == 0, c.dic->getNdbError());
5775 g_info << tab.name << ": dropped" << endl;
5776 st_set_create_tab(c, tab, false);
5777 } else {
5778 g_info << " - expect error " << code << endl;
5779 c.dic->invalidateTable(tab.name);
5780 chk1(c.dic->dropTable(tab.name) == -1);
5781 const NdbError& error = c.dic->getNdbError();
5782 chk2(error.code == code, error << " wanted: " << code);
5783 }
5784 chk1(st_verify_table(c, tab) == 0);
5785 return 0;
5786 err:
5787 return -1;
5788 }
5789
5790 static int
st_drop_table(ST_Con & c,ST_Tab & tab,ST_Errins errins)5791 st_drop_table(ST_Con& c, ST_Tab& tab, ST_Errins errins)
5792 {
5793 require(errins.code != 0);
5794 chk1(st_do_errins(c, errins) == 0);
5795 chk1(st_drop_table(c, tab, errins.code) == 0);
5796 return 0;
5797 err:
5798 return -1;
5799 }
5800
5801 static int
st_create_index(ST_Con & c,ST_Ind & ind,int code=0)5802 st_create_index(ST_Con& c, ST_Ind& ind, int code = 0)
5803 {
5804 ST_Tab& tab = *ind.tab;
5805 g_info << ind.name << ": create index on "
5806 << tab.name << "(" << ind.colnames.c_str() << ")";
5807 if (code == 0) {
5808 g_info << endl;
5809 require(!ind.exists());
5810 chk2(c.dic->createIndex(*ind.ind, *tab.tab_r) == 0, c.dic->getNdbError());
5811 st_set_create_ind(c, ind, true);
5812 g_info << ind.name << ": created" << endl;
5813 } else {
5814 g_info << " - expect error " << code << endl;
5815 chk1(c.dic->createIndex(*ind.ind, *tab.tab_r) == -1);
5816 const NdbError& error = c.dic->getNdbError();
5817 chk2(error.code == code, error << " wanted: " << code);
5818 }
5819 chk1(st_verify_index(c, ind) == 0);
5820 return 0;
5821 err:
5822 return -1;
5823 }
5824
5825 static int
st_create_index(ST_Con & c,ST_Ind & ind,ST_Errins errins)5826 st_create_index(ST_Con& c, ST_Ind& ind, ST_Errins errins)
5827 {
5828 require(errins.code != 0);
5829 chk1(st_do_errins(c, errins) == 0);
5830 chk1(st_create_index(c, ind, errins.code) == 0);
5831 return 0;
5832 err:
5833 return -1;
5834 }
5835
5836 static int
st_drop_index(ST_Con & c,ST_Ind & ind,int code=0)5837 st_drop_index(ST_Con& c, ST_Ind& ind, int code = 0)
5838 {
5839 ST_Tab& tab = *ind.tab;
5840 g_info << ind.name << ": drop index";
5841 if (code == 0) {
5842 g_info << endl;
5843 require(ind.exists());
5844 c.dic->invalidateIndex(ind.name, tab.name);
5845 chk2(c.dic->dropIndex(ind.name, tab.name) == 0, c.dic->getNdbError());
5846 g_info << ind.name << ": dropped" << endl;
5847 st_set_create_ind(c, ind, false);
5848 } else {
5849 g_info << " expect error " << code << endl;
5850 c.dic->invalidateIndex(ind.name, tab.name);
5851 chk1(c.dic->dropIndex(ind.name, tab.name) == -1);
5852 const NdbError& error = c.dic->getNdbError();
5853 chk2(error.code == code, error << " wanted: " << code);
5854 }
5855 chk1(st_verify_index(c, ind) == 0);
5856 return 0;
5857 err:
5858 return -1;
5859 }
5860
5861 static int
st_drop_index(ST_Con & c,ST_Ind & ind,ST_Errins errins)5862 st_drop_index(ST_Con& c, ST_Ind& ind, ST_Errins errins)
5863 {
5864 require(errins.code != 0);
5865 chk1(st_do_errins(c, errins) == 0);
5866 chk1(st_drop_index(c, ind, errins.code) == 0);
5867 return 0;
5868 err:
5869 return -1;
5870 }
5871
5872 static int
st_create_table_index(ST_Con & c,ST_Tab & tab)5873 st_create_table_index(ST_Con& c, ST_Tab& tab)
5874 {
5875 chk1(st_create_table(c, tab) == 0);
5876 int j;
5877 for (j = 0; j < tab.indcount; j++) {
5878 ST_Ind& ind = tab.ind(j);
5879 chk1(st_create_index(c, ind) == 0);
5880 }
5881 return 0;
5882 err:
5883 return -1;
5884 }
5885
5886 // drop all
5887
5888 static int
st_drop_test_tables(ST_Con & c)5889 st_drop_test_tables(ST_Con& c)
5890 {
5891 g_info << "st_drop_test_tables" << endl;
5892 int i;
5893 for (i = 0; i < c.tabcount; i++) {
5894 ST_Tab& tab = c.tab(i);
5895 if (tab.exists())
5896 chk1(st_drop_table(c, tab) == 0);
5897 }
5898 return 0;
5899 err:
5900 return -1;
5901 }
5902
5903 // error insert values
5904
5905 static const ST_Errins
5906 st_errins_begin_trans[] = {
5907 ST_Errins(6101, 780),
5908 ST_Errins()
5909 };
5910
5911 static const ST_Errins
5912 st_errins_end_trans1[] = {
5913 ST_Errins(ERR_INSERT_MASTER_FAILURE1, 0, 1),
5914 ST_Errins()
5915 };
5916
5917 static const ST_Errins
5918 st_errins_end_trans2[] = {
5919 ST_Errins(ERR_INSERT_MASTER_FAILURE2, 0, 1),
5920 ST_Errins()
5921 };
5922
5923 static const ST_Errins
5924 st_errins_end_trans3[] = {
5925 ST_Errins(ERR_INSERT_MASTER_FAILURE3, 0, 1),
5926 ST_Errins()
5927 };
5928
5929 static const ST_Errins
5930 st_errins_table[] = {
5931 ST_Errins(6111, 783),
5932 ST_Errins(6121, 9121),
5933 //ST_Errins(6131, 9131),
5934 ST_Errins()
5935 };
5936
5937 static ST_Errins
5938 st_errins_index[] = {
5939 ST_Errins(st_errins_table),
5940 ST_Errins(6112, 783),
5941 ST_Errins(6113, 783),
5942 ST_Errins(6114, 783),
5943 ST_Errins(6122, 9122),
5944 ST_Errins(6123, 9123),
5945 ST_Errins(6124, 9124),
5946 //ST_Errins(6132, 9131),
5947 //ST_Errins(6133, 9131),
5948 //ST_Errins(6134, 9131),
5949 //ST_Errins(6135, 9131),
5950 ST_Errins()
5951 };
5952
5953 static ST_Errins
5954 st_errins_index_create[] = {
5955 ST_Errins(st_errins_index),
5956 ST_Errins(6116, 783),
5957 ST_Errins(6126, 9126),
5958 //ST_Errins(6136, 9136),
5959 ST_Errins()
5960 };
5961
5962 static ST_Errins
5963 st_errins_index_drop[] = {
5964 ST_Errins(st_errins_index),
5965 ST_Errins()
5966 };
5967
5968 // specific test cases
5969
5970 static int
st_test_create(ST_Con & c,int arg=-1)5971 st_test_create(ST_Con& c, int arg = -1)
5972 {
5973 int do_abort = (arg == 1);
5974 int i;
5975 chk1(st_begin_trans(c) == 0);
5976 for (i = 0; i < c.tabcount; i++) {
5977 ST_Tab& tab = c.tab(i);
5978 chk1(st_create_table_index(c, tab) == 0);
5979 }
5980 chk1(st_verify_list(c) == 0);
5981 if (!do_abort)
5982 chk1(st_end_trans(c, 0) == 0);
5983 else
5984 chk1(st_end_trans(c, ST_AbortFlag) == 0);
5985 chk1(st_verify_list(c) == 0);
5986 if (!do_abort)
5987 chk1(st_drop_test_tables(c) == 0);
5988 return NDBT_OK;
5989 err:
5990 return NDBT_FAILED;
5991 }
5992
5993 static int
st_test_drop(ST_Con & c,int arg=-1)5994 st_test_drop(ST_Con& c, int arg = -1)
5995 {
5996 int do_abort = (arg == 1);
5997 int i;
5998 for (i = 0; i < c.tabcount; i++) {
5999 ST_Tab& tab = c.tab(i);
6000 chk1(st_create_table_index(c, tab) == 0);
6001 }
6002 chk1(st_begin_trans(c) == 0);
6003 for (i = 0; i < c.tabcount; i++) {
6004 ST_Tab& tab = c.tab(i);
6005 chk1(st_drop_table(c, tab) == 0);
6006 }
6007 chk1(st_verify_list(c) == 0);
6008 if (!do_abort)
6009 chk1(st_end_trans(c, 0) == 0);
6010 else
6011 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6012 chk1(st_verify_list(c) == 0);
6013 return NDBT_OK;
6014 err:
6015 return NDBT_FAILED;
6016 }
6017
6018 static int
st_test_rollback_create_table(ST_Con & c,int arg=-1)6019 st_test_rollback_create_table(ST_Con& c, int arg = -1)
6020 {
6021 int i;
6022 chk1(st_begin_trans(c) == 0);
6023 for (i = 0; i < c.tabcount; i++) {
6024 ST_Tab& tab = c.tab(i);
6025 if (i % 2 == 0) {
6026 ST_Errins errins(6111, 783, 0); // fail CTa seize op
6027 chk1(st_create_table(c, tab, errins) == 0);
6028 } else {
6029 chk1(st_create_table(c, tab) == 0);
6030 }
6031 }
6032 chk1(st_end_trans(c, 0) == 0);
6033 chk1(st_verify_list(c) == 0);
6034 for (i = 0; i < c.tabcount; i++) {
6035 ST_Tab& tab = c.tab(i);
6036 if (i % 2 == 0)
6037 require(!tab.exists());
6038 else {
6039 require(tab.exists());
6040 chk1(st_drop_table(c, tab) == 0);
6041 }
6042 }
6043 return NDBT_OK;
6044 err:
6045 return NDBT_FAILED;
6046 }
6047
6048 static int
st_test_rollback_drop_table(ST_Con & c,int arg=-1)6049 st_test_rollback_drop_table(ST_Con& c, int arg = -1)
6050 {
6051 int i;
6052 for (i = 0; i < c.tabcount; i++) {
6053 ST_Tab& tab = c.tab(i);
6054 chk1(st_create_table(c, tab) == 0);
6055 }
6056 chk1(st_begin_trans(c) == 0);
6057 for (i = 0; i < c.tabcount; i++) {
6058 ST_Tab& tab = c.tab(i);
6059 if (i % 2 == 0) {
6060 ST_Errins errins(6111, 783, 0); // fail DTa seize op
6061 chk1(st_drop_table(c, tab, errins) == 0);
6062 } else {
6063 chk1(st_drop_table(c, tab) == 0);
6064 }
6065 }
6066 chk1(st_end_trans(c, 0) == 0);
6067 chk1(st_verify_list(c) == 0);
6068 for (i = 0; i < c.tabcount; i++) {
6069 ST_Tab& tab = c.tab(i);
6070 if (i % 2 == 0) {
6071 require(tab.exists());
6072 chk1(st_drop_table(c, tab) == 0);
6073 } else {
6074 require(!tab.exists());
6075 }
6076 }
6077 return NDBT_OK;
6078 err:
6079 return NDBT_FAILED;
6080 }
6081
6082 static int
st_test_rollback_create_index(ST_Con & c,int arg=-1)6083 st_test_rollback_create_index(ST_Con& c, int arg = -1)
6084 {
6085 int i, j;
6086 for (i = 0; i < c.tabcount; i++) {
6087 ST_Tab& tab = c.tab(i);
6088 if (tab.indcount < 1)
6089 continue;
6090 chk1(st_create_table(c, tab) == 0);
6091 chk1(st_begin_trans(c) == 0);
6092 for (j = 0; j < tab.indcount; j++) {
6093 ST_Ind& ind = tab.ind(j);
6094 if (j % 2 == 0) {
6095 ST_Errins errins(6116, 783, 0); // fail BIn seize op
6096 chk1(st_create_index(c, ind, errins) == 0);
6097 } else {
6098 chk1(st_create_index(c, ind) == 0);
6099 }
6100 }
6101 chk1(st_end_trans(c, 0) == 0);
6102 chk1(st_verify_list(c) == 0);
6103 for (j = 0; j < tab.indcount; j++) {
6104 ST_Ind& ind = tab.ind(j);
6105 if (j % 2 == 0)
6106 require(!ind.exists());
6107 else {
6108 require(ind.exists());
6109 chk1(st_drop_index(c, ind) == 0);
6110 }
6111 }
6112 chk1(st_drop_table(c, tab) == 0);
6113 }
6114 return NDBT_OK;
6115 err:
6116 return NDBT_FAILED;
6117 }
6118
6119 static int
st_test_rollback_drop_index(ST_Con & c,int arg=-1)6120 st_test_rollback_drop_index(ST_Con& c, int arg = -1)
6121 {
6122 int i, j;
6123 for (i = 0; i < c.tabcount; i++) {
6124 ST_Tab& tab = c.tab(i);
6125 if (tab.indcount < 1)
6126 continue;
6127 chk1(st_create_table_index(c, tab) == 0);
6128 }
6129 for (i = 0; i < c.tabcount; i++) {
6130 ST_Tab& tab = c.tab(i);
6131 if (tab.indcount < 1)
6132 continue;
6133 chk1(st_begin_trans(c) == 0);
6134 for (j = 0; j < tab.indcount; j++) {
6135 ST_Ind& ind = tab.ind(j);
6136 if (j % 2 == 0) {
6137 ST_Errins errins(6114, 783, 0); // fail ATr seize op
6138 chk1(st_drop_index(c, ind, errins) == 0);
6139 } else {
6140 chk1(st_drop_index(c, ind) == 0);
6141 }
6142 }
6143 chk1(st_end_trans(c, 0) == 0);
6144 chk1(st_verify_list(c) == 0);
6145 for (j = 0; j < tab.indcount; j++) {
6146 ST_Ind& ind = tab.ind(j);
6147 if (j % 2 == 0) {
6148 require(ind.exists());
6149 chk1(st_drop_index(c, ind) == 0);
6150 } else {
6151 require(!ind.exists());
6152 }
6153 }
6154 }
6155 return NDBT_OK;
6156 err:
6157 return NDBT_FAILED;
6158 }
6159
6160 static int
st_test_dup_create_table(ST_Con & c,int arg=-1)6161 st_test_dup_create_table(ST_Con& c, int arg = -1)
6162 {
6163 int do_trans;
6164 int do_abort;
6165 int i;
6166 for (do_trans = 0; do_trans <= 1; do_trans++) {
6167 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6168 g_info << "trans:" << do_trans
6169 << " abort:" << do_abort << endl;
6170 for (i = 0; i < c.tabcount; i++) {
6171 ST_Tab& tab = c.tab(i);
6172 if (do_trans)
6173 chk1(st_begin_trans(c) == 0);
6174 chk1(st_create_table(c, tab) == 0);
6175 chk1(st_create_table(c, tab, 721) == 0);
6176 if (do_trans) {
6177 if (!do_abort)
6178 chk1(st_end_trans(c, 0) == 0);
6179 else
6180 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6181 }
6182 chk1(st_verify_list(c) == 0);
6183 if (tab.exists()) {
6184 chk1(st_drop_table(c, tab) == 0);
6185 }
6186 }
6187 }
6188 }
6189 return NDBT_OK;
6190 err:
6191 return NDBT_FAILED;
6192 }
6193
6194 static int
st_test_dup_drop_table(ST_Con & c,int arg=-1)6195 st_test_dup_drop_table(ST_Con& c, int arg = -1)
6196 {
6197 int do_trans;
6198 int do_abort;
6199 int i;
6200 for (do_trans = 0; do_trans <= 1; do_trans++) {
6201 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6202 g_info << "trans:" << do_trans
6203 << " abort:" << do_abort << endl;
6204 for (i = 0; i < c.tabcount; i++) {
6205 ST_Tab& tab = c.tab(i);
6206 chk1(st_create_table(c, tab) == 0);
6207 if (do_trans)
6208 chk1(st_begin_trans(c) == 0);
6209 chk1(st_drop_table(c, tab) == 0);
6210 if (!do_trans)
6211 chk1(st_drop_table(c, tab, 723) == 0);
6212 else
6213 chk1(st_drop_table(c, tab, 785) == 0);
6214 if (do_trans) {
6215 if (!do_abort)
6216 chk1(st_end_trans(c, 0) == 0);
6217 else
6218 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6219 }
6220 chk1(st_verify_list(c) == 0);
6221 if (tab.exists()) {
6222 chk1(st_drop_table(c, tab) == 0);
6223 }
6224 }
6225 }
6226 }
6227 return NDBT_OK;
6228 err:
6229 return NDBT_FAILED;
6230 }
6231
6232 static int
st_test_dup_create_index(ST_Con & c,int arg=-1)6233 st_test_dup_create_index(ST_Con& c, int arg = -1)
6234 {
6235 int do_trans;
6236 int do_abort;
6237 int i, j;
6238 for (do_trans = 0; do_trans <= 1; do_trans++) {
6239 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6240 g_info << "trans:" << do_trans
6241 << " abort:" << do_abort << endl;
6242 for (i = 0; i < c.tabcount; i++) {
6243 ST_Tab& tab = c.tab(i);
6244 if (tab.indcount < 1)
6245 continue;
6246 chk1(st_create_table(c, tab) == 0);
6247 for (j = 0; j < tab.indcount; j++) {
6248 ST_Ind& ind = tab.ind(j);
6249 if (do_trans)
6250 chk1(st_begin_trans(c) == 0);
6251 chk1(st_create_index(c, ind) == 0);
6252 chk1(st_create_index(c, ind, 721) == 0);
6253 if (do_trans) {
6254 if (!do_abort)
6255 chk1(st_end_trans(c, 0) == 0);
6256 else
6257 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6258 }
6259 chk1(st_verify_list(c) == 0);
6260 }
6261 chk1(st_drop_table(c, tab) == 0);
6262 }
6263 }
6264 }
6265 return NDBT_OK;
6266 err:
6267 return NDBT_FAILED;
6268 }
6269
6270 static int
st_test_dup_drop_index(ST_Con & c,int arg=-1)6271 st_test_dup_drop_index(ST_Con& c, int arg = -1)
6272 {
6273 int do_trans;
6274 int do_abort;
6275 int i, j;
6276 for (do_trans = 0; do_trans <= 1; do_trans++) {
6277 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6278 g_info << "trans:" << do_trans
6279 << " abort:" << do_abort << endl;
6280 for (i = 0; i < c.tabcount; i++) {
6281 ST_Tab& tab = c.tab(i);
6282 if (tab.indcount < 1)
6283 continue;
6284 chk1(st_create_table(c, tab) == 0);
6285 for (j = 0; j < tab.indcount; j++) {
6286 ST_Ind& ind = tab.ind(j);
6287 chk1(st_create_index(c, ind) == 0);
6288 if (do_trans)
6289 chk1(st_begin_trans(c) == 0);
6290 chk1(st_drop_index(c, ind) == 0);
6291 if (!do_trans)
6292 chk1(st_drop_index(c, ind, 4243) == 0);
6293 else
6294 chk1(st_drop_index(c, ind, 785) == 0);
6295 if (do_trans) {
6296 if (!do_abort)
6297 chk1(st_end_trans(c, 0) == 0);
6298 else
6299 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6300 }
6301 chk1(st_verify_list(c) == 0);
6302 }
6303 chk1(st_drop_table(c, tab) == 0);
6304 }
6305 }
6306 }
6307 return NDBT_OK;
6308 err:
6309 return NDBT_FAILED;
6310 }
6311
6312 static int
st_test_build_index(ST_Con & c,int arg=-1)6313 st_test_build_index(ST_Con& c, int arg = -1)
6314 {
6315 int i, j;
6316 for (i = 0; i < c.tabcount; i++) {
6317 ST_Tab& tab = c.tab(i);
6318 if (tab.indcount < 1)
6319 continue;
6320 chk1(st_create_table(c, tab) == 0);
6321 chk1(st_load_table(c, tab) == 0);
6322 for (j = 0; j < tab.indcount; j++) {
6323 ST_Ind& ind = tab.ind(j);
6324 chk1(st_create_index(c, ind) == 0);
6325 chk1(st_verify_list(c) == 0);
6326 }
6327 chk1(st_drop_table(c, tab) == 0);
6328 }
6329 return NDBT_OK;
6330 err:
6331 return NDBT_FAILED;
6332 }
6333
6334 static ST_Errins
6335 st_test_local_create_list[] = {
6336 ST_Errins(8033, 293, 1), // TC trigger
6337 ST_Errins(8033, 293, 0),
6338 ST_Errins(4003, 4237, 1), // TUP trigger
6339 ST_Errins(4003, 4237, 0),
6340 ST_Errins(8034, 292, 1), // TC index
6341 ST_Errins(8034, 292, 0)
6342 };
6343
6344 static int
st_test_local_create(ST_Con & c,int arg=-1)6345 st_test_local_create(ST_Con& c, int arg = -1)
6346 {
6347 const int n = arg;
6348 ST_Errins *list = st_test_local_create_list;
6349 const int listlen =
6350 sizeof(st_test_local_create_list)/sizeof(st_test_local_create_list[0]);
6351 require(0 <= n && n < listlen);
6352 const bool only_unique = (n == 0 || n == 1 || n == 4 || n == 5);
6353 int i, j;
6354 for (i = 0; i < c.tabcount; i++) {
6355 ST_Tab& tab = c.tab(i);
6356 bool tabdone = false;
6357 for (j = 0; j < tab.indcount; j++) {
6358 ST_Ind& ind = tab.ind(j);
6359 if (only_unique && !ind.is_unique())
6360 continue;
6361 if (!tabdone) {
6362 chk1(st_create_table(c, tab) == 0);
6363 chk1(st_load_table(c, tab) == 0);
6364 tabdone = true;
6365 }
6366 ST_Errins errins = list[n];
6367 chk1(st_create_index(c, ind, errins) == 0);
6368 chk1(st_verify_list(c) == 0);
6369 }
6370 if (tabdone)
6371 chk1(st_drop_table(c, tab) == 0);
6372 }
6373 return NDBT_OK;
6374 err:
6375 return NDBT_FAILED;
6376 }
6377
6378 // random test cases
6379
6380 static const uint ST_AllowAbort = 1;
6381 static const uint ST_AllowErrins = 2;
6382
6383 static int
st_test_trans(ST_Con & c,int arg=-1)6384 st_test_trans(ST_Con& c, int arg = -1)
6385 {
6386 if ((arg & ST_AllowErrins) && randomly(2, 3)) {
6387 ST_Errins errins = st_get_errins(c, st_errins_begin_trans);
6388 chk1(st_begin_trans(c, errins) == 0);
6389 } else {
6390 chk1(st_begin_trans(c) == 0);
6391 if (randomly(1, 5)) {
6392 g_info << "try duplicate begin trans" << endl;
6393 chk1(st_begin_trans(c, 4410) == 0);
6394 chk1(c.dic->hasSchemaTrans() == true);
6395 }
6396 if ((arg & ST_AllowAbort) && randomly(1, 3)) {
6397 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6398 } else {
6399 chk1(st_end_trans(c, 0) == 0);
6400 }
6401 }
6402 return NDBT_OK;
6403 err:
6404 return NDBT_FAILED;
6405 }
6406
6407 static int
st_test_create_table(ST_Con & c,int arg=-1)6408 st_test_create_table(ST_Con& c, int arg = -1)
6409 {
6410 bool trans = randomly(3, 4);
6411 bool simpletrans = !trans && randomly(1, 2);
6412 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6413 if (trans) {
6414 chk1(st_begin_trans(c) == 0);
6415 }
6416 int i;
6417 for (i = 0; i < c.tabcount; i++) {
6418 ST_Tab& tab = c.tab(i);
6419 if (tab.exists()) {
6420 g_info << tab.name << ": skip existing" << endl;
6421 continue;
6422 }
6423 g_info << tab.name << ": to create" << endl;
6424 if (simpletrans) {
6425 chk1(st_begin_trans(c) == 0);
6426 }
6427 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6428 ST_Errins errins = st_get_errins(c, st_errins_table);
6429 chk1(st_create_table(c, tab, errins) == 0);
6430 if (simpletrans) {
6431 if (randomly(1, 2))
6432 chk1(st_end_trans(c, 0) == 0);
6433 else
6434 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6435 }
6436 } else {
6437 chk1(st_create_table(c, tab) == 0);
6438 if (simpletrans) {
6439 uint flags = 0;
6440 if ((arg & ST_AllowAbort) && randomly(4, 5))
6441 flags |= ST_AbortFlag;
6442 chk1(st_end_trans(c, flags) == 0);
6443 }
6444 }
6445 if (tab.exists() && randomly(1, 3)) {
6446 g_info << tab.name << ": try duplicate create" << endl;
6447 chk1(st_create_table(c, tab, 721) == 0);
6448 }
6449 }
6450 if (trans) {
6451 uint flags = 0;
6452 if ((arg & ST_AllowAbort) && randomly(4, 5))
6453 flags |= ST_AbortFlag;
6454 chk1(st_end_trans(c, flags) == 0);
6455 }
6456 return NDBT_OK;
6457 err:
6458 return NDBT_FAILED;
6459 }
6460
6461 static int
st_test_drop_table(ST_Con & c,int arg=-1)6462 st_test_drop_table(ST_Con& c, int arg = -1)
6463 {
6464 bool trans = randomly(3, 4);
6465 bool simpletrans = !trans && randomly(1, 2);
6466 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6467 if (trans) {
6468 chk1(st_begin_trans(c) == 0);
6469 }
6470 int i;
6471 for (i = 0; i < c.tabcount; i++) {
6472 ST_Tab& tab = c.tab(i);
6473 if (!tab.exists()) {
6474 g_info << tab.name << ": skip not existing" << endl;
6475 continue;
6476 }
6477 g_info << tab.name << ": to drop" << endl;
6478 if (simpletrans) {
6479 chk1(st_begin_trans(c) == 0);
6480 }
6481 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6482 ST_Errins errins = st_get_errins(c, st_errins_table);
6483 chk1(st_drop_table(c, tab, errins) == 0);
6484 if (simpletrans) {
6485 if (randomly(1, 2))
6486 chk1(st_end_trans(c, 0) == 0);
6487 else
6488 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6489 }
6490 } else {
6491 chk1(st_drop_table(c, tab) == 0);
6492 if (simpletrans) {
6493 uint flags = 0;
6494 if ((arg & ST_AllowAbort) && randomly(4, 5))
6495 flags |= ST_AbortFlag;
6496 chk1(st_end_trans(c, flags) == 0);
6497 }
6498 }
6499 if (!tab.exists() && randomly(1, 3)) {
6500 g_info << tab.name << ": try duplicate drop" << endl;
6501 chk1(st_drop_table(c, tab, 723) == 0);
6502 }
6503 }
6504 if (trans) {
6505 uint flags = 0;
6506 if ((arg & ST_AllowAbort) && randomly(4, 5))
6507 flags |= ST_AbortFlag;
6508 chk1(st_end_trans(c, flags) == 0);
6509 }
6510 return NDBT_OK;
6511 err:
6512 return NDBT_FAILED;
6513 }
6514
6515 static int
st_test_table(ST_Con & c,int arg=-1)6516 st_test_table(ST_Con& c, int arg = -1)
6517 {
6518 chk1(st_test_create_table(c) == NDBT_OK);
6519 chk1(st_test_drop_table(c) == NDBT_OK);
6520 return NDBT_OK;
6521 err:
6522 return NDBT_FAILED;
6523 }
6524
6525 static int
st_test_create_index(ST_Con & c,int arg=-1)6526 st_test_create_index(ST_Con& c, int arg = -1)
6527 {
6528 bool trans = randomly(3, 4);
6529 bool simpletrans = !trans && randomly(1, 2);
6530 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6531 if (trans) {
6532 chk1(st_begin_trans(c) == 0);
6533 }
6534 int i, j;
6535 for (i = 0; i < c.tabcount; i++) {
6536 ST_Tab& tab = c.tab(i);
6537 if (tab.indcount == 0)
6538 continue;
6539 if (!tab.exists()) {
6540 g_info << tab.name << ": to create" << endl;
6541 chk1(st_create_table(c, tab) == 0);
6542 }
6543 for (j = 0; j < tab.indcount; j++) {
6544 ST_Ind& ind = tab.ind(j);
6545 if (ind.exists()) {
6546 g_info << ind.name << ": skip existing" << endl;
6547 continue;
6548 }
6549 g_info << ind.name << ": to create" << endl;
6550 if (simpletrans) {
6551 chk1(st_begin_trans(c) == 0);
6552 }
6553 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6554 const ST_Errins* list = st_errins_index_create;
6555 ST_Errins errins = st_get_errins(c, list);
6556 chk1(st_create_index(c, ind, errins) == 0);
6557 if (simpletrans) {
6558 if (randomly(1, 2))
6559 chk1(st_end_trans(c, 0) == 0);
6560 else
6561 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6562 }
6563 } else {
6564 chk1(st_create_index(c, ind) == 0);
6565 if (simpletrans) {
6566 uint flags = 0;
6567 if ((arg & ST_AllowAbort) && randomly(4, 5))
6568 flags |= ST_AbortFlag;
6569 chk1(st_end_trans(c, flags) == 0);
6570 }
6571 }
6572 if (ind.exists() && randomly(1, 3)) {
6573 g_info << ind.name << ": try duplicate create" << endl;
6574 chk1(st_create_index(c, ind, 721) == 0);
6575 }
6576 }
6577 }
6578 if (trans) {
6579 uint flags = 0;
6580 if ((arg & ST_AllowAbort) && randomly(4, 5))
6581 flags |= ST_AbortFlag;
6582 chk1(st_end_trans(c, flags) == 0);
6583 }
6584 return NDBT_OK;
6585 err:
6586 return NDBT_FAILED;
6587 }
6588
6589 static int
st_test_drop_index(ST_Con & c,int arg=-1)6590 st_test_drop_index(ST_Con& c, int arg = -1)
6591 {
6592 bool trans = randomly(3, 4);
6593 bool simpletrans = !trans && randomly(1, 2);
6594 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
6595 if (trans) {
6596 chk1(st_begin_trans(c) == 0);
6597 }
6598 int i, j;
6599 for (i = 0; i < c.tabcount; i++) {
6600 ST_Tab& tab = c.tab(i);
6601 if (tab.indcount == 0)
6602 continue;
6603 if (!tab.exists()) {
6604 g_info << tab.name << ": skip not existing" << endl;
6605 continue;
6606 }
6607 for (j = 0; j < tab.indcount; j++) {
6608 ST_Ind& ind = tab.ind(j);
6609 if (!ind.exists()) {
6610 g_info << ind.name << ": skip not existing" << endl;
6611 continue;
6612 }
6613 g_info << ind.name << ": to drop" << endl;
6614 if (simpletrans) {
6615 chk1(st_begin_trans(c) == 0);
6616 }
6617 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
6618 const ST_Errins* list = st_errins_index_drop;
6619 ST_Errins errins = st_get_errins(c, list);
6620 chk1(st_drop_index(c, ind, errins) == 0);
6621 if (simpletrans) {
6622 if (randomly(1, 2))
6623 chk1(st_end_trans(c, 0) == 0);
6624 else
6625 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6626 }
6627 } else {
6628 chk1(st_drop_index(c, ind) == 0);
6629 if (simpletrans) {
6630 uint flags = 0;
6631 if ((arg & ST_AllowAbort) && randomly(4, 5))
6632 flags |= ST_AbortFlag;
6633 chk1(st_end_trans(c, flags) == 0);
6634 }
6635 }
6636 if (!ind.exists() && randomly(1, 3)) {
6637 g_info << ind.name << ": try duplicate drop" << endl;
6638 chk1(st_drop_index(c, ind, 4243) == 0);
6639 }
6640 }
6641 }
6642 if (trans) {
6643 uint flags = 0;
6644 if ((arg & ST_AllowAbort) && randomly(4, 5))
6645 flags |= ST_AbortFlag;
6646 chk1(st_end_trans(c, flags) == 0);
6647 }
6648 return NDBT_OK;
6649 err:
6650 return NDBT_FAILED;
6651 }
6652
6653 static int
st_test_index(ST_Con & c,int arg=-1)6654 st_test_index(ST_Con& c, int arg = -1)
6655 {
6656 chk1(st_test_create_index(c) == NDBT_OK);
6657 chk1(st_test_drop_index(c) == NDBT_OK);
6658 return NDBT_OK;
6659 err:
6660 return NDBT_FAILED;
6661 }
6662
6663 // node failure and system restart
6664
6665 static int
st_test_anf_parse(ST_Con & c,int arg=-1)6666 st_test_anf_parse(ST_Con& c, int arg = -1)
6667 {
6668 int i;
6669 chk1(st_start_xcon(c) == 0);
6670 {
6671 ST_Con& xc = *c.xcon;
6672 chk1(st_begin_trans(xc) == 0);
6673 for (i = 0; i < c.tabcount; i++) {
6674 ST_Tab& tab = c.tab(i);
6675 chk1(st_create_table_index(xc, tab) == 0);
6676 }
6677 // DICT aborts the trans
6678 xc.tx_on = false;
6679 xc.tx_commit = false;
6680 st_set_commit_all(xc);
6681 chk1(st_stop_xcon(c) == 0);
6682 chk1(st_wait_idle(c) == 0);
6683 chk1(st_verify_list(c) == 0);
6684 }
6685 return NDBT_OK;
6686 err:
6687 return NDBT_FAILED;
6688 }
6689
6690 static int
st_test_anf_background(ST_Con & c,int arg=-1)6691 st_test_anf_background(ST_Con& c, int arg = -1)
6692 {
6693 int i;
6694 chk1(st_start_xcon(c) == 0);
6695 {
6696 ST_Con& xc = *c.xcon;
6697 chk1(st_begin_trans(xc) == 0);
6698 for (i = 0; i < c.tabcount; i++) {
6699 ST_Tab& tab = c.tab(i);
6700 chk1(st_create_table(xc, tab) == 0);
6701 }
6702 // DICT takes over and completes the trans
6703 st_end_trans(xc, ST_BackgroundFlag);
6704 chk1(st_stop_xcon(c) == 0);
6705 chk1(st_wait_idle(c) == 0);
6706 chk1(st_verify_list(c) == 0);
6707 }
6708 return NDBT_OK;
6709 err:
6710 return NDBT_FAILED;
6711 }
6712
6713 static int
st_test_anf_fail_begin(ST_Con & c,int arg=-1)6714 st_test_anf_fail_begin(ST_Con& c, int arg = -1)
6715 {
6716 chk1(st_start_xcon(c) == 0);
6717 {
6718 ST_Con& xc = *c.xcon;
6719
6720 ST_Errins errins1(6102, -1, 1); // master kills us at begin
6721 ST_Errins errins2(6103, -1, 0); // slave delays conf
6722 chk1(st_do_errins(xc, errins1) == 0);
6723 chk1(st_do_errins(xc, errins2) == 0);
6724
6725 chk1(st_begin_trans(xc, 4009) == 0);
6726
6727 // DICT aborts the trans
6728 xc.tx_on = false;
6729 xc.tx_commit = false;
6730 st_set_commit_all(xc);
6731 chk1(st_stop_xcon(c) == 0);
6732
6733 // xc may get 4009 before takeover is ready (5000 ms delay)
6734 ST_Retry retry = { 100, 100 }; // 100 * 100ms = 10000ms
6735 chk1(st_begin_trans(c, retry) == 0);
6736 chk1(st_wait_idle(c) == 0);
6737 chk1(st_verify_list(c) == 0);
6738 }
6739 return NDBT_OK;
6740 err:
6741 return NDBT_FAILED;
6742 }
6743
6744 static int
st_test_snf_parse(ST_Con & c,int arg=-1)6745 st_test_snf_parse(ST_Con& c, int arg = -1)
6746 {
6747 bool do_abort = (arg == 1);
6748 chk1(st_begin_trans(c) == 0);
6749 int node_id;
6750 node_id = -1;
6751 int i;
6752 int midcount;
6753 midcount = c.tabcount / 2;
6754
6755 for (i = 0; i < c.tabcount; i++) {
6756 ST_Tab& tab = c.tab(i);
6757 if (i == midcount) {
6758 require(c.numdbnodes > 1);
6759 uint rand = urandom(c.numdbnodes);
6760 node_id = c.restarter->getRandomNotMasterNodeId(rand);
6761 g_info << "restart node " << node_id << " (async)" << endl;
6762 const int flags = NdbRestarter::NRRF_NOSTART;
6763 chk1(c.restarter->restartOneDbNode2(node_id, flags) == 0);
6764 chk1(c.restarter->waitNodesNoStart(&node_id, 1) == 0);
6765 chk1(c.restarter->startNodes(&node_id, 1) == 0);
6766 }
6767 chk1(st_create_table_index(c, tab) == 0);
6768 }
6769 if (!do_abort)
6770 chk1(st_end_trans(c, 0) == 0);
6771 else
6772 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6773
6774 g_info << "wait for node " << node_id << " to come up" << endl;
6775 chk1(c.restarter->waitClusterStarted() == 0);
6776 g_info << "verify all" << endl;
6777 chk1(st_verify_all(c) == 0);
6778 return NDBT_OK;
6779 err:
6780 return NDBT_FAILED;
6781 }
6782
6783 static int
st_test_mnf_parse(ST_Con & c,int arg=-1)6784 st_test_mnf_parse(ST_Con& c, int arg = -1)
6785 {
6786 const NdbDictionary::Table* pTab;
6787 bool do_abort = (arg == 1);
6788 chk1(st_begin_trans(c) == 0);
6789 int node_id;
6790 node_id = -1;
6791 int i;
6792 int midcount;
6793 midcount = c.tabcount / 2;
6794
6795 for (i = 0; i < c.tabcount; i++) {
6796 ST_Tab& tab = c.tab(i);
6797 chk1(st_create_table_index(c, tab) == 0);
6798 if (i == midcount) {
6799 require(c.numdbnodes > 1);
6800 node_id = c.restarter->getMasterNodeId();
6801 g_info << "restart node " << node_id << " (async)" << endl;
6802 const int flags = NdbRestarter::NRRF_NOSTART;
6803 chk1(c.restarter->restartOneDbNode2(node_id, flags) == 0);
6804 chk1(c.restarter->waitNodesNoStart(&node_id, 1) == 0);
6805 chk1(c.restarter->startNodes(&node_id, 1) == 0);
6806 break;
6807 }
6808 }
6809 if (!do_abort)
6810 chk1(st_end_trans_aborted(c, ST_CommitFlag) == 0);
6811 else
6812 chk1(st_end_trans_aborted(c, ST_AbortFlag) == 0);
6813
6814 g_info << "wait for node " << node_id << " to come up" << endl;
6815 chk1(c.restarter->waitClusterStarted() == 0);
6816 g_info << "verify all" << endl;
6817 for (i = 0; i < c.tabcount; i++) {
6818 ST_Tab& tab = c.tab(i);
6819 // Verify that table is not in db
6820 c.dic->invalidateTable(tab.name);
6821 pTab =
6822 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
6823 chk1(pTab == NULL);
6824 }
6825 /*
6826 chk1(st_verify_all(c) == 0);
6827 */
6828 return NDBT_OK;
6829 err:
6830 return NDBT_FAILED;
6831 }
6832
6833 static int
st_test_mnf_prepare(ST_Con & c,int arg=-1)6834 st_test_mnf_prepare(ST_Con& c, int arg = -1)
6835 {
6836 NdbRestarter restarter;
6837 //int master = restarter.getMasterNodeId();
6838 ST_Errins errins = st_get_errins(c, st_errins_end_trans1);
6839 int i;
6840
6841 chk1(st_begin_trans(c) == 0);
6842 for (i = 0; i < c.tabcount; i++) {
6843 ST_Tab& tab = c.tab(i);
6844 chk1(st_create_table_index(c, tab) == 0);
6845 }
6846 if (arg == 1)
6847 {
6848 chk1(st_end_trans_aborted(c, errins, ST_BackgroundFlag) == 0);
6849 chk1(st_wait_idle(c) == 0);
6850 }
6851 else
6852 chk1(st_end_trans_aborted(c, errins, ST_CommitFlag) == 0);
6853 chk1(c.restarter->waitClusterStarted() == 0);
6854 //st_wait_db_node_up(c, master);
6855 for (i = 0; i < c.tabcount; i++) {
6856 ST_Tab& tab = c.tab(i);
6857 // Verify that table is not in db
6858 c.dic->invalidateTable(tab.name);
6859 const NdbDictionary::Table* pTab =
6860 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
6861 chk1(pTab == NULL);
6862 }
6863 return NDBT_OK;
6864 err:
6865 return NDBT_FAILED;
6866 }
6867
6868 static int
st_test_mnf_commit1(ST_Con & c,int arg=-1)6869 st_test_mnf_commit1(ST_Con& c, int arg = -1)
6870 {
6871 NdbRestarter restarter;
6872 //int master = restarter.getMasterNodeId();
6873 ST_Errins errins = st_get_errins(c, st_errins_end_trans2);
6874 int i;
6875
6876 chk1(st_begin_trans(c) == 0);
6877 for (i = 0; i < c.tabcount; i++) {
6878 ST_Tab& tab = c.tab(i);
6879 chk1(st_create_table_index(c, tab) == 0);
6880 }
6881 if (arg == 1)
6882 {
6883 chk1(st_end_trans(c, errins, ST_BackgroundFlag) == 0);
6884 chk1(st_wait_idle(c) == 0);
6885 }
6886 else
6887 chk1(st_end_trans(c, errins, ST_CommitFlag) == 0);
6888 chk1(c.restarter->waitClusterStarted() == 0);
6889 //st_wait_db_node_up(c, master);
6890 for (i = 0; i < c.tabcount; i++) {
6891 ST_Tab& tab = c.tab(i);
6892 chk1(st_verify_table(c, tab) == 0);
6893 }
6894 chk1(st_drop_test_tables(c) == 0);
6895 return NDBT_OK;
6896 err:
6897 return NDBT_FAILED;
6898 }
6899
6900 static int
st_test_mnf_commit2(ST_Con & c,int arg=-1)6901 st_test_mnf_commit2(ST_Con& c, int arg = -1)
6902 {
6903 NdbRestarter restarter;
6904 //int master = restarter.getMasterNodeId();
6905 ST_Errins errins = st_get_errins(c, st_errins_end_trans3);
6906 int i;
6907
6908 chk1(st_begin_trans(c) == 0);
6909 for (i = 0; i < c.tabcount; i++) {
6910 ST_Tab& tab = c.tab(i);
6911 chk1(st_create_table_index(c, tab) == 0);
6912 }
6913 if (arg == 1)
6914 {
6915 chk1(st_end_trans(c, errins, ST_BackgroundFlag) == 0);
6916 chk1(st_wait_idle(c) == 0);
6917 }
6918 else
6919 chk1(st_end_trans(c, errins, ST_CommitFlag) == 0);
6920 chk1(c.restarter->waitClusterStarted() == 0);
6921 //st_wait_db_node_up(c, master);
6922 chk1(st_verify_all(c) == 0);
6923 for (i = 0; i < c.tabcount; i++) {
6924 ST_Tab& tab = c.tab(i);
6925 chk1(st_load_table(c, tab) == 0);
6926 }
6927 chk1(st_drop_test_tables(c) == 0);
6928 return NDBT_OK;
6929 err:
6930 return NDBT_FAILED;
6931 }
6932
6933 static int
st_test_mnf_run_commit(ST_Con & c,int arg=-1)6934 st_test_mnf_run_commit(ST_Con& c, int arg = -1)
6935 {
6936 const NdbDictionary::Table* pTab;
6937 NdbRestarter restarter;
6938 //int master = restarter.getMasterNodeId();
6939 int i;
6940
6941 if (arg == FAIL_BEGIN)
6942 {
6943 // No transaction to be found if only one node left
6944 if (restarter.getNumDbNodes() < 3)
6945 return NDBT_OK;
6946 chk1(st_begin_trans(c) == -1);
6947 goto verify;
6948 }
6949 else
6950 chk1(st_begin_trans(c) == 0);
6951 for (i = 0; i < c.tabcount; i++) {
6952 ST_Tab& tab = c.tab(i);
6953 if (arg == FAIL_CREATE)
6954 {
6955 chk1(st_create_table_index(c, tab) == -1);
6956 goto verify;
6957 }
6958 else
6959 chk1(st_create_table_index(c, tab) == 0);
6960 }
6961 if (arg == FAIL_END)
6962 {
6963 chk1(st_end_trans(c, ST_CommitFlag) == -1);
6964 }
6965 else // if (arg == SUCCEED_COMMIT)
6966 chk1(st_end_trans(c, ST_CommitFlag) == 0);
6967
6968 verify:
6969 g_info << "wait for master node to come up" << endl;
6970 chk1(c.restarter->waitClusterStarted() == 0);
6971 //st_wait_db_node_up(c, master);
6972 g_info << "verify all" << endl;
6973 for (i = 0; i < c.tabcount; i++) {
6974 ST_Tab& tab = c.tab(i);
6975 switch (arg) {
6976 case FAIL_BEGIN:
6977 case FAIL_CREATE:
6978 case FAIL_END:
6979 {
6980 // Verify that table is not in db
6981 c.dic->invalidateTable(tab.name);
6982 pTab =
6983 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
6984 chk1(pTab == NULL);
6985 break;
6986 }
6987 default:
6988 chk1(st_verify_table(c, tab) == 0);
6989 }
6990 }
6991
6992 return NDBT_OK;
6993 err:
6994 return NDBT_FAILED;
6995 }
6996
6997 static int
st_test_mnf_run_abort(ST_Con & c,int arg=-1)6998 st_test_mnf_run_abort(ST_Con& c, int arg = -1)
6999 {
7000 NdbRestarter restarter;
7001 //int master = restarter.getMasterNodeId();
7002 const NdbDictionary::Table* pTab;
7003 bool do_abort = (arg == SUCCEED_ABORT);
7004 int i;
7005
7006 chk1(st_begin_trans(c) == 0);
7007 for (i = 0; i < c.tabcount; i++) {
7008 ST_Tab& tab = c.tab(i);
7009 chk1(st_create_table_index(c, tab) == 0);
7010 }
7011 if (!do_abort)
7012 chk1(st_end_trans(c, ST_CommitFlag) == -1);
7013 else
7014 chk1(st_end_trans_aborted(c, ST_AbortFlag) == 0);
7015
7016 g_info << "wait for master node to come up" << endl;
7017 chk1(c.restarter->waitClusterStarted() == 0);
7018 //st_wait_db_node_up(c, master);
7019 g_info << "verify all" << endl;
7020 for (i = 0; i < c.tabcount; i++) {
7021 ST_Tab& tab = c.tab(i);
7022 // Verify that table is not in db
7023 c.dic->invalidateTable(tab.name);
7024 pTab =
7025 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
7026 chk1(pTab == NULL);
7027 }
7028
7029 return NDBT_OK;
7030 err:
7031 return NDBT_FAILED;
7032 }
7033
7034 static int
st_test_mnf_start_partial(ST_Con & c,int arg=-1)7035 st_test_mnf_start_partial(ST_Con& c, int arg = -1)
7036 {
7037 ST_Errins errins(ERR_INSERT_PARTIAL_START_FAIL, 0, 1); // slave skips start
7038 chk1(st_do_errins(c, errins) == 0);
7039 return st_test_mnf_run_commit(c, arg);
7040 err:
7041 return -1;
7042 }
7043
7044 static int
st_test_mnf_parse_partial(ST_Con & c,int arg=-1)7045 st_test_mnf_parse_partial(ST_Con& c, int arg = -1)
7046 {
7047 ST_Errins errins(ERR_INSERT_PARTIAL_PARSE_FAIL, 0, 1); // slave skips parse
7048 chk1(st_do_errins(c, errins) == 0);
7049 return st_test_mnf_run_commit(c, arg);
7050 err:
7051 return -1;
7052 }
7053
7054 static int
st_test_mnf_flush_prepare_partial(ST_Con & c,int arg=-1)7055 st_test_mnf_flush_prepare_partial(ST_Con& c, int arg = -1)
7056 {
7057 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_PREPARE_FAIL, 0, 1); // slave skips flush prepare
7058 chk1(st_do_errins(c, errins) == 0);
7059 return st_test_mnf_run_commit(c, arg);
7060 err:
7061 return -1;
7062 }
7063
7064 static int
st_test_mnf_prepare_partial(ST_Con & c,int arg=-1)7065 st_test_mnf_prepare_partial(ST_Con& c, int arg = -1)
7066 {
7067 ST_Errins errins(ERR_INSERT_PARTIAL_PREPARE_FAIL, 0, 1); // slave skips prepare
7068 chk1(st_do_errins(c, errins) == 0);
7069 return st_test_mnf_run_commit(c, arg);
7070 err:
7071 return -1;
7072 }
7073
7074 static int
st_test_mnf_abort_parse_partial(ST_Con & c,int arg=-1)7075 st_test_mnf_abort_parse_partial(ST_Con& c, int arg = -1)
7076 {
7077 ST_Errins errins(ERR_INSERT_PARTIAL_ABORT_PARSE_FAIL, 0, 1); // slave skips abort parse
7078 chk1(st_do_errins(c, errins) == 0);
7079 return st_test_mnf_run_abort(c, arg);
7080 err:
7081 return -1;
7082 }
7083
7084 static int
st_test_mnf_abort_prepare_partial(ST_Con & c,int arg=-1)7085 st_test_mnf_abort_prepare_partial(ST_Con& c, int arg = -1)
7086 {
7087 ST_Errins errins(ERR_INSERT_PARTIAL_ABORT_PREPARE_FAIL, 0, 1); // slave skips abort prepare
7088 chk1(st_do_errins(c, errins) == 0);
7089 return st_test_mnf_run_abort(c, arg);
7090 err:
7091 return -1;
7092 }
7093
7094 static int
st_test_mnf_flush_commit_partial(ST_Con & c,int arg=-1)7095 st_test_mnf_flush_commit_partial(ST_Con& c, int arg = -1)
7096 {
7097 NdbRestarter restarter;
7098 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_COMMIT_FAIL, 0, 1); // slave skips flush commit
7099 chk1(st_do_errins(c, errins) == 0);
7100 if (restarter.getNumDbNodes() < 3)
7101 // If new master is only node and it hasn't flush commit, we abort
7102 return st_test_mnf_run_commit(c, FAIL_END);
7103 else
7104 return st_test_mnf_run_commit(c, arg);
7105 err:
7106 return -1;
7107 }
7108
7109 static int
st_test_mnf_commit_partial(ST_Con & c,int arg=-1)7110 st_test_mnf_commit_partial(ST_Con& c, int arg = -1)
7111 {
7112 ST_Errins errins(ERR_INSERT_PARTIAL_COMMIT_FAIL, 0, 1); // slave skips commit
7113 chk1(st_do_errins(c, errins) == 0);
7114 return st_test_mnf_run_commit(c, arg);
7115 err:
7116 return -1;
7117 }
7118
7119 static int
st_test_mnf_flush_complete_partial(ST_Con & c,int arg=-1)7120 st_test_mnf_flush_complete_partial(ST_Con& c, int arg = -1)
7121 {
7122 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_COMPLETE_FAIL, 0, 1); // slave skips flush complete
7123 chk1(st_do_errins(c, errins) == 0);
7124 return st_test_mnf_run_commit(c, arg);
7125 err:
7126 return -1;
7127 }
7128
7129 static int
st_test_mnf_complete_partial(ST_Con & c,int arg=-1)7130 st_test_mnf_complete_partial(ST_Con& c, int arg = -1)
7131 {
7132 ST_Errins errins(ERR_INSERT_PARTIAL_COMPLETE_FAIL, 0, 1); // slave skips complete
7133 chk1(st_do_errins(c, errins) == 0);
7134 return st_test_mnf_run_commit(c, arg);
7135 err:
7136 return -1;
7137 }
7138
7139 static int
st_test_mnf_end_partial(ST_Con & c,int arg=-1)7140 st_test_mnf_end_partial(ST_Con& c, int arg = -1)
7141 {
7142 ST_Errins errins(ERR_INSERT_PARTIAL_END_FAIL, 0, 1); // slave skips end
7143 chk1(st_do_errins(c, errins) == 0);
7144 return st_test_mnf_run_commit(c, arg);
7145 err:
7146 return -1;
7147 }
7148
7149 static int
st_test_sr_parse(ST_Con & c,int arg=-1)7150 st_test_sr_parse(ST_Con& c, int arg = -1)
7151 {
7152 bool do_abort = (arg == 1);
7153 chk1(st_begin_trans(c) == 0);
7154 int i;
7155 for (i = 0; i < c.tabcount; i++) {
7156 ST_Tab& tab = c.tab(i);
7157 chk1(st_create_table_index(c, tab) == 0);
7158 }
7159 if (!do_abort)
7160 chk1(st_end_trans(c, 0) == 0);
7161 else
7162 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7163
7164 g_info << "restart all" << endl;
7165 int flags;
7166 flags = NdbRestarter::NRRF_NOSTART;
7167 chk1(c.restarter->restartAll2(flags) == 0);
7168 g_info << "wait for cluster started" << endl;
7169 chk1(c.restarter->waitClusterNoStart() == 0);
7170 chk1(c.restarter->startAll() == 0);
7171 chk1(c.restarter->waitClusterStarted() == 0);
7172 g_info << "verify all" << endl;
7173 chk1(st_verify_all(c) == 0);
7174 return NDBT_OK;
7175 err:
7176 return NDBT_FAILED;
7177 }
7178
7179 #if 0
7180 static int
7181 st_test_sr_commit(ST_Con& c, int arg = -1)
7182 {
7183 g_info << "not yet" << endl;
7184 return NDBT_OK;
7185 }
7186 #endif
7187
7188 // run test cases
7189
7190 struct ST_Test {
7191 const char* key;
7192 int mindbnodes;
7193 int arg;
7194 int (*func)(ST_Con& c, int arg);
7195 const char* name;
7196 const char* desc;
7197 };
7198
7199 static NdbOut&
operator <<(NdbOut & out,const ST_Test & test)7200 operator<<(NdbOut& out, const ST_Test& test)
7201 {
7202 out << "CASE " << test.key;
7203 out << " " << test.name;
7204 if (test.arg != -1)
7205 out << "+" << test.arg;
7206 out << " - " << test.desc;
7207 return out;
7208 }
7209
7210 static const ST_Test
7211 st_test_list[] = {
7212 #define func(f) f, #f
7213 // specific ops
7214 { "a1", 1, 0,
7215 func(st_test_create),
7216 "create all within trans, commit" },
7217 { "a2", 1, 1,
7218 func(st_test_create),
7219 "create all within trans, abort" },
7220 { "a3", 1, 0,
7221 func(st_test_drop),
7222 "drop all within trans, commit" },
7223 { "a4", 1, 1,
7224 func(st_test_drop),
7225 "drop all within trans, abort" },
7226 { "b1", 1, -1,
7227 func(st_test_rollback_create_table),
7228 "partial rollback of create table ops" },
7229 { "b2", 1, -1,
7230 func(st_test_rollback_drop_table),
7231 "partial rollback of drop table ops" },
7232 { "b3", 1, -1,
7233 func(st_test_rollback_create_index),
7234 "partial rollback of create index ops" },
7235 { "b4", 1, -1,
7236 func(st_test_rollback_drop_index),
7237 "partial rollback of drop index ops" },
7238 { "c1", 1, -1,
7239 func(st_test_dup_create_table),
7240 "try to create same table twice" },
7241 { "c2", 1, -1,
7242 func(st_test_dup_drop_table),
7243 "try to drop same table twice" },
7244 { "c3", 1, -1,
7245 func(st_test_dup_create_index),
7246 "try to create same index twice" },
7247 { "c4", 1, -1,
7248 func(st_test_dup_drop_index),
7249 "try to drop same index twice" },
7250 { "d1", 1, -1,
7251 func(st_test_build_index),
7252 "build index on non-empty table" },
7253 { "e1", 1, 0,
7254 func(st_test_local_create),
7255 "fail trigger create in TC, master errins 8033" },
7256 { "e2", 2, 1,
7257 func(st_test_local_create),
7258 "fail trigger create in TC, slave errins 8033" },
7259 { "e3", 1, 2,
7260 func(st_test_local_create),
7261 "fail trigger create in TUP, master errins 4003" },
7262 { "e4", 2, 3,
7263 func(st_test_local_create),
7264 "fail trigger create in TUP, slave errins 4003" },
7265 { "e5", 1, 4,
7266 func(st_test_local_create),
7267 "fail index create in TC, master errins 8034" },
7268 { "e6", 2, 5,
7269 func(st_test_local_create),
7270 "fail index create in TC, slave errins 8034" },
7271 // random ops
7272 { "o1", 1, 0,
7273 func(st_test_trans),
7274 "start and stop schema trans" },
7275 { "o2", 1, ST_AllowAbort,
7276 func(st_test_trans),
7277 "start and stop schema trans, allow abort" },
7278 { "o3", 1, ST_AllowAbort | ST_AllowErrins,
7279 func(st_test_trans),
7280 "start and stop schema trans, allow abort errins" },
7281 //
7282 { "p1", 1, 0,
7283 func(st_test_create_table),
7284 "create tables at random" },
7285 { "p2", 1, ST_AllowAbort,
7286 func(st_test_create_table),
7287 "create tables at random, allow abort" },
7288 { "p3", 1, ST_AllowAbort | ST_AllowErrins,
7289 func(st_test_create_table),
7290 "create tables at random, allow abort errins" },
7291 //
7292 { "p4", 1, 0,
7293 func(st_test_table),
7294 "create and drop tables at random" },
7295 { "p5", 1, ST_AllowAbort,
7296 func(st_test_table),
7297 "create and drop tables at random, allow abort" },
7298 { "p6", 1, ST_AllowAbort | ST_AllowErrins,
7299 func(st_test_table),
7300 "create and drop tables at random, allow abort errins" },
7301 //
7302 { "q1", 1, 0,
7303 func(st_test_create_index),
7304 "create indexes at random" },
7305 { "q2", 1, ST_AllowAbort,
7306 func(st_test_create_index),
7307 "create indexes at random, allow abort" },
7308 { "q3", 1, ST_AllowAbort | ST_AllowErrins,
7309 func(st_test_create_index),
7310 "create indexes at random, allow abort errins" },
7311 //
7312 { "q4", 1, 0,
7313 func(st_test_index),
7314 "create and drop indexes at random" },
7315 { "q5", 1, ST_AllowAbort,
7316 func(st_test_index),
7317 "create and drop indexes at random, allow abort" },
7318 { "q6", 1, ST_AllowAbort | ST_AllowErrins,
7319 func(st_test_index),
7320 "create and drop indexes at random, allow abort errins" },
7321 // node failure and system restart
7322 { "u1", 1, -1,
7323 func(st_test_anf_parse),
7324 "api node fail in parse phase" },
7325 { "u2", 1, -1,
7326 func(st_test_anf_background),
7327 "api node fail after background trans" },
7328 { "u3", 2, -1,
7329 func(st_test_anf_fail_begin),
7330 "api node fail in middle of kernel begin trans" },
7331 //
7332 { "v1", 2, 0,
7333 func(st_test_snf_parse),
7334 "slave node fail in parse phase, commit" },
7335 { "v2", 2, 1,
7336 func(st_test_snf_parse),
7337 "slave node fail in parse phase, abort" },
7338 { "w1", 1, 0,
7339 func(st_test_sr_parse),
7340 "system restart in parse phase, commit" },
7341 { "w2", 1, 1,
7342 func(st_test_sr_parse),
7343 "system restart in parse phase, abort" },
7344 #ifdef ndb_master_failure
7345 { "x1", 2, 0,
7346 func(st_test_mnf_parse),
7347 "master node fail in parse phase, commit" },
7348 { "x2", 2, 1,
7349 func(st_test_mnf_parse),
7350 "master node fail in parse phase, abort" },
7351 { "x3", 2, 0,
7352 func(st_test_mnf_prepare),
7353 "master node fail in prepare phase" },
7354 { "x4", 2, 0,
7355 func(st_test_mnf_commit1),
7356 "master node fail in start of commit phase" },
7357 { "x5", 2, 0,
7358 func(st_test_mnf_commit2),
7359 "master node fail in end of commit phase" },
7360 { "y1", 2, SUCCEED_COMMIT,
7361 func(st_test_mnf_start_partial),
7362 "master node fail in start phase, retry will succeed" },
7363 { "y2", 2, FAIL_CREATE,
7364 func(st_test_mnf_parse_partial),
7365 "master node fail in parse phase, partial rollback" },
7366 { "y3", 2, FAIL_END,
7367 func(st_test_mnf_flush_prepare_partial),
7368 "master node fail in flush prepare phase, partial rollback" },
7369 { "y4", 2, FAIL_END,
7370 func(st_test_mnf_prepare_partial),
7371 "master node fail in prepare phase, partial rollback" },
7372 { "y5", 2, SUCCEED_COMMIT,
7373 func(st_test_mnf_flush_commit_partial),
7374 "master node fail in flush commit phase, partial rollback" },
7375 { "y6", 2, SUCCEED_COMMIT,
7376 func(st_test_mnf_commit_partial),
7377 "master node fail in commit phase, commit, partial rollforward" },
7378 { "y7", 2, SUCCEED_COMMIT,
7379 func(st_test_mnf_flush_complete_partial),
7380 "master node fail in flush complete phase, commit, partial rollforward" },
7381 { "y8", 2, SUCCEED_COMMIT,
7382 func(st_test_mnf_complete_partial),
7383 "master node fail in complete phase, commit, partial rollforward" },
7384 { "y9", 2, SUCCEED_COMMIT,
7385 func(st_test_mnf_end_partial),
7386 "master node fail in end phase, commit, partial rollforward" },
7387 { "z1", 2, SUCCEED_ABORT,
7388 func(st_test_mnf_abort_parse_partial),
7389 "master node fail in abort parse phase, partial rollback" },
7390 { "z2", 2, FAIL_END,
7391 func(st_test_mnf_abort_prepare_partial),
7392 "master node fail in abort prepare phase, partial rollback" },
7393 { "z3", 2, 1,
7394 func(st_test_mnf_prepare),
7395 "master node fail in prepare phase in background" },
7396 { "z4", 2, 1,
7397 func(st_test_mnf_commit1),
7398 "master node fail in start of commit phase in background" },
7399 { "z5", 2, 1,
7400 func(st_test_mnf_commit2),
7401 "master node fail in end of commit phase in background" },
7402
7403 #endif
7404 #undef func
7405 };
7406
7407 static const int
7408 st_test_count = sizeof(st_test_list)/sizeof(st_test_list[0]);
7409
7410 static const char* st_test_case = 0;
7411 static const char* st_test_skip = 0;
7412
7413 static bool
st_test_match(const ST_Test & test)7414 st_test_match(const ST_Test& test)
7415 {
7416 const char* p = 0;
7417 if (st_test_case == 0)
7418 goto skip;
7419 if (strstr(st_test_case, test.key) != 0)
7420 goto skip;
7421 p = strchr(st_test_case, test.key[0]);
7422 if (p != 0 && (p[1] < '0' || p[1] > '9'))
7423 goto skip;
7424 return false;
7425 skip:
7426 if (st_test_skip == 0)
7427 return true;
7428 if (strstr(st_test_skip, test.key) != 0)
7429 return false;
7430 p = strchr(st_test_skip, test.key[0]);
7431 if (p != 0 && (p[1] < '0' || p[1] > '9'))
7432 return false;
7433 return true;
7434 }
7435
7436 static int
st_test(ST_Con & c,const ST_Test & test)7437 st_test(ST_Con& c, const ST_Test& test)
7438 {
7439 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7440 chk1(st_drop_test_tables(c) == 0);
7441 chk1(st_check_db_nodes(c) == 0);
7442
7443 g_err << test << endl;
7444 if (c.numdbnodes < test.mindbnodes) {
7445 g_err << "skip, too few db nodes" << endl;
7446 return NDBT_OK;
7447 }
7448
7449 chk1((*test.func)(c, test.arg) == NDBT_OK);
7450 chk1(st_check_db_nodes(c) == 0);
7451 //chk1(st_verify_list(c) == 0);
7452
7453 return NDBT_OK;
7454 err:
7455 return NDBT_FAILED;
7456 }
7457
7458 static int st_random_seed = -1;
7459
7460 int
runSchemaTrans(NDBT_Context * ctx,NDBT_Step * step)7461 runSchemaTrans(NDBT_Context* ctx, NDBT_Step* step)
7462 {
7463 #ifdef NDB_USE_GET_ENV
7464 { const char* env = NdbEnv_GetEnv("NDB_TEST_DBUG", 0, 0);
7465 if (env != 0 && env[0] != 0) // e.g. d:t:L:F:o,ndb_test.log
7466 DBUG_PUSH(env);
7467 }
7468 { const char* env = NdbEnv_GetEnv("NDB_TEST_CORE", 0, 0);
7469 if (env != 0 && env[0] != 0 && env[0] != '0' && env[0] != 'N')
7470 st_core_on_err = true;
7471 }
7472 { const char* env = NdbEnv_GetEnv("NDB_TEST_CASE", 0, 0);
7473 st_test_case = env;
7474 }
7475 { const char* env = NdbEnv_GetEnv("NDB_TEST_SKIP", 0, 0);
7476 st_test_skip = env;
7477 }
7478 { const char* env = NdbEnv_GetEnv("NDB_TEST_SEED", 0, 0);
7479 if (env != 0)
7480 st_random_seed = atoi(env);
7481 }
7482 #endif
7483 if (st_test_case != 0 && strcmp(st_test_case, "?") == 0) {
7484 int i;
7485 ndbout << "case func+arg desc" << endl;
7486 for (i = 0; i < st_test_count; i++) {
7487 const ST_Test& test = st_test_list[i];
7488 ndbout << test << endl;
7489 }
7490 return NDBT_WRONGARGS;
7491 }
7492
7493 if (st_random_seed == -1)
7494 st_random_seed = (short)getpid();
7495 if (st_random_seed != 0) {
7496 g_err << "random seed: " << st_random_seed << endl;
7497 ndb_srand(st_random_seed);
7498 } else {
7499 g_err << "random seed: loop number" << endl;
7500 }
7501
7502 Ndb_cluster_connection* ncc = &ctx->m_cluster_connection;
7503 Ndb* ndb = GETNDB(step);
7504 ST_Restarter* restarter = new ST_Restarter;
7505 ST_Con c(ncc, ndb, restarter);
7506
7507 chk1(st_drop_all_tables(c) == 0);
7508 st_init_objects(c, ctx);
7509
7510 int numloops;
7511 numloops = ctx->getNumLoops();
7512
7513 for (c.loop = 0; numloops == 0 || c.loop < numloops; c.loop++) {
7514 g_err << "LOOP " << c.loop << endl;
7515 if (st_random_seed == 0)
7516 ndb_srand(c.loop);
7517 int i;
7518 for (i = 0; i < st_test_count; i++) {
7519 const ST_Test& test = st_test_list[i];
7520 if (st_test_match(test)) {
7521 chk1(st_test(c, test) == NDBT_OK);
7522 }
7523 }
7524 }
7525
7526 st_report_db_nodes(c, g_err);
7527 return NDBT_OK;
7528 err:
7529 st_report_db_nodes(c, g_err);
7530 return NDBT_FAILED;
7531 }
7532
7533 // end schema trans
7534
7535 int
runFailCreateHashmap(NDBT_Context * ctx,NDBT_Step * step)7536 runFailCreateHashmap(NDBT_Context* ctx, NDBT_Step* step)
7537 {
7538 static int lst[] = { 6204, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 0 };
7539
7540 NdbRestarter restarter;
7541 int nodeId = restarter.getMasterNodeId();
7542 Ndb* pNdb = GETNDB(step);
7543 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7544
7545 int errNo = 0;
7546 #ifdef NDB_USE_GET_ENV
7547 char buf[100];
7548 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
7549 {
7550 errNo = atoi(buf);
7551 ndbout_c("Using errno: %u", errNo);
7552 }
7553 #endif
7554 const int loops = ctx->getNumLoops();
7555 int result = NDBT_OK;
7556
7557 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
7558 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
7559
7560 NdbDictionary::HashMap hm;
7561 pDic->initDefaultHashMap(hm, 1);
7562
7563 loop:
7564 if (pDic->getHashMap(hm, hm.getName()) != -1)
7565 {
7566 pDic->initDefaultHashMap(hm, rand() % 64);
7567 goto loop;
7568 }
7569
7570 for (int l = 0; l < loops; l++)
7571 {
7572 for (unsigned i0 = 0; lst[i0]; i0++)
7573 {
7574 unsigned j = (l == 0 ? i0 : myRandom48(i0 + l));
7575 int errval = lst[j];
7576 if (errNo != 0 && errNo != errval)
7577 continue;
7578 g_info << "insert error node=" << nodeId << " value=" << errval << endl;
7579 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
7580 "failed to set error insert");
7581 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
7582
7583 int res = pDic->createHashMap(hm);
7584 CHECK2(res != 0, "create hashmap failed to fail");
7585
7586 NdbDictionary::HashMap check;
7587 CHECK2(res != 0, "create hashmap existed");
7588
7589 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
7590 "failed to clear error insert");
7591 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
7592 }
7593 }
7594 end:
7595 return result;
7596 }
7597 // end FAIL create hashmap
7598
7599 int
runCreateHashmaps(NDBT_Context * ctx,NDBT_Step * step)7600 runCreateHashmaps(NDBT_Context* ctx, NDBT_Step* step)
7601 {
7602 NdbRestarter restarter;
7603 // int nodeId = restarter.getMasterNodeId();
7604 Ndb* pNdb = GETNDB(step);
7605 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7606
7607 const int loops = ctx->getNumLoops();
7608 int result = NDBT_OK;
7609
7610 NdbDictionary::HashMap hm;
7611
7612 int created = 0;
7613 for (int i = 1; i <= NDB_DEFAULT_HASHMAP_BUCKETS && created < loops ; i++)
7614 {
7615 pDic->initDefaultHashMap(hm, i);
7616 int res = pDic->getHashMap(hm, hm.getName());
7617 if (res == -1)
7618 {
7619 const NdbError err = pDic->getNdbError();
7620 if (err.code != 723)
7621 {
7622 g_err << "getHashMap: " << hm.getName() << ": " << err << endl;
7623 result = NDBT_FAILED;
7624 break;
7625 }
7626 int res = pDic->createHashMap(hm);
7627 if (res == -1)
7628 {
7629 const NdbError err = pDic->getNdbError();
7630 if (err.code != 707 && err.code != 712)
7631 {
7632 g_err << "createHashMap: " << hm.getName() << ": " << err << endl;
7633 result = NDBT_FAILED;
7634 }
7635 break;
7636 }
7637 created++;
7638 }
7639 }
7640
7641 // Drop all hashmaps (and everything else) with initial restart
7642 ndbout << "Restarting cluster" << endl;
7643 restarter.restartAll(/* initial */ true);
7644 restarter.waitClusterStarted();
7645
7646 return result;
7647 }
7648 // end FAIL create hashmap
7649
7650 int
runFailAddPartition(NDBT_Context * ctx,NDBT_Step * step)7651 runFailAddPartition(NDBT_Context* ctx, NDBT_Step* step)
7652 {
7653 static int lst[] = { 7211, 7212, 4050, 12008, 6212, 6124, 6213, 6214, 0 };
7654
7655 Ndb* pNdb = GETNDB(step);
7656 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7657 NdbDictionary::Table tab(*ctx->getTab());
7658 NdbRestarter restarter;
7659 int nodeId = restarter.getMasterNodeId();
7660
7661 int errNo = 0;
7662 #ifdef NDB_USE_GET_ENV
7663 char buf[100];
7664 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
7665 {
7666 errNo = atoi(buf);
7667 ndbout_c("Using errno: %u", errNo);
7668 }
7669 #endif
7670 // ordered index on first few columns
7671 NdbDictionary::Index idx("X");
7672 idx.setTable(tab.getName());
7673 idx.setType(NdbDictionary::Index::OrderedIndex);
7674 idx.setLogging(false);
7675 for (int cnt = 0, i_hate_broken_compilers = 0;
7676 cnt < 3 &&
7677 i_hate_broken_compilers < tab.getNoOfColumns();
7678 i_hate_broken_compilers++) {
7679 if (NdbSqlUtil::check_column_for_ordered_index
7680 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
7681 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
7682 NdbDictionary::Column::StorageTypeDisk)
7683 {
7684 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
7685 cnt++;
7686 }
7687 }
7688
7689 for (int i = 0; i<tab.getNoOfColumns(); i++)
7690 {
7691 if (tab.getColumn(i)->getStorageType() ==
7692 NdbDictionary::Column::StorageTypeDisk)
7693 {
7694 NDBT_Tables::create_default_tablespace(pNdb);
7695 break;
7696 }
7697 }
7698
7699 const int loops = ctx->getNumLoops();
7700 int result = NDBT_OK;
7701 (void)pDic->dropTable(tab.getName());
7702 if (pDic->createTable(tab) != 0)
7703 {
7704 ndbout << "FAIL: " << pDic->getNdbError() << endl;
7705 return NDBT_FAILED;
7706 }
7707
7708 if (pDic->createIndex(idx) != 0)
7709 {
7710 ndbout << "FAIL: " << pDic->getNdbError() << endl;
7711 return NDBT_FAILED;
7712 }
7713
7714 const NdbDictionary::Table * org = pDic->getTable(tab.getName());
7715 NdbDictionary::Table altered = * org;
7716 altered.setFragmentCount(org->getFragmentCount() +
7717 restarter.getNumDbNodes());
7718
7719 if (pDic->beginSchemaTrans())
7720 {
7721 ndbout << "Failed to beginSchemaTrans()" << pDic->getNdbError() << endl;
7722 return NDBT_FAILED;
7723 }
7724
7725 if (pDic->prepareHashMap(*org, altered) == -1)
7726 {
7727 ndbout << "Failed to create hashmap: " << pDic->getNdbError() << endl;
7728 return NDBT_FAILED;
7729 }
7730
7731 if (pDic->endSchemaTrans())
7732 {
7733 ndbout << "Failed to endSchemaTrans()" << pDic->getNdbError() << endl;
7734 return NDBT_FAILED;
7735 }
7736
7737 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
7738 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
7739
7740 for (int l = 0; l < loops; l++)
7741 {
7742 for (unsigned i0 = 0; lst[i0]; i0++)
7743 {
7744 unsigned j = (l == 0 ? i0 : myRandom48(sizeof(lst)/sizeof(lst[0]) - 1));
7745 int errval = lst[j];
7746 if (errNo != 0 && errNo != errval)
7747 continue;
7748 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
7749 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
7750 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
7751 "failed to set error insert");
7752
7753 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
7754
7755 int res = pDic->alterTable(*org, altered);
7756 if (res)
7757 {
7758 ndbout << pDic->getNdbError() << endl;
7759 }
7760 CHECK2(res != 0,
7761 "failed to fail after error insert " << errval);
7762 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
7763 "failed to clear error insert");
7764 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
7765 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
7766
7767 int dump3[] = {DumpStateOrd::DihAddFragFailCleanedUp, org->getTableId()};
7768 CHECK(restarter.dumpStateAllNodes(dump3, 2) == 0);
7769
7770 const NdbDictionary::Table* check = pDic->getTable(tab.getName());
7771
7772 CHECK2((check->getObjectId() == org->getObjectId() &&
7773 check->getObjectVersion() == org->getObjectVersion()),
7774 "table has been altered!");
7775 }
7776 }
7777
7778 end:
7779 (void)pDic->dropTable(tab.getName());
7780 return result;
7781 }
7782 // fail add partition
7783
7784 int
runTableAddPartition(NDBT_Context * ctx,NDBT_Step * step)7785 runTableAddPartition(NDBT_Context* ctx, NDBT_Step* step){
7786
7787 int result = NDBT_OK;
7788
7789 Ndb* pNdb = GETNDB(step);
7790 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
7791 int records = ctx->getNumRecords();
7792 const int loops = ctx->getNumLoops();
7793
7794 ndbout << "|- " << ctx->getTab()->getName() << endl;
7795
7796 NdbDictionary::Table myTab= *(ctx->getTab());
7797 myTab.setFragmentType(NdbDictionary::Object::HashMapPartition);
7798
7799 for (int l = 0; l < loops && result == NDBT_OK ; l++)
7800 {
7801 // Try to create table in db
7802 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
7803 return NDBT_FAILED;
7804 }
7805
7806 // Verify that table is in db
7807 const NdbDictionary::Table* pTab2 =
7808 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
7809 if (pTab2 == NULL){
7810 ndbout << myTab.getName() << " was not found in DB"<< endl;
7811 return NDBT_FAILED;
7812 }
7813 ctx->setTab(pTab2);
7814
7815 #if 1
7816 // Load table
7817 const NdbDictionary::Table* pTab;
7818 CHECK((pTab = ctx->getTab()) != NULL);
7819 HugoTransactions beforeTrans(*pTab);
7820 if (beforeTrans.loadTable(pNdb, records) != 0){
7821 return NDBT_FAILED;
7822 }
7823 #endif
7824
7825 // Add attributes to table.
7826 BaseString pTabName(pTab2->getName());
7827 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
7828
7829 NdbDictionary::Table newTable= *oldTable;
7830
7831 newTable.setFragmentCount(2 * oldTable->getFragmentCount());
7832 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
7833 "TableAddAttrs failed");
7834
7835 /* Need to purge old version and reload new version after alter table. */
7836 dict->invalidateTable(pTabName.c_str());
7837
7838 #if 0
7839 {
7840 HugoTransactions afterTrans(* dict->getTable(pTabName.c_str()));
7841
7842 ndbout << "delete...";
7843 if (afterTrans.clearTable(pNdb) != 0)
7844 {
7845 return NDBT_FAILED;
7846 }
7847 ndbout << endl;
7848
7849 ndbout << "insert...";
7850 if (afterTrans.loadTable(pNdb, records) != 0){
7851 return NDBT_FAILED;
7852 }
7853 ndbout << endl;
7854
7855 ndbout << "update...";
7856 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
7857 {
7858 return NDBT_FAILED;
7859 }
7860 ndbout << endl;
7861
7862 ndbout << "delete...";
7863 if (afterTrans.clearTable(pNdb) != 0)
7864 {
7865 return NDBT_FAILED;
7866 }
7867 ndbout << endl;
7868 }
7869 #endif
7870 abort();
7871 // Drop table.
7872 dict->dropTable(pTabName.c_str());
7873 }
7874 end:
7875
7876 return result;
7877 }
7878
7879 int
runBug41905(NDBT_Context * ctx,NDBT_Step * step)7880 runBug41905(NDBT_Context* ctx, NDBT_Step* step)
7881 {
7882 const NdbDictionary::Table* pTab = ctx->getTab();
7883 BaseString tabName(pTab->getName());
7884 Ndb* pNdb = GETNDB(step);
7885 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7886
7887 NdbDictionary::Table creTab = *pTab;
7888 creTab.setForceVarPart(true);
7889 int ret = NDBT_OK;
7890
7891 (void)pDic->dropTable(tabName.c_str());
7892 if (pDic->createTable(creTab)) {
7893 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7894 ret = NDBT_FAILED;
7895 }
7896
7897 Uint32 cols = creTab.getNoOfColumns();
7898 Uint32 vers = 0;
7899 while (ret == NDBT_OK) {
7900 const NdbDictionary::Table* pOldTab = pDic->getTableGlobal(tabName.c_str());
7901 require(pOldTab != 0);
7902
7903 const Uint32 old_st = pOldTab->getObjectStatus();
7904 const Uint32 old_cols = pOldTab->getNoOfColumns();
7905 const Uint32 old_vers = pOldTab->getObjectVersion() >> 24;
7906
7907 if (old_st != NdbDictionary::Object::Retrieved) {
7908 g_err << __LINE__ << ": " << "got status " << old_st << endl;
7909 ret = NDBT_FAILED;
7910 break;
7911 }
7912 // bug#41905 or related: other thread causes us to get old version
7913 if (old_cols != cols || old_vers != vers) {
7914 g_err << __LINE__ << ": "
7915 << "got cols,vers " << old_cols << "," << old_vers
7916 << " expected " << cols << "," << vers << endl;
7917 ret = NDBT_FAILED;
7918 break;
7919 }
7920 if (old_cols >= 100)
7921 break;
7922 const NdbDictionary::Table& oldTab = *pOldTab;
7923
7924 NdbDictionary::Table newTab = oldTab;
7925 char colName[100];
7926 sprintf(colName, "COL41905_%02d", cols);
7927 g_info << "add " << colName << endl;
7928 NDBT_Attribute newCol(colName, NdbDictionary::Column::Unsigned, 1,
7929 false, true, (CHARSET_INFO*)0,
7930 NdbDictionary::Column::StorageTypeMemory, true);
7931 newTab.addColumn(newCol);
7932
7933 ctx->setProperty("Bug41905", 1);
7934 NdbSleep_MilliSleep(10);
7935
7936 const bool removeEarly = (uint)rand() % 2;
7937 g_info << "removeEarly = " << removeEarly << endl;
7938
7939 if (pDic->beginSchemaTrans() != 0) {
7940 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7941 ret = NDBT_FAILED;
7942 break;
7943 }
7944 if (pDic->alterTable(oldTab, newTab) != 0) {
7945 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7946 ret = NDBT_FAILED;
7947 break;
7948 }
7949
7950 if (removeEarly)
7951 pDic->removeTableGlobal(*pOldTab, 0);
7952
7953 if (pDic->endSchemaTrans() != 0) {
7954 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
7955 ret = NDBT_FAILED;
7956 break;
7957 }
7958
7959 cols++;
7960 vers++;
7961 if (!removeEarly)
7962 pDic->removeTableGlobal(*pOldTab, 0);
7963 ctx->setProperty("Bug41905", 2);
7964 NdbSleep_MilliSleep(10);
7965 }
7966
7967 ctx->setProperty("Bug41905", 3);
7968 return ret;
7969 }
7970
7971 int
runBug41905getTable(NDBT_Context * ctx,NDBT_Step * step)7972 runBug41905getTable(NDBT_Context* ctx, NDBT_Step* step)
7973 {
7974 const NdbDictionary::Table* pTab = ctx->getTab();
7975 BaseString tabName(pTab->getName());
7976 Ndb* pNdb = GETNDB(step);
7977 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
7978
7979 while (1) {
7980 while (1) {
7981 if (ctx->getProperty("Bug41905") == 1)
7982 break;
7983 if (ctx->getProperty("Bug41905") == 3)
7984 goto out;
7985 NdbSleep_MilliSleep(10);
7986 }
7987
7988 uint ms = (uint)rand() % 1000;
7989 NdbSleep_MilliSleep(ms);
7990 g_info << "get begin ms=" << ms << endl;
7991
7992 Uint32 count = 0;
7993 Uint32 oldstatus = 0;
7994 while (1) {
7995 count++;
7996 const NdbDictionary::Table* pTmp = pDic->getTableGlobal(tabName.c_str());
7997 require(pTmp != 0);
7998 Uint32 code = pDic->getNdbError().code;
7999 Uint32 status = pTmp->getObjectStatus();
8000 if (oldstatus == 2 && status == 3)
8001 g_info << "code=" << code << " status=" << status << endl;
8002 oldstatus = status;
8003 pDic->removeTableGlobal(*pTmp, 0);
8004 if (ctx->getProperty("Bug41905") != 1)
8005 break;
8006 NdbSleep_MilliSleep(10);
8007 }
8008 g_info << "get end count=" << count << endl;
8009 }
8010
8011 out:
8012 (void)pDic->dropTable(tabName.c_str());
8013 return NDBT_OK;
8014 }
8015
8016 static
8017 int
createIndexes(NdbDictionary::Dictionary * pDic,const NdbDictionary::Table & tab,int cnt)8018 createIndexes(NdbDictionary::Dictionary* pDic,
8019 const NdbDictionary::Table & tab, int cnt)
8020 {
8021 for (int i = 0; i<cnt && i < tab.getNoOfColumns(); i++)
8022 {
8023 char buf[256];
8024 NdbDictionary::Index idx0;
8025 BaseString::snprintf(buf, sizeof(buf), "%s-idx-%u", tab.getName(), i);
8026 idx0.setName(buf);
8027 idx0.setType(NdbDictionary::Index::OrderedIndex);
8028 idx0.setTable(tab.getName());
8029 idx0.setStoredIndex(false);
8030 idx0.addIndexColumn(tab.getColumn(i)->getName());
8031
8032 if (pDic->createIndex(idx0))
8033 {
8034 ndbout << pDic->getNdbError() << endl;
8035 return NDBT_FAILED;
8036 }
8037 }
8038
8039 return 0;
8040 }
8041
8042 int
runBug46552(NDBT_Context * ctx,NDBT_Step * step)8043 runBug46552(NDBT_Context* ctx, NDBT_Step* step)
8044 {
8045 Ndb* pNdb = GETNDB(step);
8046 const NdbDictionary::Table* pTab = ctx->getTab();
8047 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8048
8049 NdbRestarter res;
8050 if (res.getNumDbNodes() < 2)
8051 return NDBT_OK;
8052
8053 NdbDictionary::Table tab0 = *pTab;
8054 NdbDictionary::Table tab1 = *pTab;
8055
8056 BaseString name;
8057 name.assfmt("%s_0", tab0.getName());
8058 tab0.setName(name.c_str());
8059 name.assfmt("%s_1", tab1.getName());
8060 tab1.setName(name.c_str());
8061
8062 pDic->dropTable(tab0.getName());
8063 pDic->dropTable(tab1.getName());
8064
8065 if (pDic->createTable(tab0))
8066 {
8067 ndbout << pDic->getNdbError() << endl;
8068 return NDBT_FAILED;
8069 }
8070
8071 if (pDic->createTable(tab1))
8072 {
8073 ndbout << pDic->getNdbError() << endl;
8074 return NDBT_FAILED;
8075 }
8076
8077 if (createIndexes(pDic, tab1, 4))
8078 return NDBT_FAILED;
8079
8080 Vector<int> group1;
8081 Vector<int> group2;
8082 Bitmask<256/32> nodeGroupMap;
8083 for (int j = 0; j<res.getNumDbNodes(); j++)
8084 {
8085 int node = res.getDbNodeId(j);
8086 int ng = res.getNodeGroup(node);
8087 if (nodeGroupMap.get(ng))
8088 {
8089 group2.push_back(node);
8090 }
8091 else
8092 {
8093 group1.push_back(node);
8094 nodeGroupMap.set(ng);
8095 }
8096 }
8097
8098 res.restartNodes(group1.getBase(), (int)group1.size(),
8099 NdbRestarter::NRRF_NOSTART |
8100 NdbRestarter::NRRF_ABORT);
8101
8102 res.waitNodesNoStart(group1.getBase(), (int)group1.size());
8103 res.startNodes(group1.getBase(), (int)group1.size());
8104 res.waitClusterStarted();
8105
8106 res.restartNodes(group2.getBase(), (int)group2.size(),
8107 NdbRestarter::NRRF_NOSTART |
8108 NdbRestarter::NRRF_ABORT);
8109 res.waitNodesNoStart(group2.getBase(), (int)group2.size());
8110 res.startNodes(group2.getBase(), (int)group2.size());
8111 res.waitClusterStarted();
8112
8113 if (pDic->dropTable(tab0.getName()))
8114 {
8115 ndbout << pDic->getNdbError() << endl;
8116 return NDBT_FAILED;
8117 }
8118
8119 if (pDic->createTable(tab0))
8120 {
8121 ndbout << pDic->getNdbError() << endl;
8122 return NDBT_FAILED;
8123 }
8124
8125 if (createIndexes(pDic, tab0, 4))
8126 return NDBT_FAILED;
8127
8128 res.restartAll2(NdbRestarter::NRRF_NOSTART | NdbRestarter::NRRF_ABORT);
8129 res.waitClusterNoStart();
8130 res.startAll();
8131 res.waitClusterStarted();
8132
8133 if (pDic->dropTable(tab0.getName()))
8134 {
8135 ndbout << pDic->getNdbError() << endl;
8136 return NDBT_FAILED;
8137 }
8138
8139 if (pDic->dropTable(tab1.getName()))
8140 {
8141 ndbout << pDic->getNdbError() << endl;
8142 return NDBT_FAILED;
8143 }
8144
8145 return NDBT_OK;
8146 }
8147
8148 int
runBug46585(NDBT_Context * ctx,NDBT_Step * step)8149 runBug46585(NDBT_Context* ctx, NDBT_Step* step)
8150 {
8151 Ndb* pNdb = GETNDB(step);
8152 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8153 NdbDictionary::Table tab(*ctx->getTab());
8154 NdbRestarter res;
8155 int records = ctx->getNumRecords();
8156
8157 // ordered index on first few columns
8158 NdbDictionary::Index idx("X");
8159 idx.setTable(tab.getName());
8160 idx.setType(NdbDictionary::Index::OrderedIndex);
8161 idx.setLogging(false);
8162 for (int cnt = 0, i_hate_broken_compilers = 0;
8163 cnt < 3 &&
8164 i_hate_broken_compilers < tab.getNoOfColumns();
8165 i_hate_broken_compilers++) {
8166 if (NdbSqlUtil::check_column_for_ordered_index
8167 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
8168 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
8169 NdbDictionary::Column::StorageTypeDisk)
8170 {
8171 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
8172 cnt++;
8173 }
8174 }
8175
8176 for (int i = 0; i<tab.getNoOfColumns(); i++)
8177 {
8178 if (tab.getColumn(i)->getStorageType() ==
8179 NdbDictionary::Column::StorageTypeDisk)
8180 {
8181 NDBT_Tables::create_default_tablespace(pNdb);
8182 break;
8183 }
8184 }
8185
8186 const int loops = ctx->getNumLoops();
8187 int result = NDBT_OK;
8188 (void)pDic->dropTable(tab.getName());
8189 if (pDic->createTable(tab) != 0)
8190 {
8191 ndbout << "FAIL: " << pDic->getNdbError() << endl;
8192 return NDBT_FAILED;
8193 }
8194
8195 if (pDic->createIndex(idx) != 0)
8196 {
8197 ndbout << "FAIL: " << pDic->getNdbError() << endl;
8198 return NDBT_FAILED;
8199 }
8200
8201 for (int i = 0; i<loops; i++)
8202 {
8203 const NdbDictionary::Table * org = pDic->getTable(tab.getName());
8204 {
8205 CHECK(org != NULL);
8206 HugoTransactions trans(* org);
8207 CHECK2(trans.loadTable(pNdb, records) == 0,
8208 "load table failed");
8209 }
8210
8211 NdbDictionary::Table altered = * org;
8212 altered.setFragmentCount(org->getFragmentCount() + 1);
8213 ndbout_c("alter from %u to %u partitions",
8214 org->getFragmentCount(),
8215 altered.getFragmentCount());
8216
8217 if (pDic->beginSchemaTrans())
8218 {
8219 ndbout << "Failed to beginSchemaTrans()" << pDic->getNdbError() << endl;
8220 return NDBT_FAILED;
8221 }
8222
8223 if (pDic->prepareHashMap(*org, altered) == -1)
8224 {
8225 ndbout << "Failed to create hashmap: " << pDic->getNdbError() << endl;
8226 return NDBT_FAILED;
8227 }
8228
8229 if (pDic->endSchemaTrans())
8230 {
8231 ndbout << "Failed to endSchemaTrans()" << pDic->getNdbError() << endl;
8232 return NDBT_FAILED;
8233 }
8234
8235 result = pDic->alterTable(*org, altered);
8236 if (result)
8237 {
8238 ndbout << pDic->getNdbError() << endl;
8239 }
8240 if (pDic->getNdbError().code == 1224)
8241 {
8242 /**
8243 * To many fragments is an acceptable error
8244 * depending on configuration used for test-case
8245 */
8246 result = NDBT_OK;
8247 goto end;
8248 }
8249 CHECK2(result == 0,
8250 "failed to alter");
8251
8252 pDic->invalidateTable(tab.getName());
8253 {
8254 const NdbDictionary::Table * alteredP = pDic->getTable(tab.getName());
8255 CHECK2(alteredP->getFragmentCount() == altered.getFragmentCount(),
8256 "altered table does not have correct frag count");
8257
8258 HugoTransactions trans(* alteredP);
8259
8260 CHECK2(trans.scanUpdateRecords(pNdb, records) == 0,
8261 "scan update failed");
8262 trans.startTransaction(pNdb);
8263 trans.pkUpdateRecord(pNdb, 0);
8264 trans.execute_Commit(pNdb);
8265 ndbout_c("before restart, gci: %d", trans.getRecordGci(0));
8266 trans.closeTransaction(pNdb);
8267 }
8268
8269 switch(i % 2){
8270 case 0:
8271 if (res.getNumDbNodes() > 1)
8272 {
8273 int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
8274 ndbout_c("performing node-restart of node %d", nodeId);
8275 CHECK2(res.restartOneDbNode(nodeId,
8276 false,
8277 true,
8278 true) == 0,
8279 "restart one node failed");
8280 CHECK2(res.waitNodesNoStart(&nodeId, 1) == 0,
8281 "wait node started failed");
8282 CHECK2(res.startNodes(&nodeId, 1) == 0,
8283 "start node failed");
8284 break;
8285 }
8286 case 1:
8287 {
8288 ndbout_c("performing system restart");
8289 CHECK2(res.restartAll(false, true, false) == 0,
8290 "restart all failed");
8291 CHECK2(res.waitClusterNoStart() == 0,
8292 "waitClusterNoStart failed");
8293 CHECK2(res.startAll() == 0,
8294 "startAll failed");
8295 break;
8296 }
8297 }
8298 CHECK2(res.waitClusterStarted() == 0,
8299 "wait cluster started failed");
8300
8301 Uint32 restartGCI = 0;
8302 CHECK2(pDic->getRestartGCI(&restartGCI) == 0,
8303 "getRestartGCI failed");
8304 ndbout_c("restartGCI: %u", restartGCI);
8305
8306 pDic->invalidateTable(tab.getName());
8307 {
8308 const NdbDictionary::Table * alteredP = pDic->getTable(tab.getName());
8309 CHECK(alteredP != NULL);
8310 HugoTransactions trans(* alteredP);
8311
8312 int cnt;
8313 CHECK2(trans.selectCount(pNdb, 0, &cnt) == 0,
8314 "select count failed");
8315
8316 CHECK2(cnt == records,
8317 "table does not have correct record count: "
8318 << cnt << " != " << records);
8319
8320 CHECK2(alteredP->getFragmentCount() == altered.getFragmentCount(),
8321 "altered table does not have correct frag count");
8322
8323 CHECK2(trans.scanUpdateRecords(pNdb, records) == 0,
8324 "scan update failed");
8325 CHECK2(trans.pkUpdateRecords(pNdb, records) == 0,
8326 "pkUpdateRecords failed");
8327 CHECK2(trans.clearTable(pNdb) == 0,
8328 "clear table failed");
8329 }
8330 }
8331
8332 end:
8333 (void)pDic->dropTable(tab.getName());
8334 return result;
8335 }
8336
8337 int
runBug53944(NDBT_Context * ctx,NDBT_Step * step)8338 runBug53944(NDBT_Context* ctx, NDBT_Step* step)
8339 {
8340 Ndb* pNdb = GETNDB(step);
8341 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8342 NdbDictionary::Table tab(*ctx->getTab());
8343 NdbRestarter res;
8344
8345 Vector<int> ids;
8346 for (unsigned i = 0; i< 25; i++)
8347 {
8348 NdbDictionary::Table copy = tab;
8349 BaseString name;
8350 name.appfmt("%s_%u", copy.getName(), i);
8351 copy.setName(name.c_str());
8352 int res = pDic->createTable(copy);
8353 if (res)
8354 {
8355 g_err << "Failed to create table" << copy.getName() << "\n"
8356 << pDic->getNdbError() << endl;
8357 return NDBT_FAILED;
8358 }
8359 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
8360 if (tab == 0)
8361 {
8362 g_err << "Failed to retreive table" << copy.getName() << endl;
8363 return NDBT_FAILED;
8364
8365 }
8366 ids.push_back(tab->getObjectId());
8367 }
8368
8369 res.restartAll2(NdbRestarter::NRRF_ABORT | NdbRestarter::NRRF_NOSTART);
8370 res.waitClusterNoStart();
8371 res.startAll();
8372 res.waitClusterStarted();
8373
8374 for (unsigned i = 0; i< 25; i++)
8375 {
8376 NdbDictionary::Table copy = tab;
8377 BaseString name;
8378 name.appfmt("%s_%u", copy.getName(), i);
8379 copy.setName(name.c_str());
8380 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
8381 if (tab == 0)
8382 {
8383 g_err << "Failed to retreive table" << copy.getName() << endl;
8384 return NDBT_FAILED;
8385
8386 }
8387 int res = pDic->dropTable(copy.getName());
8388 if (res)
8389 {
8390 g_err << "Failed to drop table" << copy.getName() << "\n"
8391 << pDic->getNdbError() << endl;
8392 return NDBT_FAILED;
8393 }
8394 }
8395
8396 Vector<int> ids2;
8397 for (unsigned i = 0; i< 25; i++)
8398 {
8399 NdbDictionary::Table copy = tab;
8400 BaseString name;
8401 name.appfmt("%s_%u", copy.getName(), i);
8402 copy.setName(name.c_str());
8403 int res = pDic->createTable(copy);
8404 if (res)
8405 {
8406 g_err << "Failed to create table" << copy.getName() << "\n"
8407 << pDic->getNdbError() << endl;
8408 return NDBT_FAILED;
8409 }
8410 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
8411 if (tab == 0)
8412 {
8413 g_err << "Failed to retreive table" << copy.getName() << endl;
8414 return NDBT_FAILED;
8415
8416 }
8417 ids2.push_back(tab->getObjectId());
8418 }
8419
8420 for (unsigned i = 0; i< 25; i++)
8421 {
8422 NdbDictionary::Table copy = tab;
8423 BaseString name;
8424 name.appfmt("%s_%u", copy.getName(), i);
8425 copy.setName(name.c_str());
8426 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
8427 if (tab == 0)
8428 {
8429 g_err << "Failed to retreive table" << copy.getName() << endl;
8430 return NDBT_FAILED;
8431
8432 }
8433 int res = pDic->dropTable(copy.getName());
8434 if (res)
8435 {
8436 g_err << "Failed to drop table" << copy.getName() << "\n"
8437 << pDic->getNdbError() << endl;
8438 return NDBT_FAILED;
8439 }
8440 }
8441
8442 /**
8443 * With Bug53944 - none of the table-id have been reused in this scenario
8444 * check that atleast 15 of the 25 have been to return OK
8445 */
8446 unsigned reused = 0;
8447 for (unsigned i = 0; i<ids.size(); i++)
8448 {
8449 int id = ids[i];
8450 for (unsigned j = 0; j<ids2.size(); j++)
8451 {
8452 if (ids2[j] == id)
8453 {
8454 reused++;
8455 break;
8456 }
8457 }
8458 }
8459
8460 ndbout_c("reused %u table-ids out of %u",
8461 (unsigned)reused, (unsigned)ids.size());
8462
8463 if (reused >= (ids.size() >> 2))
8464 {
8465 return NDBT_OK;
8466 }
8467 else
8468 {
8469 return NDBT_FAILED;
8470 }
8471 }
8472
8473 // Bug58277 + Bug57057
8474
8475 #define CHK2(b, e) \
8476 if (!(b)) { \
8477 g_err << "ERR: " << #b << " failed at line " << __LINE__ \
8478 << ": " << e << endl; \
8479 result = NDBT_FAILED; \
8480 break; \
8481 }
8482
8483 // allow list of expected error codes which do not cause NDBT_FAILED
8484 #define CHK3(b, e, x) \
8485 if (!(b)) { \
8486 int n = sizeof(x)/sizeof(x[0]); \
8487 int i; \
8488 for (i = 0; i < n; i++) { \
8489 int s = (x[i] >= 0 ? +1 : -1); \
8490 if (e.code == s * x[i]) { \
8491 if (s == +1) \
8492 g_info << "OK: " << #b << " failed at line " << __LINE__ \
8493 << ": " << e << endl; \
8494 break; \
8495 } \
8496 } \
8497 if (i == n) { \
8498 g_err << "ERR: " << #b << " failed at line " << __LINE__ \
8499 << ": " << e << endl; \
8500 result = NDBT_FAILED; \
8501 } \
8502 break; \
8503 }
8504
8505 const char* tabName_Bug58277 = "TBug58277";
8506 const char* indName_Bug58277 = "TBug58277X1";
8507
8508 static void
sync_main_step(NDBT_Context * ctx,NDBT_Step * step,const char * state)8509 sync_main_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
8510 {
8511 // total sub-steps
8512 Uint32 sub_steps = ctx->getProperty("SubSteps", (Uint32)0);
8513 require(sub_steps != 0);
8514 // count has been reset before
8515 require(ctx->getProperty("SubCount", (Uint32)0) == 0);
8516 // set the state
8517 g_info << "step main: set " << state << endl;
8518 require(ctx->getProperty(state, (Uint32)0) == 0);
8519 ctx->setProperty(state, (Uint32)1);
8520 // wait for sub-steps
8521 ctx->getPropertyWait("SubCount", sub_steps);
8522 if (ctx->isTestStopped())
8523 return;
8524 g_info << "step main: sub-steps got " << state << endl;
8525 // reset count and state
8526 ctx->setProperty("SubCount", (Uint32)0);
8527 ctx->setProperty(state, (Uint32)0);
8528 }
8529
8530 static void
sync_sub_step(NDBT_Context * ctx,NDBT_Step * step,const char * state)8531 sync_sub_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
8532 {
8533 // wait for main step to set state
8534 g_info << "step " << step->getStepNo() << ": wait for " << state << endl;
8535 ctx->getPropertyWait(state, (Uint32)1);
8536 if (ctx->isTestStopped())
8537 return;
8538 // add to sub-step counter
8539 ctx->incProperty("SubCount");
8540 g_info << "step " << step->getStepNo() << ": got " << state << endl;
8541 // continue to run until next sync
8542 }
8543
8544 static int
runBug58277createtable(NDBT_Context * ctx,NDBT_Step * step)8545 runBug58277createtable(NDBT_Context* ctx, NDBT_Step* step)
8546 {
8547 Ndb* pNdb = GETNDB(step);
8548 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8549 int result = NDBT_OK;
8550 const int rows = ctx->getNumRecords();
8551 const char* tabname = tabName_Bug58277;
8552
8553 do
8554 {
8555 CHK2(rows > 0, "cannot use --records=0"); // others require this
8556 g_info << "create table " << tabname << endl;
8557 NdbDictionary::Table tab(tabname);
8558 const char* name[] = { "a", "b" };
8559 for (int i = 0; i <= 1; i++)
8560 {
8561 NdbDictionary::Column c(name[i]);
8562 c.setType(NdbDictionary::Column::Unsigned);
8563 c.setPrimaryKey(i == 0);
8564 c.setNullable(false);
8565 tab.addColumn(c);
8566 }
8567 if (rand() % 3 != 0)
8568 {
8569 g_info << "set FragAllLarge" << endl;
8570 tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
8571 }
8572 CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
8573 }
8574 while (0);
8575 return result;
8576 }
8577
8578 static int
runBug58277loadtable(NDBT_Context * ctx,NDBT_Step * step)8579 runBug58277loadtable(NDBT_Context* ctx, NDBT_Step* step)
8580 {
8581 Ndb* pNdb = GETNDB(step);
8582 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8583 int result = NDBT_OK;
8584 const int rows = ctx->getNumRecords();
8585 const char* tabname = tabName_Bug58277;
8586
8587 do
8588 {
8589 g_info << "load table" << endl;
8590 const NdbDictionary::Table* pTab = 0;
8591 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
8592
8593 int cnt = 0;
8594 for (int i = 0; i < rows; i++)
8595 {
8596 int retries = 10;
8597 retry:
8598 NdbTransaction* pTx = 0;
8599 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8600
8601 NdbOperation* pOp = 0;
8602 CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
8603 CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
8604 Uint32 aVal = i;
8605 Uint32 bVal = rand() % rows;
8606 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
8607 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
8608
8609 do
8610 {
8611 int x[] = {
8612 -630
8613 };
8614 int res = pTx->execute(Commit);
8615 if (res != 0 &&
8616 pTx->getNdbError().status == NdbError::TemporaryError)
8617 {
8618 retries--;
8619 if (retries >= 0)
8620 {
8621 pTx->close();
8622 NdbSleep_MilliSleep(10);
8623 goto retry;
8624 }
8625 }
8626 CHK3(res == 0, pTx->getNdbError(), x);
8627 cnt++;
8628 }
8629 while (0);
8630 CHK2(result == NDBT_OK, "load failed");
8631 pNdb->closeTransaction(pTx);
8632 }
8633 CHK2(result == NDBT_OK, "load failed");
8634 g_info << "load " << cnt << " rows" << endl;
8635 }
8636 while (0);
8637 return result;
8638 }
8639
8640 static int
runBug58277createindex(NDBT_Context * ctx,NDBT_Step * step)8641 runBug58277createindex(NDBT_Context* ctx, NDBT_Step* step)
8642 {
8643 Ndb* pNdb = GETNDB(step);
8644 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8645 int result = NDBT_OK;
8646 const char* tabname = tabName_Bug58277;
8647 const char* indname = indName_Bug58277;
8648
8649 do
8650 {
8651 g_info << "create index " << indname << endl;
8652 NdbDictionary::Index ind(indname);
8653 ind.setTable(tabname);
8654 ind.setType(NdbDictionary::Index::OrderedIndex);
8655 ind.setLogging(false);
8656 ind.addColumn("b");
8657 CHK2(pDic->createIndex(ind) == 0, pDic->getNdbError());
8658
8659 const NdbDictionary::Index* pInd = 0;
8660 CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
8661 }
8662 while (0);
8663 return result;
8664 }
8665
8666 // separate error handling test
8667 int
runBug58277errtest(NDBT_Context * ctx,NDBT_Step * step)8668 runBug58277errtest(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 int rows = ctx->getNumRecords();
8675 NdbRestarter restarter;
8676 const char* tabname = tabName_Bug58277;
8677 const char* indname = indName_Bug58277;
8678 (void)pDic->dropTable(tabname);
8679
8680 const int errloops = loops < 5 ? loops : 5;
8681 int errloop = 0;
8682 while (!ctx->isTestStopped() && errloop < errloops)
8683 {
8684 g_info << "===== errloop " << errloop << " =====" << endl;
8685
8686 if (errloop == 0)
8687 {
8688 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
8689 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
8690 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
8691 }
8692 const NdbDictionary::Index* pInd = 0;
8693 CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
8694
8695 int errins[] = {
8696 12008, 909, // TuxNoFreeScanOp
8697 12009, 4259 // InvalidBounds
8698 };
8699 const int errcnt = (int)(sizeof(errins)/sizeof(errins[0]));
8700 for (int i = 0; i < errcnt; i += 2)
8701 {
8702 const int ei = errins[i + 0];
8703 const int ec = errins[i + 1];
8704 CHK2(restarter.insertErrorInAllNodes(ei) == 0, "value " << ei);
8705
8706 NdbTransaction* pSTx = 0;
8707 CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8708 NdbIndexScanOperation* pSOp = 0;
8709 CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
8710
8711 NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
8712 Uint32 flags = 0;
8713 CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
8714
8715 Uint32 aVal = 0;
8716 CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
8717 CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
8718 // before fixes 12009 failed to fail at once here
8719 CHK2(pSOp->nextResult(true) == -1, "failed to fail on " << ei);
8720 CHK2(pSOp->getNdbError().code == ec, "expect " << ec << " got " << pSOp->getNdbError());
8721 pNdb->closeTransaction(pSTx);
8722
8723 g_info << "error " << ei << " " << ec << " ok" << endl;
8724 CHK2(restarter.insertErrorInAllNodes(0) == 0, "value " << 0);
8725 }
8726 CHK2(result == NDBT_OK, "test error handling failed");
8727
8728 errloop++;
8729 if (errloop == errloops)
8730 {
8731 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
8732 g_info << "table " << tabname << " dropped" << endl;
8733 }
8734 }
8735 if (result != NDBT_OK)
8736 {
8737 g_info << "stop test at line " << __LINE__ << endl;
8738 ctx->stopTest();
8739 }
8740 return result;
8741 }
8742
8743 int
runBug58277drop(NDBT_Context * ctx,NDBT_Step * step)8744 runBug58277drop(NDBT_Context* ctx, NDBT_Step* step)
8745 {
8746 Ndb* pNdb = GETNDB(step);
8747 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8748 int result = NDBT_OK;
8749 const char* tabname = tabName_Bug58277;
8750 const char* indname = indName_Bug58277;
8751 int dropms = 0;
8752
8753 while (!ctx->isTestStopped())
8754 {
8755 sync_sub_step(ctx, step, "Start");
8756 if (ctx->isTestStopped())
8757 break;
8758 dropms = ctx->getProperty("DropMs", (Uint32)0);
8759 NdbSleep_MilliSleep(dropms);
8760
8761 g_info << "drop index " << indname << endl;
8762 CHK2(pDic->dropIndex(indname, tabname) == 0, pDic->getNdbError());
8763 pDic->invalidateIndex(indname, tabname);
8764 CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
8765 g_info << "drop index done" << endl;
8766
8767 sync_sub_step(ctx, step, "Stop");
8768 if (ctx->isTestStopped())
8769 break;
8770 }
8771 if (result != NDBT_OK)
8772 {
8773 g_info << "stop test at line " << __LINE__ << endl;
8774 ctx->stopTest();
8775 }
8776 return result;
8777 }
8778
8779 static int
runBug58277scanop(NDBT_Context * ctx,NDBT_Step * step,int cnt[1+3])8780 runBug58277scanop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
8781 {
8782 Ndb* pNdb = GETNDB(step);
8783 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8784 int result = NDBT_OK;
8785 const int rows = ctx->getNumRecords();
8786 const char* tabname = tabName_Bug58277;
8787 const char* indname = indName_Bug58277;
8788 const int range_max = ctx->getProperty("RANGE_MAX", (Uint32)0);
8789 require(range_max > 0);
8790 const bool scan_delete = ctx->getProperty("SCAN_DELETE", (Uint32)0);
8791
8792 do
8793 {
8794 const NdbDictionary::Index* pInd = 0;
8795 {
8796 int x[] = {
8797 4243 // Index not found
8798 };
8799 pDic->invalidateIndex(indname, tabname);
8800 CHK3((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError(), x);
8801 }
8802
8803 NdbTransaction* pSTx = 0;
8804 CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8805 NdbIndexScanOperation* pSOp = 0;
8806 CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
8807 NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
8808 Uint32 flags = 0;
8809 int range_cnt = rand() % range_max;
8810 if (range_cnt > 1 || rand() % 5 == 0)
8811 flags |= NdbIndexScanOperation::SF_MultiRange;
8812 CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
8813 g_info << "range cnt " << range_cnt << endl;
8814 for (int i = 0; i < range_cnt; )
8815 {
8816 int tlo = -1;
8817 int thi = -1;
8818 if (rand() % 5 == 0)
8819 {
8820 if (rand() % 5 != 0)
8821 tlo = 0 + rand() % 2;
8822 if (rand() % 5 != 0)
8823 thi = 2 + rand() % 2;
8824 }
8825 else
8826 tlo = 4;
8827 // apparently no bounds is not allowed (see also bug#57396)
8828 if (tlo == -1 && thi == -1)
8829 continue;
8830 Uint32 blo = 0;
8831 Uint32 bhi = 0;
8832 if (tlo != -1)
8833 {
8834 blo = rand() % rows;
8835 CHK2(pSOp->setBound("b", tlo, &blo) == 0, pSOp->getNdbError());
8836 }
8837 if (thi != -1)
8838 {
8839 bhi = rand() % (rows + 1);
8840 if (bhi < blo)
8841 bhi = rand() % (rows + 1);
8842 CHK2(pSOp->setBound("b", thi, &bhi) == 0, pSOp->getNdbError());
8843 }
8844 CHK2(pSOp->end_of_bound() == 0, pSOp->getNdbError());
8845 i++;
8846 }
8847 CHK2(result == NDBT_OK, "set bound ranges failed");
8848
8849 Uint32 aVal = 0;
8850 CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
8851 CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
8852
8853 while (1)
8854 {
8855 int ret;
8856 {
8857 int x[] = {
8858 241, // Invalid schema object version
8859 274, // Time-out in NDB, probably caused by deadlock
8860 283, // Table is being dropped
8861 284, // Table not defined in transaction coordinator
8862 910, // Index is being dropped
8863 1226 // Table is being dropped
8864 };
8865 CHK3((ret = pSOp->nextResult(true)) != -1, pSOp->getNdbError(), x);
8866 }
8867 require(ret == 0 || ret == 1);
8868 if (ret == 1)
8869 break;
8870
8871 NdbTransaction* pTx = 0;
8872 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8873
8874 while (1)
8875 {
8876 int type = 1 + rand() % 3;
8877 if (type == 2) // insert->update
8878 type = 1;
8879 if (scan_delete)
8880 type = 3;
8881 do
8882 {
8883 if (type == 1)
8884 {
8885 NdbOperation* pOp = 0;
8886 CHK2((pOp = pSOp->updateCurrentTuple(pTx)) != 0, pSOp->getNdbError());
8887 Uint32 bVal = (Uint32)(rand() % rows);
8888 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
8889 break;
8890 }
8891 if (type == 3)
8892 {
8893 CHK2(pSOp->deleteCurrentTuple(pTx) == 0, pSOp->getNdbError());
8894 break;
8895 }
8896 require(false);
8897 }
8898 while (0);
8899 CHK2(result == NDBT_OK, "scan takeover error");
8900 cnt[type]++;
8901 {
8902 int x[] = {
8903 266, // Time-out in NDB, probably caused by deadlock
8904 499, // Scan take over error
8905 631, // 631
8906 4350 // Transaction already aborted
8907 };
8908 CHK3(pTx->execute(NoCommit) == 0, pTx->getNdbError(), x);
8909 }
8910
8911 CHK2((ret = pSOp->nextResult(false)) != -1, pSOp->getNdbError());
8912 require(ret == 0 || ret == 2);
8913 if (ret == 2)
8914 break;
8915 }
8916 CHK2(result == NDBT_OK, "batch failed");
8917
8918 {
8919 int x[] = {
8920 266, // Time-out in NDB, probably caused by deadlock
8921 4350 // Transaction already aborted
8922 };
8923 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
8924 }
8925 pNdb->closeTransaction(pTx);
8926 }
8927 CHK2(result == NDBT_OK, "batch failed");
8928 pNdb->closeTransaction(pSTx);
8929 }
8930 while (0);
8931 return result;
8932 }
8933
8934 int
runBug58277scan(NDBT_Context * ctx,NDBT_Step * step)8935 runBug58277scan(NDBT_Context* ctx, NDBT_Step* step)
8936 {
8937 int result = NDBT_OK;
8938
8939 while (!ctx->isTestStopped())
8940 {
8941 sync_sub_step(ctx, step, "Start");
8942 if (ctx->isTestStopped())
8943 break;
8944 g_info << "start scan loop" << endl;
8945 while (!ctx->isTestStopped())
8946 {
8947 g_info << "start scan" << endl;
8948 int cnt[1+3] = { 0, 0, 0, 0 };
8949 CHK2(runBug58277scanop(ctx, step, cnt) == NDBT_OK, "scan failed");
8950 g_info << "scan ops " << cnt[1] << "/-/" << cnt[3] << endl;
8951
8952 if (ctx->getProperty("Stop", (Uint32)0) == 1)
8953 {
8954 sync_sub_step(ctx, step, "Stop");
8955 break;
8956 }
8957 }
8958 CHK2(result == NDBT_OK, "scan loop failed");
8959 }
8960 if (result != NDBT_OK)
8961 {
8962 g_info << "stop test at line " << __LINE__ << endl;
8963 ctx->stopTest();
8964 }
8965 return result;
8966 }
8967
8968 static int
runBug58277pkop(NDBT_Context * ctx,NDBT_Step * step,int cnt[1+3])8969 runBug58277pkop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
8970 {
8971 Ndb* pNdb = GETNDB(step);
8972 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8973 int result = NDBT_OK;
8974 const int rows = ctx->getNumRecords();
8975 const char* tabname = tabName_Bug58277;
8976
8977 do
8978 {
8979 const NdbDictionary::Table* pTab = 0;
8980 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
8981
8982 NdbTransaction* pTx = 0;
8983 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
8984 NdbOperation* pOp = 0;
8985 CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
8986 int type = 1 + rand() % 3;
8987 Uint32 aVal = rand() % rows;
8988 Uint32 bVal = rand() % rows;
8989
8990 do
8991 {
8992 if (type == 1)
8993 {
8994 CHK2(pOp->updateTuple() == 0, pOp->getNdbError());
8995 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
8996 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
8997 int x[] = {
8998 266, // Time-out in NDB, probably caused by deadlock
8999 -626 // Tuple did not exist
9000 };
9001 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
9002 break;
9003 }
9004 if (type == 2)
9005 {
9006 CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
9007 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
9008 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
9009 int x[] = {
9010 266, // Time-out in NDB, probably caused by deadlock
9011 -630 // Tuple already existed when attempting to insert
9012 };
9013 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
9014 break;
9015 }
9016 if (type == 3)
9017 {
9018 CHK2(pOp->deleteTuple() == 0, pOp->getNdbError());
9019 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
9020 int x[] = {
9021 266, // Time-out in NDB, probably caused by deadlock
9022 -626 // Tuple did not exist
9023 };
9024 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
9025 break;
9026 }
9027 require(false);
9028 }
9029 while (0);
9030 CHK2(result == NDBT_OK, "pk op failed");
9031
9032 pNdb->closeTransaction(pTx);
9033 cnt[type]++;
9034 }
9035 while (0);
9036 return result;
9037 }
9038
9039 int
runBug58277pk(NDBT_Context * ctx,NDBT_Step * step)9040 runBug58277pk(NDBT_Context* ctx, NDBT_Step* step)
9041 {
9042 int result = NDBT_OK;
9043
9044 while (!ctx->isTestStopped())
9045 {
9046 sync_sub_step(ctx, step, "Start");
9047 if (ctx->isTestStopped())
9048 break;
9049
9050 g_info << "start pk loop" << endl;
9051 int cnt[1+3] = { 0, 0, 0, 0 };
9052 while (!ctx->isTestStopped())
9053 {
9054 CHK2(runBug58277pkop(ctx, step, cnt) == NDBT_OK, "pk op failed");
9055
9056 if (ctx->getProperty("Stop", (Uint32)0) == 1)
9057 {
9058 sync_sub_step(ctx, step, "Stop");
9059 break;
9060 }
9061 }
9062 CHK2(result == NDBT_OK, "pk loop failed");
9063 g_info << "pk ops " << cnt[1] << "/" << cnt[2] << "/" << cnt[3] << endl;
9064 }
9065 if (result != NDBT_OK)
9066 {
9067 g_info << "stop test at line " << __LINE__ << endl;
9068 ctx->stopTest();
9069 }
9070 return result;
9071 }
9072
9073 int
runBug58277rand(NDBT_Context * ctx,NDBT_Step * step)9074 runBug58277rand(NDBT_Context* ctx, NDBT_Step* step)
9075 {
9076 int result = NDBT_OK;
9077 NdbRestarter restarter;
9078
9079 while (!ctx->isTestStopped())
9080 {
9081 int sleepms = rand() % 5000;
9082 g_info << "rand sleep " << sleepms << " ms" << endl;
9083 NdbSleep_MilliSleep(sleepms);
9084 if (rand() % 5 == 0)
9085 {
9086 g_info << "rand force LCP" << endl;
9087 int dump1[] = { DumpStateOrd::DihStartLcpImmediately };
9088 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
9089 }
9090 }
9091 if (result != NDBT_OK)
9092 {
9093 g_info << "stop test at line " << __LINE__ << endl;
9094 ctx->stopTest();
9095 }
9096 g_info << "rand exit" << endl;
9097 return result;
9098 }
9099
9100 int
runBug58277(NDBT_Context * ctx,NDBT_Step * step)9101 runBug58277(NDBT_Context* ctx, NDBT_Step* step)
9102 {
9103 Ndb* pNdb = GETNDB(step);
9104 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9105 const int loops = ctx->getNumLoops();
9106 int result = NDBT_OK;
9107 const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
9108 NdbRestarter restarter;
9109 const char* tabname = tabName_Bug58277;
9110 const char* indname = indName_Bug58277;
9111 (void)pDic->dropTable(tabname);
9112
9113 int loop = 0;
9114 while (!ctx->isTestStopped())
9115 {
9116 g_info << "===== loop " << loop << " =====" << endl;
9117
9118 if (loop == 0)
9119 {
9120 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
9121 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
9122 }
9123
9124 if (rss_check)
9125 {
9126 g_info << "save all resource usage" << endl;
9127 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
9128 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
9129 }
9130
9131 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
9132
9133 int dropmin = 1000;
9134 int dropmax = 9000;
9135 int dropms = dropmin + rand() % (dropmax - dropmin + 1);
9136 g_info << "drop in " << dropms << " ms" << endl;
9137 ctx->setProperty("DropMs", dropms);
9138
9139 sync_main_step(ctx, step, "Start");
9140 if (ctx->isTestStopped())
9141 break;
9142
9143 // vary Stop time a bit in either direction
9144 int stopvar = rand() % 100;
9145 int stopsgn = (rand() % 2 == 0 ? +1 : -1);
9146 int stopms = dropms + stopsgn * stopvar;
9147 NdbSleep_MilliSleep(stopms);
9148
9149 sync_main_step(ctx, step, "Stop");
9150 if (ctx->isTestStopped())
9151 break;
9152
9153 // index must have been dropped
9154 pDic->invalidateIndex(indname, tabname);
9155 CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
9156
9157 if (rss_check)
9158 {
9159 g_info << "check all resource usage" << endl;
9160 int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
9161 CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
9162
9163 g_info << "check cluster is up" << endl;
9164 CHK2(restarter.waitClusterStarted() == 0, "failed");
9165 }
9166
9167 if (++loop == loops)
9168 {
9169 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
9170 g_info << "table " << tabname << " dropped" << endl;
9171 break;
9172 }
9173 }
9174
9175 g_info << "stop test at line " << __LINE__ << endl;
9176 ctx->stopTest();
9177 return result;
9178 }
9179
9180 int
runBug57057(NDBT_Context * ctx,NDBT_Step * step)9181 runBug57057(NDBT_Context* ctx, NDBT_Step* step)
9182 {
9183 Ndb* pNdb = GETNDB(step);
9184 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9185 const int loops = ctx->getNumLoops();
9186 int result = NDBT_OK;
9187 const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
9188 NdbRestarter restarter;
9189 const char* tabname = tabName_Bug58277;
9190 //const char* indname = indName_Bug58277;
9191 (void)pDic->dropTable(tabname);
9192
9193 int loop = 0;
9194 while (!ctx->isTestStopped())
9195 {
9196 g_info << "===== loop " << loop << " =====" << endl;
9197
9198 if (loop == 0)
9199 {
9200 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
9201 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
9202 }
9203
9204 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
9205
9206 if (rss_check)
9207 {
9208 g_info << "save all resource usage" << endl;
9209 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
9210 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
9211 }
9212
9213 int dropmin = 1000;
9214 int dropmax = 2000;
9215 int dropms = dropmin + rand() % (dropmax - dropmin + 1);
9216 int stopms = dropms;
9217
9218 sync_main_step(ctx, step, "Start");
9219 if (ctx->isTestStopped())
9220 break;
9221
9222 g_info << "stop in " << stopms << " ms" << endl;
9223 NdbSleep_MilliSleep(stopms);
9224
9225 sync_main_step(ctx, step, "Stop");
9226 if (ctx->isTestStopped())
9227 break;
9228
9229 if (rss_check)
9230 {
9231 g_info << "check all resource usage" << endl;
9232 int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
9233 CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
9234
9235 g_info << "check cluster is up" << endl;
9236 CHK2(restarter.waitClusterStarted() == 0, "failed");
9237 }
9238
9239 if (++loop == loops)
9240 {
9241 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
9242 g_info << "table " << tabname << " dropped" << endl;
9243 break;
9244 }
9245 }
9246
9247 g_info << "stop test at line " << __LINE__ << endl;
9248 ctx->stopTest();
9249 return result;
9250 }
9251
9252 /**
9253 * This is a regression test for Bug #14647210 "CAN CRASH ALL NODES EASILY
9254 * WHEN RESTARTING MORE THAN 6 NODES SIMULTANEOUSLY". The cause of this bug
9255 * was that DICT did not handle GET_TABINFOREF signals.
9256 */
9257 static int
runGetTabInfoRef(NDBT_Context * ctx,NDBT_Step * step)9258 runGetTabInfoRef(NDBT_Context* ctx, NDBT_Step* step)
9259 {
9260 NdbRestarter restarter;
9261 if (restarter.getNumDbNodes() == 1)
9262 {
9263 g_info << "Cannot do this test with just one datanode." << endl;
9264 return NDBT_OK;
9265 }
9266
9267 /**
9268 * This error insert makes DICT respond with GET_TABINFOREF where
9269 * error==busy when receiving the next GET_TABINFOREQ signal.
9270 */
9271 restarter.insertErrorInAllNodes(6026);
9272
9273 /* Find a node in each nodegroup to restart. */
9274 Vector<int> nodeSet;
9275 Bitmask<MAX_NDB_NODES/32> nodeGroupMap;
9276 for (int i = 0; i < restarter.getNumDbNodes(); i++)
9277 {
9278 const int node = restarter.getDbNodeId(i);
9279 const int ng = restarter.getNodeGroup(node);
9280 if (!nodeGroupMap.get(ng))
9281 {
9282 g_info << "Node " << node << " will be stopped." << endl;
9283 nodeSet.push_back(node);
9284 nodeGroupMap.set(ng);
9285 }
9286 }
9287
9288 if (restarter.restartNodes(nodeSet.getBase(), (int)nodeSet.size(),
9289 NdbRestarter::NRRF_NOSTART |
9290 NdbRestarter::NRRF_ABORT))
9291 {
9292 g_err << "Failed to stop nodes" << endl;
9293 restarter.insertErrorInAllNodes(0);
9294 return NDBT_FAILED;
9295 }
9296
9297 g_info << "Waiting for nodes to stop." << endl;
9298 if (restarter.waitNodesNoStart(nodeSet.getBase(), (int)nodeSet.size()))
9299 {
9300 g_err << "Failed to wait for nodes to stop" << endl;
9301 restarter.insertErrorInAllNodes(0);
9302 return NDBT_FAILED;
9303 }
9304
9305 if (restarter.startNodes(nodeSet.getBase(), (int)nodeSet.size()))
9306 {
9307 g_err << "Failed to restart nodes" << endl;
9308 restarter.insertErrorInAllNodes(0);
9309 return NDBT_FAILED;
9310 }
9311
9312 g_info << "Waiting for nodes to start again." << endl;
9313 if (restarter.waitClusterStarted() != 0)
9314 {
9315 g_err << "Failed to restart cluster " << endl;
9316 restarter.insertErrorInAllNodes(0);
9317 return NDBT_FAILED;
9318 }
9319
9320 restarter.insertErrorInAllNodes(0);
9321 return NDBT_OK;
9322 } // runGetTabInfoRef()
9323
9324 int
runBug13416603(NDBT_Context * ctx,NDBT_Step * step)9325 runBug13416603(NDBT_Context* ctx, NDBT_Step* step)
9326 {
9327 Ndb* pNdb = GETNDB(step);
9328 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9329 NdbIndexStat is;
9330 NdbRestarter res;
9331
9332 int elist[] = { 18026, 0 };
9333 const NdbDictionary::Table *pTab = pDic->getTable(ctx->getTab()->getName());
9334 const NdbDictionary::Index *pIdx = 0;
9335 NdbDictionary::Dictionary::List indexes;
9336 pDic->listIndexes(indexes, * pTab);
9337 for (unsigned i = 0; i < indexes.count; i++)
9338 {
9339 if ((pIdx = pDic->getIndex(indexes.elements[i].name, pTab->getName())) != 0)
9340 break;
9341 }
9342
9343 if (pIdx == 0)
9344 {
9345 return NDBT_OK;
9346 }
9347
9348 bool has_created_stat_tables = false;
9349 bool has_created_stat_events = false;
9350 pNdb->setDatabaseName("mysql");
9351 if (is.create_systables(pNdb) == 0)
9352 {
9353 has_created_stat_tables = true;
9354 }
9355
9356 if (is.create_sysevents(pNdb) == 0)
9357 {
9358 has_created_stat_events = true;
9359 }
9360
9361 chk2(is.create_listener(pNdb) == 0, is.getNdbError());
9362 chk2(is.execute_listener(pNdb) == 0, is.getNdbError());
9363
9364 is.set_index(* pIdx, * pTab);
9365
9366 {
9367 ndbout_c("%u - update_stat", __LINE__);
9368 chk2(is.update_stat(pNdb) == 0, is.getNdbError());
9369 int ret;
9370 ndbout_c("%u - poll_listener", __LINE__);
9371 chk2((ret = is.poll_listener(pNdb, 10000)) != -1, is.getNdbError());
9372 chk1(ret == 1);
9373 // one event is expected
9374 ndbout_c("%u - next_listener", __LINE__);
9375 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
9376 chk1(ret == 1);
9377 ndbout_c("%u - next_listener", __LINE__);
9378 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
9379 chk1(ret == 0);
9380 }
9381
9382 {
9383 Vector<Vector<int> > partitions = res.splitNodes();
9384 if (partitions.size() == 1)
9385 goto cleanup;
9386
9387 for (unsigned i = 0; i < partitions.size(); i++)
9388 {
9389 printf("stopping: ");
9390 for (unsigned j = 0; j < partitions[i].size(); j++)
9391 printf("%d ", partitions[i][j]);
9392 printf("\n");
9393
9394 res.restartNodes(partitions[i].getBase(),
9395 partitions[i].size(),
9396 NdbRestarter::NRRF_NOSTART | NdbRestarter::NRRF_ABORT);
9397 res.waitNodesNoStart(partitions[i].getBase(),
9398 partitions[i].size());
9399
9400 {
9401 ndbout_c("%u - update_stat", __LINE__);
9402 chk2(is.update_stat(pNdb) == 0, is.getNdbError());
9403 int ret;
9404 ndbout_c("%u - poll_listener", __LINE__);
9405 chk2((ret = is.poll_listener(pNdb, 10000)) != -1, is.getNdbError());
9406 chk1(ret == 1);
9407 // one event is expected
9408 ndbout_c("%u - next_listener", __LINE__);
9409 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
9410 chk1(ret == 1);
9411 ndbout_c("%u - next_listener", __LINE__);
9412 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
9413 chk1(ret == 0);
9414 }
9415
9416 res.startNodes(partitions[i].getBase(),
9417 partitions[i].size());
9418 res.waitClusterStarted();
9419 }
9420 }
9421
9422 for (int i = 0; elist[i] != 0; i++)
9423 {
9424 ndbout_c("testing errno: %u", elist[i]);
9425 res.insertErrorInAllNodes(elist[i]);
9426 int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
9427 res.dumpStateAllNodes(val2, 2);
9428
9429 {
9430 ndbout_c("%u - update_stat", __LINE__);
9431 int ret = is.update_stat(pNdb);
9432 ndbout_c("%u - update_stat => %d", __LINE__, ret);
9433 chk1(ret == -1);
9434 ndbout << is.getNdbError() << endl;
9435 ndbout_c("%u - poll_listener", __LINE__);
9436 chk2((ret = is.poll_listener(pNdb, 10000)) != -1, is.getNdbError());
9437 if (ret == 1)
9438 {
9439 /* After the new api is introduced, pollEvents() (old api version)
9440 * returns 1 when empty epoch is at the head of the event queue.
9441 * pollEvents2() (new api version) returns 1 when exceptional
9442 * epoch is at the head of the event queue.
9443 * So next_listener() must be called to handle them.
9444 */
9445 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
9446 }
9447 // Check that the event queue is empty
9448 chk1(ret == 0);
9449 }
9450
9451 /**
9452 * Wait for one of the nodes to have died...
9453 */
9454 int count_started = 0;
9455 int count_not_started = 0;
9456 int count_nok = 0;
9457 int down = 0;
9458 do
9459 {
9460 NdbSleep_MilliSleep(100);
9461 count_started = count_not_started = count_nok = 0;
9462 for (int i = 0; i < res.getNumDbNodes(); i++)
9463 {
9464 int n = res.getDbNodeId(i);
9465 if (res.getNodeStatus(n) == NDB_MGM_NODE_STATUS_NOT_STARTED)
9466 {
9467 count_not_started++;
9468 down = n;
9469 }
9470 else if (res.getNodeStatus(n) == NDB_MGM_NODE_STATUS_STARTED)
9471 count_started++;
9472 else
9473 count_nok ++;
9474 }
9475 } while (count_not_started != 1);
9476
9477 res.startNodes(&down, 1);
9478 res.waitClusterStarted();
9479 res.insertErrorInAllNodes(0);
9480 }
9481
9482 cleanup:
9483 // cleanup
9484 is.drop_listener(pNdb);
9485 if (has_created_stat_events)
9486 {
9487 is.drop_sysevents(pNdb);
9488 }
9489 if (has_created_stat_tables)
9490 {
9491 is.drop_systables(pNdb);
9492 }
9493
9494 // Ensure that nodes will start after error inserts again.
9495 {
9496 const int restartState[] =
9497 { DumpStateOrd::CmvmiSetRestartOnErrorInsert, NRT_DoStart_Restart };
9498
9499 require(res.dumpStateAllNodes(restartState,
9500 sizeof restartState/sizeof restartState[0])
9501 == 0);
9502 }
9503
9504 return NDBT_OK;
9505
9506 err:
9507 return NDBT_FAILED;
9508 }
9509
9510 int
runIndexStatCreate(NDBT_Context * ctx,NDBT_Step * step)9511 runIndexStatCreate(NDBT_Context* ctx, NDBT_Step* step)
9512 {
9513 Ndb* pNdb = GETNDB(step);
9514 NdbIndexStat is;
9515
9516 const int loops = ctx->getNumLoops();
9517
9518 pNdb->setDatabaseName("mysql");
9519
9520 Uint64 end = NdbTick_CurrentMillisecond() + 1000 * loops;
9521 do
9522 {
9523 if (is.create_systables(pNdb) == 0)
9524 {
9525 /**
9526 * OK
9527 */
9528 }
9529 else if (! (is.getNdbError().code == 701 || // timeout
9530 is.getNdbError().code == 721 || // already exists
9531 is.getNdbError().code == 4244 || // already exists
9532 is.getNdbError().code == 4009)) // no connection
9533 {
9534 ndbout << is.getNdbError() << endl;
9535 return NDBT_FAILED;
9536 }
9537
9538 is.drop_systables(pNdb);
9539 } while (!ctx->isTestStopped() && NdbTick_CurrentMillisecond() < end);
9540
9541 return NDBT_OK;
9542 }
9543
9544 int
runWL946(NDBT_Context * ctx,NDBT_Step * step)9545 runWL946(NDBT_Context* ctx, NDBT_Step* step)
9546 {
9547 Ndb* pNdb = GETNDB(step);
9548 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9549 const int loops = ctx->getNumLoops();
9550 const int records = ctx->getNumRecords();
9551 bool keep_table = false; // keep table and data
9552 #ifdef VM_TRACE
9553 #ifdef NDB_USE_GET_ENV
9554 {
9555 const char* p = NdbEnv_GetEnv("KEEP_TABLE_WL946", (char*)0, 0);
9556 if (p != 0 && strchr("1Y", p[0]) != 0)
9557 keep_table = true;
9558 }
9559 #endif
9560 #endif
9561 int result = NDBT_OK;
9562
9563 const char* tabname = "T_WL946";
9564 (void)pDic->dropTable(tabname);
9565
9566 for (int loop = 0; loop < loops; loop++)
9567 {
9568 g_info << "loop " << loop << "(" << loops << ")" << endl;
9569
9570 NdbDictionary::Table tab;
9571 tab.setName(tabname);
9572
9573 struct Coldef {
9574 const char* name;
9575 NdbDictionary::Column::Type type;
9576 int prec; // fractional precision 0-6
9577 int flag; // 1-pk 2-nullable 4-fractional 8-create index
9578 const char* indname;
9579 } coldef[] = {
9580 // primary key
9581 { "pk", NdbDictionary::Column::Unsigned, 0, 1, 0 },
9582 // deprecated
9583 { "a0", NdbDictionary::Column::Time, 0, 2|8, "x0" },
9584 { "a1", NdbDictionary::Column::Datetime, 0, 2|8, "x1" },
9585 { "a2", NdbDictionary::Column::Timestamp, 0, 2|8, "x2" },
9586 // fractional
9587 { "b0", NdbDictionary::Column::Time2, 0, 2|4|8, "y0" },
9588 { "b1", NdbDictionary::Column::Datetime2, 0, 2|4|8, "y1" },
9589 { "b2", NdbDictionary::Column::Timestamp2, 0, 2|4|8, "y2" },
9590 // update key
9591 { "uk", NdbDictionary::Column::Unsigned, 0, 0, 0 }
9592 };
9593 const int Colcnt = sizeof(coldef)/sizeof(coldef[0]);
9594
9595 NdbDictionary::Column col[Colcnt];
9596 for (int i = 0; i < Colcnt; i++)
9597 {
9598 Coldef& d = coldef[i];
9599 NdbDictionary::Column& c = col[i];
9600 c.setName(d.name);
9601 c.setType(d.type);
9602 if (d.flag & 4)
9603 {
9604 d.prec = myRandom48(7);
9605 require(d.prec >= 0 && d.prec <= 6);
9606 c.setPrecision(d.prec);
9607 }
9608 c.setPrimaryKey(d.flag & 1);
9609 c.setNullable(d.flag & 2);
9610 tab.addColumn(c);
9611 }
9612
9613 g_info << "create table " << tabname << endl;
9614 const NdbDictionary::Table* pTab = 0;
9615 CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
9616 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
9617
9618 const NdbDictionary::Column* pCol[Colcnt];
9619 for (int i = 0; i < Colcnt; i++)
9620 {
9621 const Coldef& d = coldef[i];
9622 const NdbDictionary::Column* pc = 0;
9623 CHK2((pc = tab.getColumn(i)) != 0, pDic->getNdbError());
9624 CHK2(strcmp(pc->getName(), d.name) == 0, "name");
9625 CHK2(pc->getType() == d.type, "type");
9626 CHK2(pc->getPrecision() == d.prec, "prec");
9627 pCol[i] = pc;
9628 }
9629 CHK2(result == NDBT_OK, "verify columns");
9630
9631 g_info << "create indexes" << endl;
9632 NdbDictionary::Index ind[Colcnt];
9633 const NdbDictionary::Index* pInd[Colcnt];
9634 for (int i = 0; i < Colcnt; i++)
9635 {
9636 Coldef& d = coldef[i];
9637 pInd[i] = 0;
9638 if (d.flag & 8)
9639 {
9640 NdbDictionary::Index& x = ind[i];
9641 x.setName(d.indname);
9642 x.setTable(tabname);
9643 x.setType(NdbDictionary::Index::OrderedIndex);
9644 x.setLogging(false);
9645 x.addColumn(d.name);
9646 const NdbDictionary::Index* px = 0;
9647 CHK2(pDic->createIndex(x) == 0, pDic->getNdbError());
9648 CHK2((px = pDic->getIndex(d.indname, tabname)) != 0, pDic->getNdbError());
9649 pInd[i] = px;
9650 }
9651 }
9652 CHK2(result == NDBT_OK, "create indexes");
9653
9654 HugoTransactions trans(*pTab);
9655
9656 g_info << "load records" << endl;
9657 CHK2(trans.loadTable(pNdb, records) == 0, trans.getNdbError());
9658
9659 const int scanloops = 5;
9660 for (int j = 0; j < scanloops; j++)
9661 {
9662 g_info << "scan table " << j << "(" << scanloops << ")" << endl;
9663 CHK2(trans.scanReadRecords(pNdb, records) == 0, trans.getNdbError());
9664
9665 for (int i = 0; i < Colcnt; i++)
9666 {
9667 Coldef& d = coldef[i];
9668 if (d.flag & 8)
9669 {
9670 g_info << "scan index " << d.indname << endl;
9671 const NdbDictionary::Index* px = pInd[i];
9672 CHK2(trans.scanReadRecords(pNdb, px, records) == 0, trans.getNdbError());
9673 }
9674 }
9675 CHK2(result == NDBT_OK, "index scan");
9676
9677 g_info << "update records" << endl;
9678 CHK2(trans.scanUpdateRecords(pNdb, records) == 0, trans.getNdbError());
9679 }
9680 CHK2(result == NDBT_OK, "scans");
9681
9682 if (loop + 1 < loops || !keep_table)
9683 {
9684 g_info << "delete records" << endl;
9685 CHK2(trans.clearTable(pNdb) == 0, trans.getNdbError());
9686
9687 g_info << "drop table" << endl;
9688 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
9689 }
9690 }
9691
9692 if (result != NDBT_OK && !keep_table)
9693 {
9694 g_info << "drop table after error" << endl;
9695 (void)pDic->dropTable(tabname);
9696 }
9697 return result;
9698 }
9699
9700 int
getOrCreateDefaultHashMap(NdbDictionary::Dictionary & dict,NdbDictionary::HashMap & hm,Uint32 buckets,Uint32 fragments)9701 getOrCreateDefaultHashMap(NdbDictionary::Dictionary& dict, NdbDictionary::HashMap& hm, Uint32 buckets, Uint32 fragments)
9702 {
9703 if (dict.getDefaultHashMap(hm, buckets, fragments) == 0)
9704 {
9705 return 0;
9706 }
9707
9708 dict.initDefaultHashMap(hm, buckets, fragments);
9709 if (dict.createHashMap(hm, NULL) == -1)
9710 {
9711 return -1;
9712 }
9713
9714 if (dict.getDefaultHashMap(hm, buckets, fragments) == 0)
9715 {
9716 return 0;
9717 }
9718
9719 return -1;
9720 }
9721
9722 struct Bug14645319_createTable_args
9723 {
9724 char const* template_name;
9725 char const* name;
9726 Uint32 buckets;
9727 Uint32 fragments;
9728 };
9729
Bug14645319_createTable(Ndb * pNdb,NdbDictionary::Table & tab,int when,void * arg)9730 int Bug14645319_createTable(Ndb* pNdb, NdbDictionary::Table& tab, int when,
9731 void* arg)
9732 {
9733 Bug14645319_createTable_args& args = *static_cast<Bug14645319_createTable_args*>(arg);
9734 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9735 if (when == 0)
9736 {
9737 tab.setName(args.name);
9738 tab.setFragmentCount(args.fragments);
9739 if (args.fragments == 0)
9740 {
9741 tab.setFragmentData(0, 0);
9742 }
9743 NdbDictionary::HashMap hm;
9744 getOrCreateDefaultHashMap(*pDic, hm, args.buckets, args.fragments);
9745 tab.setHashMap(hm);
9746 }
9747 return 0;
9748 }
9749
9750 int
runBug14645319(NDBT_Context * ctx,NDBT_Step * step)9751 runBug14645319(NDBT_Context* ctx, NDBT_Step* step)
9752 {
9753 Ndb* pNdb = GETNDB(step);
9754 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9755 int failures = 0;
9756
9757 struct test_case {
9758 char const* description;
9759 int old_fragments;
9760 int old_buckets;
9761 int new_fragments;
9762 int new_buckets;
9763 int expected_buckets;
9764 };
9765
9766 STATIC_ASSERT(NDB_DEFAULT_HASHMAP_BUCKETS % 240 == 0);
9767 STATIC_ASSERT(NDB_DEFAULT_HASHMAP_BUCKETS % 260 != 0);
9768 test_case test_cases[] = {
9769 { "Simulate online reorg, may or may not change hashmap depending on default fragment count",
9770 3, 120, 0, NDB_DEFAULT_HASHMAP_BUCKETS, 0 },
9771 { "Keep old hashmap since no new fragments",
9772 3, 120, 3, NDB_DEFAULT_HASHMAP_BUCKETS, 120 },
9773 { "Keep old hashmap size since old size a multiple of new fragment count",
9774 3, 120, 6, NDB_DEFAULT_HASHMAP_BUCKETS, 120 },
9775 { "Keep old hashmap size since new size not a multiple of old",
9776 3, 130, 6, NDB_DEFAULT_HASHMAP_BUCKETS, 130 },
9777 { "Extend hashmap",
9778 3, 120, 7, NDB_DEFAULT_HASHMAP_BUCKETS, NDB_DEFAULT_HASHMAP_BUCKETS },
9779 { "Keep old hashmap size since old size not multiple of old fragment count",
9780 5, 84, 7, 42, 84 },
9781 { "Shrink hashmap",
9782 3, 120, 6, 60, 60 },
9783 };
9784
9785 Bug14645319_createTable_args args;
9786 args.template_name = ctx->getTab()->getName();
9787 args.name = "Bug14645319";
9788
9789 for (size_t testi = 0; testi < NDB_ARRAY_SIZE(test_cases); testi++)
9790 {
9791 test_case const& test = test_cases[testi];
9792 int result = NDBT_FAILED;
9793
9794 int old_fragments = 0;
9795 int old_buckets = 0;
9796 int new_fragments = 0;
9797 int new_buckets = 0;
9798
9799 do {
9800 /* setup old table */
9801 args.buckets = test.old_buckets;
9802 args.fragments = test.old_fragments;
9803 result = NDBT_Tables::createTable(pNdb, args.template_name, false, false, Bug14645319_createTable, &args);
9804 if (result != 0) break;
9805
9806 NdbDictionary::Table const& old_tab = *pDic->getTable(args.name);
9807
9808 /* check old table properties */
9809 NdbDictionary::HashMap old_hm;
9810 result = pDic->getHashMap(old_hm, &old_tab);
9811 if (result != 0) break;
9812
9813 old_fragments = old_tab.getFragmentCount();
9814 old_buckets = old_hm.getMapLen();
9815 if (old_fragments != test.old_fragments)
9816 {
9817 result = NDBT_FAILED;
9818 break;
9819 }
9820 if (old_buckets != test.old_buckets)
9821 {
9822 result = NDBT_FAILED;
9823 break;
9824 }
9825
9826 /* alter table */
9827 NdbDictionary::Table new_tab = old_tab;
9828 new_tab.setFragmentCount(test.new_fragments);
9829 if (test.new_fragments == 0)
9830 new_tab.setFragmentData(0, 0);
9831
9832 result = pDic->beginSchemaTrans();
9833 if (result != 0) break;
9834
9835 result = pDic->prepareHashMap(old_tab, new_tab, test.new_buckets);
9836
9837 result |= pDic->endSchemaTrans();
9838 if (result != 0) break;
9839
9840 result = pDic->alterTable(old_tab, new_tab);
9841 if (result != 0) break;
9842
9843 /* check */
9844 NdbDictionary::HashMap new_hm;
9845 result = pDic->getHashMap(new_hm, &new_tab);
9846 if (result != 0) break;
9847
9848 new_fragments = new_tab.getFragmentCount();
9849 new_buckets = new_hm.getMapLen();
9850
9851 if (test.expected_buckets > 0 &&
9852 new_buckets != test.expected_buckets)
9853 {
9854 result = NDBT_FAILED;
9855 break;
9856 }
9857 result = 0;
9858 } while (false);
9859
9860 result |= pDic->dropTable(args.name);
9861
9862 if (result == 0)
9863 {
9864 ndbout << "Test#" << (testi + 1) << " '" << test_cases[testi].description << "' passed" <<
9865 " (" << old_buckets << " => " << test_cases[testi].new_buckets << " => " << test_cases[testi].expected_buckets << ")" << endl;
9866 }
9867 else
9868 {
9869 ndbout << "Test#" << (testi + 1) << " '" << test_cases[testi].description << "' failed" <<
9870 " (" << old_buckets << " => " << test_cases[testi].new_buckets << " => " << new_buckets << " expected: " << test_cases[testi].expected_buckets << ")" << endl;
9871 failures++;
9872 }
9873 }
9874
9875 return failures > 0 ? NDBT_FAILED : NDBT_OK;
9876 }
9877
9878 // FK SR/NR
9879
9880 #define CHK1(b) CHK2(b, "-");
9881
9882 // myRandom48 seems too non-random
9883 #define myRandom48(x) (unsigned(ndb_rand()) % (x))
9884 #define myRandom48Init(x) (ndb_srand(x))
9885
9886 // used for create and verify
9887 struct Fkdef {
9888 static const int tabmax = 5;
9889 static const int colmax = 5;
9890 static const int indmax = 5;
9891 static const int keymax = tabmax * 5;
9892 static const int strmax = 10;
9893 struct Ob {
9894 bool retrieved;
9895 int id;
9896 int version;
9897 };
9898 struct Col {
9899 char colname[strmax];
9900 bool pk;
9901 bool nullable; // false
9902 int icol; // pos in table columns
9903 };
9904 struct Ind : Ob {
9905 char indname[strmax];
9906 Col col[colmax];
9907 int ncol;
9908 bool pk;
9909 bool unique;
9910 const NdbDictionary::Index* pInd;
9911 };
9912 struct Tab : Ob {
9913 char tabname[strmax];
9914 Col col[colmax];
9915 int ncol;
9916 Ind ind[indmax]; // first "index" is primary key
9917 int nind;
9918 const NdbDictionary::Table* pTab;
9919 };
9920 struct Key : Ob {
9921 char keyname[strmax];
9922 char fullname[20 + strmax]; // bug#19122346
9923 // 0-parent 1-child
9924 const Tab* tab0;
9925 const Tab* tab1;
9926 const Ind* ind0;
9927 const Ind* ind1;
9928 NdbDictionary::ForeignKey::FkAction updateAction;
9929 NdbDictionary::ForeignKey::FkAction deleteAction;
9930 };
9931 struct List {
9932 NdbDictionary::Dictionary::List* list;
9933 int keystart; // FK stuff sorted to end of list starts here
ListFkdef::List9934 List() { list = 0; }
~ListFkdef::List9935 ~List() { delete list; }
9936 };
9937 Tab tab[tabmax];
9938 int ntab;
9939 Key key[keymax];
9940 int nkey;
9941 List list;
9942 bool nokeys;
9943 bool nodrop;
9944 int testcase;
9945 };
9946
9947 static int
fk_compare_icol(const void * p1,const void * p2)9948 fk_compare_icol(const void* p1, const void* p2)
9949 {
9950 const Fkdef::Col& col1 = *(const Fkdef::Col*)p1;
9951 const Fkdef::Col& col2 = *(const Fkdef::Col*)p2;
9952 return col1.icol - col2.icol;
9953 }
9954
9955 static int
fk_type(int t)9956 fk_type(int t)
9957 {
9958 if (
9959 t == NdbDictionary::Object::ForeignKey ||
9960 t == NdbDictionary::Object::FKParentTrigger ||
9961 t == NdbDictionary::Object::FKChildTrigger
9962 )
9963 return 1;
9964 return 0;
9965 }
9966
9967 static int
fk_compare_element(const void * p1,const void * p2)9968 fk_compare_element(const void* p1, const void* p2)
9969 {
9970 const NdbDictionary::Dictionary::List::Element& e1 =
9971 *(const NdbDictionary::Dictionary::List::Element*)p1;
9972 const NdbDictionary::Dictionary::List::Element& e2 =
9973 *(const NdbDictionary::Dictionary::List::Element*)p2;
9974 int k = 0;
9975 if ((k = fk_type(e1.type) - fk_type(e2.type)) != 0)
9976 return k;
9977 if ((k = e1.type - e2.type) != 0)
9978 return k;
9979 if ((k = (int)e1.id - (int)e2.id) != 0)
9980 return k;
9981 return 0;
9982 }
9983
9984 static bool
fk_find_element(const Fkdef::List & list,int type,const char * database,const char * name)9985 fk_find_element(const Fkdef::List& list, int type,
9986 const char* database, const char* name)
9987 {
9988 int found = 0;
9989 for (int i = 0; i < (int)list.list->count; i++)
9990 {
9991 const NdbDictionary::Dictionary::List::Element& e =
9992 list.list->elements[i];
9993 if (e.type == type &&
9994 strcmp(e.database, database) == 0 &&
9995 strcmp(e.name, name) == 0)
9996 {
9997 found++;
9998 }
9999 }
10000 require(found == 0 || found == 1);
10001 return found;
10002 }
10003
10004 // testcase 1: t0 (a0 pk, b0 key), t1 (a1 pk, b1 key), fk b1->a0
10005
10006 static void
fk_define_tables1(Fkdef & d)10007 fk_define_tables1(Fkdef& d)
10008 {
10009 d.ntab = 2;
10010 for (int i = 0; i < d.ntab; i++)
10011 {
10012 Fkdef::Tab& dt = d.tab[i];
10013 sprintf(dt.tabname, "t%d", i);
10014 dt.ncol = 2;
10015 for (int j = 0; j < dt.ncol; j++)
10016 {
10017 Fkdef::Col& dc = dt.col[j];
10018 sprintf(dc.colname, "%c%d", 'a' + j, i);
10019 dc.pk = (j == 0);
10020 dc.nullable = false;
10021 dc.icol = j;
10022 }
10023 dt.nind = 2;
10024 dt.pTab = 0;
10025 dt.retrieved = false;
10026 {
10027 Fkdef::Ind& di = dt.ind[0];
10028 sprintf(di.indname, "%s", "pk");
10029 di.ncol = 1;
10030 di.col[0] = dt.col[0];
10031 di.pk = true;
10032 di.unique = true;
10033 di.pInd = 0;
10034 di.retrieved = false;
10035 }
10036 {
10037 Fkdef::Ind& di = dt.ind[1];
10038 sprintf(di.indname, "t%dx%d", i, 1);
10039 di.ncol = 1;
10040 di.col[0] = dt.col[1];
10041 di.pk = false;
10042 di.unique = false;
10043 di.pInd = 0;
10044 di.retrieved = false;
10045 }
10046 }
10047 g_info << "defined " << d.ntab << " tables" << endl;
10048 }
10049
10050 static void
fk_define_keys1(Fkdef & d)10051 fk_define_keys1(Fkdef& d)
10052 {
10053 d.nkey = 1;
10054 Fkdef::Key& dk = d.key[0];
10055 sprintf(dk.keyname, "fk%d", 0);
10056 dk.tab0 = &d.tab[0];
10057 dk.tab1 = &d.tab[1];
10058 dk.ind0 = &dk.tab0->ind[0];
10059 dk.ind1 = &dk.tab1->ind[1];
10060 dk.updateAction = NdbDictionary::ForeignKey::NoAction;
10061 dk.deleteAction = NdbDictionary::ForeignKey::NoAction;
10062 dk.retrieved = false;
10063 g_info << "defined " << d.nkey << " keys" << endl;
10064 }
10065
10066 // testcase 2: random
10067
10068 static void
fk_define_tables2(Fkdef & d)10069 fk_define_tables2(Fkdef& d)
10070 {
10071 d.ntab = 1 + myRandom48(d.tabmax);
10072 for (int i = 0; i < d.ntab; i++)
10073 {
10074 Fkdef::Tab& dt = d.tab[i];
10075 sprintf(dt.tabname, "t%d", i);
10076 dt.ncol = 2 + myRandom48(d.colmax - 1);
10077 for (int j = 0; j < dt.ncol; j++)
10078 {
10079 Fkdef::Col& dc = dt.col[j];
10080 sprintf(dc.colname, "%c%d", 'a' + j, i);
10081 dc.pk = (j == 0 || myRandom48(d.colmax) == 0);
10082 dc.nullable = false;
10083 dc.icol = j;
10084 }
10085 dt.nind = 1 + myRandom48(d.indmax);
10086 dt.pTab = 0;
10087 dt.retrieved = false;
10088 for (int k = 0; k < dt.nind; k++)
10089 {
10090 Fkdef::Ind& di = dt.ind[k];
10091 if (k == 0)
10092 {
10093 sprintf(di.indname, "%s", "pk");
10094 di.ncol = 0;
10095 for (int j = 0; j < dt.ncol; j++)
10096 {
10097 Fkdef::Col& dc = dt.col[j];
10098 if (dc.pk)
10099 di.col[di.ncol++] = dc;
10100 }
10101 di.pk = true;
10102 di.unique = true;
10103 }
10104 else
10105 {
10106 di.unique = (myRandom48(3) != 0);
10107 sprintf(di.indname, "t%dx%d", i, k);
10108 di.ncol = 1 + myRandom48(dt.ncol);
10109 uint mask = 0;
10110 int n = 0;
10111 while (n < di.ncol)
10112 {
10113 int j = myRandom48(dt.ncol);
10114 Fkdef::Col& dc = dt.col[j];
10115 if ((mask & (1 << j)) == 0)
10116 {
10117 di.col[n++] = dc;
10118 mask |= (1 << j);
10119 }
10120 }
10121 if (di.unique)
10122 qsort(&di.col, di.ncol, sizeof(di.col[0]), fk_compare_icol);
10123 }
10124 di.pInd = 0;
10125 di.retrieved = false;
10126 }
10127 }
10128 g_info << "defined " << d.ntab << " tables" << endl;
10129 }
10130
10131 static void
fk_define_keys2(Fkdef & d)10132 fk_define_keys2(Fkdef& d)
10133 {
10134 int nkey = 1 + myRandom48(d.ntab * 5);
10135 int k = 0;
10136 int ntrymax = nkey * 100;
10137 int ntry = 0;
10138 while (k < nkey && ntry++ < ntrymax)
10139 {
10140 Fkdef::Key& dk = d.key[k];
10141 new (&dk) Fkdef::Key;
10142 int i0 = myRandom48(d.ntab);
10143 int i1 = myRandom48(d.ntab);
10144 Fkdef::Tab& dt0 = d.tab[i0];
10145 Fkdef::Tab& dt1 = d.tab[i1];
10146 int k0 = myRandom48(dt0.nind);
10147 int k1 = myRandom48(dt1.nind);
10148 Fkdef::Ind& di0 = dt0.ind[k0];
10149 Fkdef::Ind& di1 = dt1.ind[k1];
10150 if (!di0.unique || di0.ncol != di1.ncol)
10151 continue;
10152 if (i0 == i1 && k0 == k1)
10153 if (myRandom48(10) != 0) // allowed but try to avoid
10154 continue;
10155 sprintf(dk.keyname, "fk%d", k);
10156 dk.tab0 = &dt0;
10157 dk.tab1 = &dt1;
10158 dk.ind0 = &di0;
10159 dk.ind1 = &di1;
10160 dk.updateAction = NdbDictionary::ForeignKey::NoAction;
10161 dk.deleteAction = NdbDictionary::ForeignKey::NoAction;
10162 dk.retrieved = false;
10163 k++;
10164 }
10165 d.nkey = k;
10166 g_info << "defined " << d.nkey << " keys tries:" << ntry << endl;
10167 }
10168
10169 static void
fk_define_tables(Fkdef & d)10170 fk_define_tables(Fkdef& d)
10171 {
10172 if (d.testcase == 1)
10173 fk_define_tables1(d);
10174 else if (d.testcase == 2)
10175 fk_define_tables2(d);
10176 else
10177 require(false);
10178 }
10179
10180 static void
fk_define_keys(Fkdef & d)10181 fk_define_keys(Fkdef& d)
10182 {
10183 if (d.nokeys)
10184 {
10185 d.nkey = 0;
10186 return;
10187 }
10188 if (d.testcase == 1)
10189 fk_define_keys1(d);
10190 else if (d.testcase == 2)
10191 fk_define_keys2(d);
10192 else
10193 require(false);
10194 }
10195
10196 static void
fk_undefine_keys(Fkdef & d)10197 fk_undefine_keys(Fkdef& d)
10198 {
10199 d.nkey = 0;
10200 }
10201
10202 static void
fk_define_all(Fkdef & d)10203 fk_define_all(Fkdef& d)
10204 {
10205 fk_define_tables(d);
10206 fk_define_keys(d);
10207 }
10208
10209 static int
fk_create_table(Fkdef & d,Ndb * pNdb,int i)10210 fk_create_table(Fkdef& d, Ndb* pNdb, int i)
10211 {
10212 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10213 int result = NDBT_OK;
10214 do
10215 {
10216 Fkdef::Tab& dt = d.tab[i];
10217 NdbDictionary::Table tab;
10218 tab.setName(dt.tabname);
10219 for (int j = 0; j < dt.ncol; j++)
10220 {
10221 Fkdef::Col& dc = dt.col[j];
10222 NdbDictionary::Column col;
10223 col.setName(dc.colname);
10224 col.setType(NdbDictionary::Column::Unsigned);
10225 col.setPrimaryKey(dc.pk);
10226 col.setNullable(dc.nullable);
10227 tab.addColumn(col);
10228 }
10229 g_info << "create table " << dt.tabname << endl;
10230 CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
10231 const NdbDictionary::Table* pTab = 0;
10232 CHK2((pTab = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
10233 require(!dt.retrieved);
10234 dt.retrieved = true;
10235 dt.id = pTab->getObjectId();
10236 dt.version = pTab->getObjectVersion();
10237 dt.pTab = pTab;
10238 for (int k = 1; k < dt.nind; k++) // skip pk
10239 {
10240 Fkdef::Ind& di = dt.ind[k];
10241 NdbDictionary::Index ind;
10242 ind.setName(di.indname);
10243 ind.setTable(dt.tabname);
10244 if (di.unique)
10245 {
10246 ind.setType(NdbDictionary::Index::UniqueHashIndex);
10247 ind.setLogging(true);
10248 }
10249 else
10250 {
10251 ind.setType(NdbDictionary::Index::OrderedIndex);
10252 ind.setLogging(false);
10253 }
10254 for (int j = 0; j < di.ncol; j++)
10255 {
10256 const Fkdef::Col& dc = di.col[j];
10257 ind.addColumn(dc.colname);
10258 }
10259 g_info << "create index " << di.indname << endl;
10260 CHK2(pDic->createIndex(ind) == 0, pDic->getNdbError());
10261 const NdbDictionary::Index* pInd = 0;
10262 CHK2((pInd = pDic->getIndex(di.indname, dt.tabname)) != 0, pDic->getNdbError());
10263 require(!di.retrieved);
10264 di.retrieved = true;
10265 di.id = pInd->getObjectId();
10266 di.version = pInd->getObjectVersion();
10267 di.pInd = pInd;
10268 }
10269 }
10270 while (0);
10271 return result;
10272 }
10273
10274 static int
fk_create_tables(Fkdef & d,Ndb * pNdb)10275 fk_create_tables(Fkdef& d, Ndb* pNdb)
10276 {
10277 int result = NDBT_OK;
10278 for (int i = 0; i < d.ntab; i++)
10279 {
10280 CHK1(fk_create_table(d, pNdb, i) == NDBT_OK);
10281 }
10282 return result;
10283 }
10284
10285 static int
fk_create_key(Fkdef & d,Ndb * pNdb,int k)10286 fk_create_key(Fkdef& d, Ndb* pNdb, int k)
10287 {
10288 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10289 int result = NDBT_OK;
10290 do
10291 {
10292 Fkdef::Key& dk = d.key[k];
10293 NdbDictionary::ForeignKey key;
10294 key.setName(dk.keyname);
10295 const Fkdef::Tab& dt0 = *dk.tab0;
10296 const Fkdef::Tab& dt1 = *dk.tab1;
10297 const Fkdef::Ind& di0 = *dk.ind0;
10298 const Fkdef::Ind& di1 = *dk.ind1;
10299 const NdbDictionary::Table* pTab0 = dt0.pTab;
10300 const NdbDictionary::Table* pTab1 = dt1.pTab;
10301 const NdbDictionary::Index* pInd0 = di0.pInd;
10302 const NdbDictionary::Index* pInd1 = di1.pInd;
10303 key.setParent(*pTab0, pInd0);
10304 key.setChild(*pTab1, pInd1);
10305 g_info << "create key " << dk.keyname << endl;
10306 CHK2(pDic->createForeignKey(key) == 0, pDic->getNdbError());
10307 {
10308 NdbDictionary::ForeignKey key;
10309 sprintf(dk.fullname, "%d/%d/%s", dt0.id, dt1.id, dk.keyname);
10310 CHK2(pDic->getForeignKey(key, dk.fullname) == 0, pDic->getNdbError());
10311 require(!dk.retrieved);
10312 dk.retrieved = true;
10313 dk.id = key.getObjectId();
10314 dk.version = key.getObjectVersion();
10315 }
10316 }
10317 while (0);
10318 return result;
10319 }
10320
10321 static int
fk_create_keys(Fkdef & d,Ndb * pNdb)10322 fk_create_keys(Fkdef& d, Ndb* pNdb)
10323 {
10324 int result = NDBT_OK;
10325 for (int k = 0; k < d.nkey; k++)
10326 {
10327 CHK1(fk_create_key(d, pNdb, k) == NDBT_OK);
10328 }
10329 return result;
10330 }
10331
10332 static int
fk_alter_table(Fkdef & d,Ndb * pNdb,int i)10333 fk_alter_table(Fkdef& d, Ndb* pNdb, int i)
10334 {
10335 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10336 int result = NDBT_OK;
10337 do
10338 {
10339 Fkdef::Tab& dt = d.tab[i];
10340 const NdbDictionary::Table* pTab1 = 0;
10341 CHK2((pTab1 = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
10342 g_info << "alter table " << dt.tabname << endl;
10343 int id1 = pTab1->getObjectId();
10344 int version1 = pTab1->getObjectVersion();
10345 g_info << "old: id=" << id1 << " version=" << hex << version1 << endl;
10346 CHK2(pDic->alterTable(*pTab1, *pTab1) == 0, pDic->getNdbError());
10347 pDic->invalidateTable(dt.tabname);
10348 const NdbDictionary::Table* pTab2 = 0;
10349 CHK2((pTab2 = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
10350 int id2 = pTab2->getObjectId();
10351 int version2 = pTab2->getObjectVersion();
10352 g_info << "old: id=" << id2 << " version=" << hex << version2 << endl;
10353 CHK2(id1 == id2, id1 << " != " << id2);
10354 CHK2(version1 != version2, version1 << " == " << version2);
10355 dt.id = id2;
10356 dt.version = version2;
10357 }
10358 while (0);
10359 return result;
10360 }
10361
10362 static int
fk_alter_tables(Fkdef & d,Ndb * pNdb,bool atrandom)10363 fk_alter_tables(Fkdef& d, Ndb* pNdb, bool atrandom)
10364 {
10365 int result = NDBT_OK;
10366 for (int i = 0; i < d.ntab; i++)
10367 {
10368 if (!atrandom || myRandom48(2) == 0)
10369 {
10370 CHK1(fk_alter_table(d, pNdb, i) == NDBT_OK);
10371 }
10372 }
10373 return result;
10374 }
10375
10376 static int
fk_create_all(Fkdef & d,Ndb * pNdb)10377 fk_create_all(Fkdef& d, Ndb* pNdb)
10378 {
10379 int result = NDBT_OK;
10380 do
10381 {
10382 CHK1(fk_create_tables(d, pNdb) == 0);
10383 CHK1(fk_create_keys(d, pNdb) == NDBT_OK);
10384 // imitate mysqld by doing an alter table afterwards
10385 CHK1(fk_alter_tables(d, pNdb, true) == NDBT_OK);
10386 }
10387 while (0);
10388 return result;
10389 }
10390
10391 static int
fk_verify_table(const Fkdef & d,Ndb * pNdb,int i)10392 fk_verify_table(const Fkdef& d, Ndb* pNdb, int i)
10393 {
10394 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10395 int result = NDBT_OK;
10396 do
10397 {
10398 const Fkdef::Tab& dt = d.tab[i];
10399 g_info << "verify table " << dt.tabname << endl;
10400 const NdbDictionary::Table* pTab = 0;
10401 CHK2((pTab = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
10402 int id = pTab->getObjectId();
10403 int version = pTab->getObjectVersion();
10404 require(dt.retrieved);
10405 CHK2(dt.id == id, dt.id << " != " << id);
10406 CHK2(dt.version == version, dt.version << " != " << version);
10407 for (int k = 1; k < dt.nind; k++) // skip pk
10408 {
10409 const Fkdef::Ind& di = dt.ind[k];
10410 g_info << "verify index " << di.indname << endl;
10411 const NdbDictionary::Index* pInd = 0;
10412 CHK2((pInd = pDic->getIndex(di.indname, dt.tabname)) != 0, pDic->getNdbError());
10413 int id = pInd->getObjectId();
10414 int version = pInd->getObjectVersion();
10415 require(di.retrieved);
10416 CHK2(di.id == id, di.id << " != " << id);
10417 CHK2(di.version == version, di.version << " != " << version);
10418 }
10419 CHK1(result == NDBT_OK);
10420 }
10421 while (0);
10422 return result;
10423 }
10424
10425 static int
fk_verify_tables(const Fkdef & d,Ndb * pNdb)10426 fk_verify_tables(const Fkdef& d, Ndb* pNdb)
10427 {
10428 int result = NDBT_OK;
10429 for (int i = 0; i < d.ntab; i++)
10430 {
10431 CHK1(fk_verify_table(d, pNdb, i) == 0);
10432 }
10433 return result;
10434 }
10435
10436 static int
fk_verify_key(const Fkdef & d,Ndb * pNdb,int k)10437 fk_verify_key(const Fkdef& d, Ndb* pNdb, int k)
10438 {
10439 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10440 int result = NDBT_OK;
10441 do
10442 {
10443 const Fkdef::Key& dk = d.key[k];
10444 g_info << "verify key " << dk.fullname << endl;
10445 NdbDictionary::ForeignKey key;
10446 CHK2(pDic->getForeignKey(key, dk.fullname) == 0, pDic->getNdbError());
10447 int id = key.getObjectId();
10448 int version = key.getObjectVersion();
10449 require(dk.retrieved);
10450 CHK2(dk.id == id, dk.id << " != " << id);
10451 CHK2(dk.version == version, dk.version << " != " << version);
10452 CHK2(strcmp(dk.fullname, key.getName()) == 0, dk.fullname << " != " << key.getName());
10453 #if 0 // can add more checks
10454 const Fkdef::Tab& dt0 = *dk.tab0;
10455 const Fkdef::Tab& dt1 = *dk.tab1;
10456 const Fkdef::Ind& di0 = *dk.ind0;
10457 const Fkdef::Ind& di1 = *dk.ind1;
10458 #endif
10459 }
10460 while (0);
10461 return result;
10462 }
10463
10464 static int
fk_verify_keys(const Fkdef & d,Ndb * pNdb)10465 fk_verify_keys(const Fkdef& d, Ndb* pNdb)
10466 {
10467 int result = NDBT_OK;
10468 for (int k = 0; k < d.nkey; k++)
10469 {
10470 CHK1(fk_verify_key(d, pNdb, k) == 0);
10471 }
10472 return result;
10473 }
10474
10475 static int
fk_verify_ddl(const Fkdef & d,Ndb * pNdb)10476 fk_verify_ddl(const Fkdef& d, Ndb* pNdb)
10477 {
10478 int result = NDBT_OK;
10479 do
10480 {
10481 g_info << "verify ddl" << endl;
10482 CHK1(fk_verify_tables(d, pNdb) == 0);
10483 CHK1(fk_verify_keys(d, pNdb) == 0);
10484 }
10485 while (0);
10486 return result;
10487 }
10488
10489 static int
fk_verify_dml(const Fkdef & d,Ndb * pNdb,int records)10490 fk_verify_dml(const Fkdef& d, Ndb* pNdb, int records)
10491 {
10492 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10493 int result = NDBT_OK;
10494 const int batch = 1;
10495 const bool allowCV = false;
10496 const int errNoParent = 255;
10497 const int errHasChild = 256;
10498 do
10499 {
10500 if (!(d.testcase == 1 && records > 0))
10501 break;
10502 g_info << "verify dml" << endl;
10503 const Fkdef::Tab& dt0 = d.tab[0];
10504 const Fkdef::Tab& dt1 = d.tab[1];
10505 const NdbDictionary::Table* pTab0 = 0;
10506 const NdbDictionary::Table* pTab1 = 0;
10507 CHK2((pTab0 = pDic->getTable(dt0.tabname)) != 0, pDic->getNdbError());
10508 CHK2((pTab1 = pDic->getTable(dt1.tabname)) != 0, pDic->getNdbError());
10509 HugoTransactions tx0(*pTab0);
10510 HugoTransactions tx1(*pTab1);
10511 // insert into child t1 - not ok
10512 g_err << "expect error " << errNoParent << endl;
10513 CHK1(tx1.loadTable(pNdb, records, batch, allowCV) != 0);
10514 CHK2(tx1.getNdbError().code == errNoParent, tx1.getNdbError());
10515 // insert into parent t0 - ok
10516 CHK2(tx0.loadTable(pNdb, records, batch, allowCV) == 0,
10517 tx0.getNdbError());
10518 // insert into child t1 - ok (b1 is 0, a0 is 0,1,2,..)
10519 CHK2(tx1.loadTable(pNdb, records, batch, allowCV) == 0,
10520 tx1.getNdbError());
10521 // delete from parent - not ok
10522 g_err << "expect error " << errHasChild << endl;
10523 CHK1(tx0.pkDelRecords(pNdb, records, batch, allowCV) != 0);
10524 CHK2(tx0.getNdbError().code == errHasChild, tx0.getNdbError());
10525 // delete from child t1 - ok
10526 CHK2(tx1.pkDelRecords(pNdb, records, batch, allowCV) == 0,
10527 tx1.getNdbError());
10528 // delete from parent to - ok
10529 CHK2(tx0.pkDelRecords(pNdb, records, batch, allowCV) == 0,
10530 tx0.getNdbError());
10531 }
10532 while (0);
10533 return result;
10534 }
10535
10536 static int
fk_retrieve_list(Fkdef & d,Ndb * pNdb,Fkdef::List & list)10537 fk_retrieve_list(Fkdef& d, Ndb* pNdb, Fkdef::List& list)
10538 {
10539 (void)d;
10540 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10541 int result = NDBT_OK;
10542 do
10543 {
10544 g_info << "list objects" << endl;
10545 require(list.list == 0);
10546 list.list = new NdbDictionary::Dictionary::List;
10547 CHK2(pDic->listObjects(*list.list) == 0, pDic->getNdbError());
10548 qsort(list.list->elements, list.list->count, sizeof(list.list->elements[0]),
10549 fk_compare_element);
10550 list.keystart = 0;
10551 for (int i = 0; i < (int)list.list->count; i++)
10552 {
10553 NdbDictionary::Dictionary::List::Element& e =
10554 list.list->elements[i];
10555 if (e.database == 0)
10556 {
10557 e.database = new char [1];
10558 e.database[0] = 0;
10559 }
10560 if (!fk_type(e.type))
10561 list.keystart++;
10562 g_info << "ob " << i << ":"
10563 << " type=" << e.type << " id=" << e.id
10564 << " db=" << e.database << " name=" << e.name << endl;
10565 if (i > 0)
10566 {
10567 const NdbDictionary::Dictionary::List::Element& e2 =
10568 list.list->elements[i - 1];
10569 CHK1(e.type != e2.type || e.id != e2.id);
10570 }
10571 }
10572 g_info << "list count=" << list.list->count
10573 << " keystart=" << list.keystart << endl;
10574 }
10575 while (0);
10576 return result;
10577 }
10578
10579 static int
fk_verify_list(Fkdef & d,Ndb * pNdb,bool ignore_keys)10580 fk_verify_list(Fkdef& d, Ndb* pNdb, bool ignore_keys)
10581 {
10582 int result = NDBT_OK;
10583 do
10584 {
10585 Fkdef::List& list1 = d.list;
10586 if (list1.list == 0)
10587 {
10588 g_info << "retrieve first object list" << endl;
10589 CHK1(fk_retrieve_list(d, pNdb, list1) == 0);
10590 }
10591 else
10592 {
10593 g_info << "verify object list old vs new"
10594 " ignore_keys=" << ignore_keys << endl;
10595 Fkdef::List list2;
10596 CHK1(fk_retrieve_list(d, pNdb, list2) == NDBT_OK);
10597 // optionally ignore FK stuff in either list
10598 int count1 = !ignore_keys ? list1.list->count : list1.keystart;
10599 int count2 = !ignore_keys ? list2.list->count : list2.keystart;
10600 CHK1(count1 == count2);
10601 for (int i = 0; i < count1; i++)
10602 {
10603 const NdbDictionary::Dictionary::List::Element& e1 =
10604 list1.list->elements[i];
10605 const NdbDictionary::Dictionary::List::Element& e2 =
10606 list2.list->elements[i];
10607 CHK2(e1.type == e2.type,
10608 i << ": " << e1.type << " != " << e2.type);
10609 CHK2(e1.id == e2.id,
10610 i << ": " << e1.id << " != " << e2.id);
10611 CHK2(strcmp(e1.database, e2.database) == 0,
10612 i << ": " << e1.database << " != " << e2.database);
10613 CHK2(strcmp(e1.name, e2.name) == 0,
10614 i << ": " << e1.name << " != " << e2.name);
10615 }
10616 CHK1(result == NDBT_OK);
10617 // replace old by new
10618 delete list1.list;
10619 list1.list = list2.list;
10620 list1.keystart = list2.keystart;
10621 list2.list = 0;
10622 }
10623 // verify objects vs list
10624 for (int i = 0; i < d.ntab; i++)
10625 {
10626 const Fkdef::Tab& dt = d.tab[i];
10627 CHK2(fk_find_element(list1, NdbDictionary::Object::UserTable,
10628 "TEST_DB", dt.tabname), dt.tabname);
10629 for (int k = 1; k < dt.nind; k++)
10630 {
10631 const Fkdef::Ind& di = dt.ind[k];
10632 if (di.unique)
10633 {
10634 CHK2(fk_find_element(list1, NdbDictionary::Object::UniqueHashIndex,
10635 "sys", di.indname), di.indname);
10636 }
10637 else
10638 {
10639 CHK2(fk_find_element(list1, NdbDictionary::Object::OrderedIndex,
10640 "sys", di.indname), di.indname);
10641 }
10642 }
10643 CHK1(result == NDBT_OK);
10644 }
10645 for (int k = 0; k < d.nkey; k++) {
10646 const Fkdef::Key& dk = d.key[k];
10647 CHK2(fk_find_element(list1, NdbDictionary::Object::ForeignKey,
10648 "", dk.fullname), dk.fullname);
10649 // could also check FK triggers..
10650 }
10651 CHK1(result == NDBT_OK);
10652 }
10653 while (0);
10654 return result;
10655 }
10656
10657 static int
fk_drop_table(Fkdef & d,Ndb * pNdb,int i,bool force)10658 fk_drop_table(Fkdef& d, Ndb* pNdb, int i, bool force)
10659 {
10660 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10661 int result = NDBT_OK;
10662 do
10663 {
10664 Fkdef::Tab& dt = d.tab[i];
10665 g_info << "drop table " << dt.tabname
10666 << (force ? " (force)" : "") << endl;
10667 if (pDic->dropTable(dt.tabname) != 0)
10668 {
10669 const NdbError& err = pDic->getNdbError();
10670 CHK2(force, err);
10671 CHK2(err.code == 709 || err.code == 723, err);
10672 break;
10673 }
10674 // all indexes are dropped by ndb api
10675 // all related FKs child/parent are dropped by ndb api
10676 }
10677 while (0);
10678 return result;
10679 }
10680
10681 static int
fk_drop_tables(Fkdef & d,Ndb * pNdb,bool force)10682 fk_drop_tables(Fkdef& d, Ndb* pNdb, bool force)
10683 {
10684 int result = NDBT_OK;
10685 for (int i = 0; i < d.ntab; i++)
10686 {
10687 CHK1(fk_drop_table(d, pNdb, i, force) == NDBT_OK);
10688 }
10689 return result;
10690 }
10691
10692 static int
fk_drop_key(Fkdef & d,Ndb * pNdb,int k,bool force)10693 fk_drop_key(Fkdef& d, Ndb* pNdb, int k, bool force)
10694 {
10695 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10696 int result = NDBT_OK;
10697 do
10698 {
10699 Fkdef::Key& dk = d.key[k];
10700 g_info << "drop key " << dk.fullname
10701 << (force ? " (force)" : "") << endl;
10702 NdbDictionary::ForeignKey key;
10703 if (pDic->getForeignKey(key, dk.fullname) != 0)
10704 {
10705 const NdbError& err = pDic->getNdbError();
10706 CHK2(force, err);
10707 CHK2(err.code == 709 || err.code == 723 || err.code == 21040, err);
10708 break;
10709 }
10710 CHK2(pDic->dropForeignKey(key) == 0, pDic->getNdbError());
10711 }
10712 while (0);
10713 return result;
10714 }
10715
10716 static int
fk_drop_keys(Fkdef & d,Ndb * pNdb,bool force)10717 fk_drop_keys(Fkdef& d, Ndb* pNdb, bool force)
10718 {
10719 int result = NDBT_OK;
10720 for (int k = 0; k < d.nkey; k++)
10721 {
10722 CHK1(fk_drop_key(d, pNdb, k, force) == NDBT_OK);
10723 }
10724 return result;
10725 }
10726
10727 static int
fk_drop_all(Fkdef & d,Ndb * pNdb,bool force)10728 fk_drop_all(Fkdef& d, Ndb* pNdb, bool force)
10729 {
10730 int result = NDBT_OK;
10731 do
10732 {
10733 CHK1(fk_drop_keys(d, pNdb, force) == NDBT_OK);
10734 CHK1(fk_drop_tables(d, pNdb, force) == NDBT_OK);
10735 }
10736 while (0);
10737 return result;
10738 }
10739
10740 // commit drop
10741
10742 // just reset all retrieved
10743 static void
fk_dropped_all(Fkdef & d)10744 fk_dropped_all(Fkdef& d)
10745 {
10746 for (int i = 0; i < d.ntab; i++)
10747 {
10748 Fkdef::Tab& dt = d.tab[i];
10749 dt.retrieved = false;
10750 for (int k = 0; k < dt.nind; k++)
10751 {
10752 Fkdef::Ind& di = dt.ind[k];
10753 di.retrieved = false;
10754 }
10755 }
10756 for (int k = 0; k < d.nkey; k++)
10757 {
10758 Fkdef::Key& dk = d.key[k];
10759 dk.retrieved = false;
10760 }
10761 }
10762
10763 // for FK_Bug18069680
10764
10765 static int
fk_create_all_random(Fkdef & d,Ndb * pNdb)10766 fk_create_all_random(Fkdef& d, Ndb* pNdb)
10767 {
10768 int result = NDBT_OK;
10769 int ntab = 0;
10770 int nkey = 0;
10771 do
10772 {
10773 for (int i = 0; i < d.ntab; i++)
10774 {
10775 Fkdef::Tab& dt = d.tab[i];
10776 if (!dt.retrieved && myRandom48(3) == 0)
10777 {
10778 CHK1(fk_create_table(d, pNdb, i) == 0);
10779 require(dt.retrieved);
10780 ntab++;
10781 }
10782 }
10783 CHK1(result == NDBT_OK);
10784 for (int k = 0; k < d.nkey; k++)
10785 {
10786 Fkdef::Key& dk = d.key[k];
10787 if (!dk.retrieved && myRandom48(3) == 0 &&
10788 dk.tab0->retrieved && dk.tab1->retrieved)
10789 {
10790 CHK1(fk_create_key(d, pNdb, k) == 0);
10791 require(dk.retrieved);
10792 nkey++;
10793 }
10794 }
10795 CHK1(result == NDBT_OK);
10796 require(ntab <= d.ntab && nkey <= d.nkey);
10797 }
10798 while (ntab < d.ntab || nkey < d.nkey);
10799 return result;
10800 }
10801
10802 static int
fk_drop_indexes_under(const Fkdef & d,Ndb * pNdb)10803 fk_drop_indexes_under(const Fkdef& d, Ndb* pNdb)
10804 {
10805 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10806 int result = NDBT_OK;
10807 do
10808 {
10809 for (int i = 0; i < d.ntab; i++)
10810 {
10811 const Fkdef::Tab& dt = d.tab[i];
10812 for (int k = 1; k < dt.nind; k++) // skip pk
10813 {
10814 const Fkdef::Ind& di = dt.ind[k];
10815 int parent = 0;
10816 int child = 0;
10817 for (int m = 0; m < d.nkey; m++)
10818 {
10819 const Fkdef::Key& dk = d.key[m];
10820 if (dk.ind0 == &di)
10821 parent++;
10822 if (dk.ind1 == &di)
10823 child++;
10824 }
10825 if (parent != 0 || child != 0)
10826 {
10827 // drop must fail
10828 g_info << "try to drop index under " << di.indname
10829 << " parent:" << parent << " child:" << child << endl;
10830 int ret = pDic->dropIndex(di.indname, dt.tabname);
10831 CHK2(ret != 0, "no error on drop underlying index");
10832 const NdbError& err = pDic->getNdbError();
10833 // could be either error code depending on check order
10834 CHK2(err.code == 21081 || err.code == 21082, pDic->getNdbError());
10835 }
10836 }
10837 CHK1(result == NDBT_OK);
10838 }
10839 CHK1(result == NDBT_OK);
10840 }
10841 while (0);
10842 return result;
10843 }
10844
10845 // for manual testing
10846 static void
fk_env_options(Fkdef & d)10847 fk_env_options(Fkdef& d)
10848 {
10849 // random seed
10850 int seed = (int)getpid();
10851 #ifdef NDB_USE_GET_ENV
10852 {
10853 const char* p = NdbEnv_GetEnv("RANDOM_SEED", (char*)0, 0);
10854 if (p != 0)
10855 seed = atoi(p);
10856 }
10857 #endif
10858 myRandom48Init(seed);
10859 g_err << "random seed: " << seed << endl;
10860 // create no FKs at all
10861 d.nokeys = false;
10862 #ifdef NDB_USE_GET_ENV
10863 {
10864 const char* p = NdbEnv_GetEnv("FK_NOKEYS", (char*)0, 0);
10865 if (p != 0 && strchr("1Y", p[0]) != 0)
10866 d.nokeys = true;
10867 }
10868 #endif
10869 // do not drop objects at end
10870 d.nodrop = false;
10871 #ifdef NDB_USE_GET_ENV
10872 {
10873 const char* p = NdbEnv_GetEnv("FK_NODROP", (char*)0, 0);
10874 if (p != 0 && strchr("1Y", p[0]) != 0)
10875 d.nodrop = true;
10876 }
10877 #endif
10878 }
10879
10880 int
runFK_SRNR(NDBT_Context * ctx,NDBT_Step * step)10881 runFK_SRNR(NDBT_Context* ctx, NDBT_Step* step)
10882 {
10883 Ndb* pNdb = GETNDB(step);
10884 const int loops = ctx->getNumLoops();
10885 const int records = ctx->getNumRecords();
10886 int result = NDBT_OK;
10887
10888 NdbRestarter restarter;
10889 const int numdbnodes = restarter.getNumDbNodes();
10890
10891 Fkdef d;
10892 d.testcase = ctx->getProperty("testcase", (Uint32)0);
10893 fk_env_options(d);
10894 fk_define_all(d);
10895
10896 do
10897 {
10898 (void)fk_drop_all(d, pNdb, true);
10899 CHK1(fk_create_all(d, pNdb) == NDBT_OK);
10900 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
10901 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
10902 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
10903
10904 for (int loop = 0; loop < loops; loop++)
10905 {
10906 g_info << "loop " << loop << "<" << loops << endl;
10907
10908 bool rs = (numdbnodes == 1 || myRandom48(2) == 0);
10909 if (rs)
10910 {
10911 g_info << "restart all" << endl;
10912 CHK1(restarter.restartAll() == 0);
10913 }
10914 else
10915 {
10916 int i = myRandom48(numdbnodes);
10917 int nodeid = restarter.getDbNodeId(i);
10918 bool initial = (bool)myRandom48(2);
10919 bool nostart = true;
10920 g_info << "restart node " << nodeid << " initial=" << initial << endl;
10921
10922 CHK1(restarter.restartOneDbNode(nodeid, initial, nostart) == 0);
10923 CHK1(restarter.waitNodesNoStart(&nodeid, 1) == 0);
10924 g_info << "nostart node " << nodeid << endl;
10925
10926 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
10927 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
10928 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
10929
10930 g_info << "start node " << nodeid << endl;
10931 CHK1(restarter.startNodes(&nodeid, 1) == 0);
10932 }
10933
10934 CHK1(restarter.waitClusterStarted() == 0);
10935 g_info << "cluster is started" << endl;
10936
10937 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
10938 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
10939 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
10940 }
10941 CHK1(result == NDBT_OK);
10942
10943 if (!d.nodrop)
10944 {
10945 CHK1(fk_drop_all(d, pNdb, false) == NDBT_OK);
10946 }
10947 }
10948 while (0);
10949
10950 if (result != NDBT_OK)
10951 {
10952 if (!d.nodrop)
10953 (void)fk_drop_all(d, pNdb, true);
10954 }
10955 return result;
10956 }
10957
10958 int
runFK_TRANS(NDBT_Context * ctx,NDBT_Step * step)10959 runFK_TRANS(NDBT_Context* ctx, NDBT_Step* step)
10960 {
10961 Ndb* pNdb = GETNDB(step);
10962 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10963 const int loops = ctx->getNumLoops();
10964 const int records = ctx->getNumRecords();
10965 int result = NDBT_OK;
10966 const int abort_flag = NdbDictionary::Dictionary::SchemaTransAbort;
10967
10968 Fkdef d;
10969 d.testcase = ctx->getProperty("testcase", (Uint32)0);
10970 fk_env_options(d);
10971 fk_define_tables(d);
10972 fk_undefine_keys(d);
10973
10974 do
10975 {
10976 (void)fk_drop_all(d, pNdb, true);
10977 CHK1(fk_create_tables(d, pNdb) == NDBT_OK);
10978 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
10979 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
10980
10981 // what to do on loop % 3
10982 const int abort_loop[3][2] = { { 1, -1 }, { 0, 1 }, { 0, 0 } };
10983
10984 for (int loop = 0; loop < loops; loop++)
10985 {
10986 g_info << "loop " << loop << "<" << loops << endl;
10987
10988 int abort_create = abort_loop[loop % 3][0];
10989 require(abort_create == 0 || abort_create == 1);
10990 g_info << "abort create: " << abort_create << endl;
10991
10992 fk_define_keys(d);
10993 CHK2(pDic->beginSchemaTrans() == 0, pDic->getNdbError());
10994 CHK1(fk_create_keys(d, pNdb) == 0);
10995 if (!abort_create)
10996 {
10997 g_info << "commit schema trans" << endl;
10998 CHK2(pDic->endSchemaTrans(0) == 0, pDic->getNdbError());
10999 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11000 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11001 CHK1(fk_verify_list(d, pNdb, true) == NDBT_OK);
11002 }
11003 else
11004 {
11005 g_info << "abort schema trans" << endl;
11006 CHK2(pDic->endSchemaTrans(abort_flag) == 0, pDic->getNdbError());
11007 fk_undefine_keys(d);
11008 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11009 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11010 continue; // nothing to drop
11011 }
11012
11013 int abort_drop = abort_loop[loop % 3][1];
11014 require(abort_drop == 0 || abort_drop == 1);
11015 g_info << "abort drop: " << abort_drop << endl;
11016
11017 CHK2(pDic->beginSchemaTrans() == 0, pDic->getNdbError());
11018 CHK1(fk_drop_keys(d, pNdb, false) == 0);
11019 if (!abort_drop)
11020 {
11021 g_info << "commit schema trans" << endl;
11022 CHK2(pDic->endSchemaTrans(0) == 0, pDic->getNdbError());
11023 fk_undefine_keys(d);
11024 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11025 CHK1(fk_verify_list(d, pNdb, true) == NDBT_OK);
11026 }
11027 else
11028 {
11029 g_info << "abort schema trans" << endl;
11030 CHK2(pDic->endSchemaTrans(abort_flag) == 0, pDic->getNdbError());
11031 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11032 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11033 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11034 // prepare for next round
11035 CHK1(fk_drop_keys(d, pNdb, false) == NDBT_OK);
11036 fk_undefine_keys(d);
11037 }
11038 }
11039 CHK1(result == NDBT_OK);
11040
11041 if (!d.nodrop)
11042 {
11043 CHK1(fk_drop_all(d, pNdb, false) == NDBT_OK);
11044 }
11045 }
11046 while (0);
11047
11048 if (result != NDBT_OK)
11049 {
11050 (void)pDic->endSchemaTrans(abort_flag);
11051 if (!d.nodrop)
11052 (void)fk_drop_all(d, pNdb, true);
11053 }
11054 return result;
11055 }
11056
11057 int
runFK_Bug18069680(NDBT_Context * ctx,NDBT_Step * step)11058 runFK_Bug18069680(NDBT_Context* ctx, NDBT_Step* step)
11059 {
11060 Ndb* pNdb = GETNDB(step);
11061 const int loops = ctx->getNumLoops();
11062 const int records = ctx->getNumRecords();
11063 int result = NDBT_OK;
11064
11065 Fkdef d;
11066 d.testcase = ctx->getProperty("testcase", (Uint32)0);
11067 fk_env_options(d);
11068 fk_define_all(d);
11069
11070 do
11071 {
11072 (void)fk_drop_all(d, pNdb, true);
11073
11074 for (int loop = 0; loop < loops; loop++)
11075 {
11076 g_info << "loop " << loop << "<" << loops << endl;
11077
11078 CHK1(fk_create_all_random(d, pNdb) == NDBT_OK);
11079 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11080 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11081
11082 CHK1(fk_drop_indexes_under(d, pNdb) == NDBT_OK);
11083 CHK1(fk_drop_tables(d, pNdb, false) == NDBT_OK);
11084
11085 fk_dropped_all(d);
11086 }
11087 CHK1(result == NDBT_OK);
11088 }
11089 while (0);
11090
11091 if (result != NDBT_OK)
11092 {
11093 if (!d.nodrop)
11094 (void)fk_drop_all(d, pNdb, true);
11095 }
11096 return result;
11097 }
11098
11099 #undef myRandom48
11100 #undef myRandom48Init
11101
11102 int
runDictTO_1(NDBT_Context * ctx,NDBT_Step * step)11103 runDictTO_1(NDBT_Context* ctx, NDBT_Step* step)
11104 {
11105 Ndb* pNdb = GETNDB(step);
11106 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11107 NdbRestarter restarter;
11108
11109 if (restarter.getNumDbNodes() < 3)
11110 return NDBT_OK;
11111
11112 for (int i = 0; i < ctx->getNumLoops(); i++)
11113 {
11114 int master = restarter.getMasterNodeId();
11115 int next = restarter.getNextMasterNodeId(master);
11116 int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
11117
11118 restarter.dumpStateOneNode(master, val2, 2);
11119 restarter.insertError2InNode(master, 6050, next);
11120
11121 ndbout_c("master: %d next: %d", master, next);
11122 {
11123 g_info << "save all resource usage" << endl;
11124 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
11125 restarter.dumpStateAllNodes(dump1, 1);
11126 }
11127
11128
11129 {
11130 if (pDic->beginSchemaTrans() != 0)
11131 {
11132 ndbout << "ERROR: line: " << __LINE__ << endl;
11133 ndbout << pDic->getNdbError();
11134 return NDBT_FAILED;
11135 }
11136 for (int j = 0; j < (i + 1); j++)
11137 {
11138 NdbDictionary::Table pTab(* ctx->getTab());
11139 pTab.setName(BaseString(pTab.getName()).appfmt("_EXTRA_%u", j).c_str());
11140
11141 if (pDic->createTable(pTab) != 0)
11142 {
11143 ndbout << "ERROR: line: " << __LINE__ << endl;
11144 ndbout << pDic->getNdbError();
11145 return NDBT_FAILED;
11146 }
11147 }
11148
11149 // this should give master failuer...but trans should rollforward
11150 if (pDic->endSchemaTrans() != 0)
11151 {
11152 ndbout << "ERROR: line: " << __LINE__ << endl;
11153 ndbout << pDic->getNdbError();
11154 return NDBT_FAILED;
11155 }
11156 }
11157
11158 for (int j = 0; j < (i + 1); j++)
11159 {
11160 pDic->dropTable(BaseString(ctx->getTab()->getName()).appfmt("_EXTRA_%u", j).c_str());
11161 }
11162
11163 {
11164 g_info << "check all resource usage" << endl;
11165 for (int j = 0; j < restarter.getNumDbNodes(); j++)
11166 {
11167 if (restarter.getDbNodeId(j) == master)
11168 continue;
11169
11170 int dump1[] = { DumpStateOrd::SchemaResourceCheckLeak };
11171 restarter.dumpStateOneNode(restarter.getDbNodeId(j), dump1, 1);
11172 }
11173 }
11174
11175 restarter.waitNodesNoStart(&master, 1);
11176 restarter.startNodes(&master, 1);
11177 restarter.waitClusterStarted();
11178 }
11179
11180 return NDBT_OK;
11181 }
11182
11183 NDBT_TESTSUITE(testDict);
11184 TESTCASE("testDropDDObjects",
11185 "* 1. start cluster\n"
11186 "* 2. Create LFG\n"
11187 "* 3. create TS\n"
11188 "* 4. run DropDDObjects\n"
11189 "* 5. Verify DropDDObjectsRestart worked\n"){
11190 INITIALIZER(runWaitStarted);
11191 INITIALIZER(runDropDDObjects);
11192 INITIALIZER(testDropDDObjectsSetup);
11193 STEP(runDropDDObjects);
11194 FINALIZER(DropDDObjectsVerify);
11195 }
11196
11197 TESTCASE("Bug29501",
11198 "* 1. start cluster\n"
11199 "* 2. Restart 1 node -abort -nostart\n"
11200 "* 3. create LFG\n"
11201 "* 4. Restart data node\n"
11202 "* 5. Restart 1 node -nostart\n"
11203 "* 6. Drop LFG\n"){
11204 INITIALIZER(runWaitStarted);
11205 INITIALIZER(runDropDDObjects);
11206 STEP(runBug29501);
11207 FINALIZER(runDropDDObjects);
11208 }
11209 TESTCASE("CreateAndDrop",
11210 "Try to create and drop the table loop number of times\n"){
11211 INITIALIZER(runCreateAndDrop);
11212 }
11213 TESTCASE("CreateAndDropAtRandom",
11214 "Try to create and drop table at random loop number of times\n"
11215 "Uses all available tables\n"
11216 "Uses error insert 4013 to make TUP verify table descriptor"){
11217 INITIALIZER(runCreateAndDropAtRandom);
11218 }
11219 TESTCASE("CreateAndDropIndexes",
11220 "Like CreateAndDropAtRandom but also creates random ordered\n"
11221 "indexes and loads data as a simple check of index operation"){
11222 TC_PROPERTY("CreateIndexes", 1);
11223 TC_PROPERTY("LoadData", 1);
11224 INITIALIZER(runCreateAndDropAtRandom);
11225 }
11226 TESTCASE("CreateAndDropWithData",
11227 "Try to create and drop the table when it's filled with data\n"
11228 "do this loop number of times\n"){
11229 INITIALIZER(runCreateAndDropWithData);
11230 }
11231 TESTCASE("CreateAndDropDuring",
11232 "Try to create and drop the table when other thread is using it\n"
11233 "do this loop number of times\n"){
11234 STEP(runCreateAndDropDuring);
11235 STEP(runUseTableUntilStopped);
11236 }
11237 TESTCASE("DropWithTakeover","bug 14190114"){
11238 INITIALIZER(runDropTakeoverTest);
11239 }
11240 TESTCASE("CreateInvalidTables",
11241 "Try to create the invalid tables we have defined\n"){
11242 INITIALIZER(runCreateInvalidTables);
11243 }
11244 TESTCASE("DropTableConcurrentLCP",
11245 "Drop a table while LCP is ongoing\n")
11246 {
11247 INITIALIZER(runCreateTheTable);
11248 INITIALIZER(runFillTable);
11249 INITIALIZER(runSetMinTimeBetweenLCP);
11250 INITIALIZER(runSetDropTableConcurrentLCP);
11251 INITIALIZER(runDropTheTable);
11252 FINALIZER(runResetMinTimeBetweenLCP);
11253 }
11254 TESTCASE("DropTableConcurrentLCP2",
11255 "Drop a table while LCP is ongoing\n")
11256 {
11257 INITIALIZER(runCreateTheTable);
11258 INITIALIZER(runFillTable);
11259 INITIALIZER(runSetMinTimeBetweenLCP);
11260 INITIALIZER(runSetDropTableConcurrentLCP2);
11261 INITIALIZER(runDropTheTable);
11262 FINALIZER(runResetMinTimeBetweenLCP);
11263 }
11264 TESTCASE("CreateTableWhenDbIsFull",
11265 "Try to create a new table when db already is full\n"){
11266 INITIALIZER(runCreateTheTable);
11267 INITIALIZER(runFillTable);
11268 INITIALIZER(runCreateTableWhenDbIsFull);
11269 INITIALIZER(runDropTableWhenDbIsFull);
11270 FINALIZER(runDropTheTable);
11271 }
11272 TESTCASE("FragmentTypeSingle",
11273 "Create the table with fragment type Single\n"){
11274 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragSingle);
11275 INITIALIZER(runTestFragmentTypes);
11276 }
11277 TESTCASE("FragmentTypeAllSmall",
11278 "Create the table with fragment type AllSmall\n"){
11279 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllSmall);
11280 INITIALIZER(runTestFragmentTypes);
11281 }
11282 TESTCASE("FragmentTypeAllMedium",
11283 "Create the table with fragment type AllMedium\n"){
11284 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllMedium);
11285 INITIALIZER(runTestFragmentTypes);
11286 }
11287 TESTCASE("FragmentTypeAllLarge",
11288 "Create the table with fragment type AllLarge\n"){
11289 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllLarge);
11290 INITIALIZER(runTestFragmentTypes);
11291 }
11292 TESTCASE("TemporaryTables",
11293 "Create the table as temporary and make sure it doesn't\n"
11294 "contain any data when system is restarted\n"){
11295 INITIALIZER(runTestTemporaryTables);
11296 }
11297 TESTCASE("CreateMaxTables",
11298 "Create tables until db says that it can't create any more\n"){
11299 TC_PROPERTY("tables", 1000);
11300 INITIALIZER(runCreateMaxTables);
11301 INITIALIZER(runDropMaxTables);
11302 }
11303 TESTCASE("PkSizes",
11304 "Create tables with all different primary key sizes.\n"\
11305 "Test all data operations insert, update, delete etc.\n"\
11306 "Drop table."){
11307 INITIALIZER(runPkSizes);
11308 }
11309 TESTCASE("StoreFrm",
11310 "Test that a frm file can be properly stored as part of the\n"
11311 "data in Dict."){
11312 INITIALIZER(runStoreFrm);
11313 }
11314 TESTCASE("GetPrimaryKey",
11315 "Test the function NdbDictionary::Column::getPrimaryKey\n"
11316 "It should return true only if the column is part of \n"
11317 "the primary key in the table"){
11318 INITIALIZER(runGetPrimaryKey);
11319 }
11320 TESTCASE("StoreFrmError",
11321 "Test that a frm file with too long length can't be stored."){
11322 INITIALIZER(runStoreFrmError);
11323 }
11324 TESTCASE("TableRename",
11325 "Test basic table rename"){
11326 INITIALIZER(runTableRename);
11327 }
11328 TESTCASE("TableRenameSR",
11329 "Test that table rename can handle system restart"){
11330 INITIALIZER(runTableRenameSR);
11331 }
11332 TESTCASE("DictionaryPerf",
11333 ""){
11334 INITIALIZER(runTestDictionaryPerf);
11335 }
11336 TESTCASE("CreateLogfileGroup", ""){
11337 INITIALIZER(runCreateLogfileGroup);
11338 }
11339 TESTCASE("CreateTablespace", ""){
11340 INITIALIZER(runCreateTablespace);
11341 }
11342 TESTCASE("CreateDiskTable", ""){
11343 INITIALIZER(runCreateDiskTable);
11344 }
11345 TESTCASE("FailAddFragment",
11346 "Fail add fragment or attribute in ACC or TUP or TUX\n"){
11347 INITIALIZER(runFailAddFragment);
11348 }
11349 TESTCASE("Restart_NF1",
11350 "DICT ops during node graceful shutdown (not master)"){
11351 TC_PROPERTY("Restart_NF_ops", 1);
11352 TC_PROPERTY("Restart_NF_type", 1);
11353 STEP(runRestarts);
11354 STEP(runDictOps);
11355 }
11356 TESTCASE("Restart_NF2",
11357 "DICT ops during node shutdown abort (not master)"){
11358 TC_PROPERTY("Restart_NF_ops", 1);
11359 TC_PROPERTY("Restart_NF_type", 2);
11360 STEP(runRestarts);
11361 STEP(runDictOps);
11362 }
11363 TESTCASE("Restart_NR1",
11364 "DICT ops during node startup (not master)"){
11365 TC_PROPERTY("Restart_NR_ops", 1);
11366 STEP(runRestarts);
11367 STEP(runDictOps);
11368 }
11369 TESTCASE("Restart_NR2",
11370 "DICT ops during node startup with crash inserts (not master)"){
11371 TC_PROPERTY("Restart_NR_ops", 1);
11372 TC_PROPERTY("Restart_NR_error", 1);
11373 STEP(runRestarts);
11374 STEP(runDictOps);
11375 }
11376 TESTCASE("TableAddAttrs",
11377 "Add attributes to an existing table using alterTable()"){
11378 INITIALIZER(runTableAddAttrs);
11379 }
11380 TESTCASE("TableAddAttrsDuring",
11381 "Try to add attributes to the table when other thread is using it\n"
11382 "do this loop number of times\n"){
11383 INITIALIZER(runCreateTheTable);
11384 STEP(runTableAddAttrsDuring);
11385 STEP(runUseTableUntilStopped2);
11386 STEP(runUseTableUntilStopped3);
11387 FINALIZER(runDropTheTable);
11388 }
11389 TESTCASE("TableAddAttrsDuringError",
11390 "Try to add attributes to the table when other thread is using it\n"
11391 "do this loop number of times\n"){
11392 TC_PROPERTY("AbortAlter", 1);
11393 INITIALIZER(runCreateTheTable);
11394 STEP(runTableAddAttrsDuring);
11395 STEP(runUseTableUntilStopped2);
11396 STEP(runUseTableUntilStopped3);
11397 FINALIZER(runDropTheTable);
11398 }
11399 TESTCASE("Bug21755",
11400 ""){
11401 INITIALIZER(runBug21755);
11402 }
11403 TESTCASE("DictRestart",
11404 ""){
11405 INITIALIZER(runDictRestart);
11406 }
11407 TESTCASE("Bug24631",
11408 ""){
11409 INITIALIZER(runBug24631);
11410 }
11411 TESTCASE("Bug36702", "")
11412 {
11413 INITIALIZER(runDropDDObjects);
11414 INITIALIZER(runBug36072);
11415 FINALIZER(restartClusterInitial);
11416 }
11417 TESTCASE("Bug29186",
11418 ""){
11419 INITIALIZER(runBug29186);
11420 }
11421 TESTCASE("Bug48604",
11422 "Online ordered index build.\n"
11423 "Complements testOIBasic -case f"){
11424 STEP(runBug48604);
11425 STEP(runBug48604ops);
11426 #if 0 // for future MT test
11427 STEP(runBug48604ops);
11428 STEP(runBug48604ops);
11429 STEP(runBug48604ops);
11430 #endif
11431 }
11432 TESTCASE("Bug54651", ""){
11433 INITIALIZER(runBug54651);
11434 }
11435 /** telco-6.4 **/
11436 TESTCASE("SchemaTrans",
11437 "Schema transactions"){
11438 ALL_TABLES();
11439 STEP(runSchemaTrans);
11440 }
11441 TESTCASE("FailCreateHashmap",
11442 "Fail create hashmap")
11443 {
11444 INITIALIZER(runFailCreateHashmap);
11445 }
11446 TESTCASE("FailAddPartition",
11447 "Fail add partition")
11448 {
11449 INITIALIZER(runFailAddPartition);
11450 }
11451 TESTCASE("TableAddPartitions",
11452 "Add partitions to an existing table using alterTable()"){
11453 INITIALIZER(runTableAddPartition);
11454 }
11455 TESTCASE("Bug41905",
11456 ""){
11457 STEP(runBug41905);
11458 STEP(runBug41905getTable);
11459 }
11460 TESTCASE("Bug46552", "")
11461 {
11462 INITIALIZER(runBug46552);
11463 }
11464 TESTCASE("Bug46585", "")
11465 {
11466 INITIALIZER(runWaitStarted);
11467 INITIALIZER(runBug46585);
11468 }
11469 TESTCASE("Bug53944", "")
11470 {
11471 INITIALIZER(runBug53944);
11472 }
11473 TESTCASE("Bug58277",
11474 "Dropping busy ordered index can crash data node.\n"
11475 "Give any tablename as argument (T1)"){
11476 TC_PROPERTY("RSS_CHECK", (Uint32)true);
11477 TC_PROPERTY("RANGE_MAX", (Uint32)5);
11478 INITIALIZER(runBug58277errtest);
11479 STEP(runBug58277);
11480 // sub-steps 2-8 synced with main step
11481 TC_PROPERTY("SubSteps", 7);
11482 STEP(runBug58277drop);
11483 /*
11484 * A single scan update can show the bug but this is not likely.
11485 * Add more scan updates. Also add PK ops for other asserts.
11486 */
11487 STEP(runBug58277scan);
11488 STEP(runBug58277scan);
11489 STEP(runBug58277scan);
11490 STEP(runBug58277scan);
11491 STEP(runBug58277pk);
11492 STEP(runBug58277pk);
11493 // kernel side scans (eg. LCP) for resource usage check
11494 STEP(runBug58277rand);
11495 }
11496 TESTCASE("Bug57057",
11497 "MRR + delete leaks stored procs (fixed under Bug58277).\n"
11498 "Give any tablename as argument (T1)"){
11499 TC_PROPERTY("RSS_CHECK", (Uint32)true);
11500 TC_PROPERTY("RANGE_MAX", (Uint32)100);
11501 TC_PROPERTY("SCAN_DELETE", (Uint32)1);
11502 STEP(runBug57057);
11503 TC_PROPERTY("SubSteps", 1);
11504 STEP(runBug58277scan);
11505 }
11506 TESTCASE("GetTabInfoRef", "Regression test for bug #14647210 'CAN CRASH ALL "
11507 "NODES EASILY WHEN RESTARTING MORE THAN 6 NODES SIMULTANEOUSLY'"
11508 " (missing handling of GET_TABINFOREF signal).")
11509 {
11510 INITIALIZER(runGetTabInfoRef);
11511 }
11512 TESTCASE("Bug13416603", "")
11513 {
11514 INITIALIZER(runCreateTheTable);
11515 INITIALIZER(runLoadTable);
11516 INITIALIZER(runBug13416603);
11517 FINALIZER(runDropTheTable);
11518 }
11519 TESTCASE("IndexStatCreate", "")
11520 {
11521 STEPS(runIndexStatCreate, 10);
11522 }
11523 TESTCASE("WL946",
11524 "Time types with fractional seconds.\n"
11525 "Give any tablename as argument (T1)"){
11526 INITIALIZER(runWL946);
11527 }
11528 TESTCASE("Bug14645319", "")
11529 {
11530 STEP(runBug14645319);
11531 }
11532 TESTCASE("FK_SRNR1",
11533 "Foreign keys SR/NR, simple case with DDL and DML checks.\n"
11534 "Give any tablename as argument (T1)"){
11535 TC_PROPERTY("testcase", 1);
11536 INITIALIZER(runFK_SRNR);
11537 }
11538 TESTCASE("FK_SRNR2",
11539 "Foreign keys SR/NR, complex case with DDL checks .\n"
11540 "Give any tablename as argument (T1)"){
11541 TC_PROPERTY("testcase", 2);
11542 INITIALIZER(runFK_SRNR);
11543 }
11544 TESTCASE("FK_TRANS1",
11545 "Foreign keys schema trans, simple case with DDL and DML checks.\n"
11546 "Give any tablename as argument (T1)"){
11547 TC_PROPERTY("testcase", 1);
11548 INITIALIZER(runFK_TRANS);
11549 }
11550 TESTCASE("FK_TRANS2",
11551 "Foreign keys schema trans, complex case with DDL checks.\n"
11552 "Give any tablename as argument (T1)"){
11553 TC_PROPERTY("testcase", 2);
11554 INITIALIZER(runFK_TRANS);
11555 }
11556 TESTCASE("FK_Bug18069680",
11557 "NDB API drop table with foreign keys.\n"
11558 "Give any tablename as argument (T1)"){
11559 TC_PROPERTY("testcase", 2);
11560 INITIALIZER(runFK_Bug18069680);
11561 }
11562 TESTCASE("CreateHashmaps",
11563 "Create (default) hashmaps")
11564 {
11565 INITIALIZER(runCreateHashmaps);
11566 }
11567 TESTCASE("DictTakeOver_1", "")
11568 {
11569 INITIALIZER(runDictTO_1);
11570 }
11571 NDBT_TESTSUITE_END(testDict);
11572
main(int argc,const char ** argv)11573 int main(int argc, const char** argv){
11574 ndb_init();
11575 NDBT_TESTSUITE_INSTANCE(testDict);
11576 // Tables should not be auto created
11577 testDict.setCreateTable(false);
11578 myRandom48Init((long)NdbTick_CurrentMillisecond());
11579 return testDict.execute(argc, argv);
11580 }
11581