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