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