1 /*
2    Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <NDBT.hpp>
26 #include <NDBT_Test.hpp>
27 #include <HugoTransactions.hpp>
28 #include <UtilTransactions.hpp>
29 #include <NdbRestarter.hpp>
30 #include <NdbRestarts.hpp>
31 #include <Vector.hpp>
32 #include <signaldata/DumpStateOrd.hpp>
33 #include <NodeBitmask.hpp>
34 #include <NdbSqlUtil.hpp>
35 #include <BlockNumbers.h>
36 
37 #define CHECK(b) if (!(b)) { \
38   g_err << "ERR: "<< step->getName() \
39          << " failed on line " << __LINE__ << endl; \
40   result = NDBT_FAILED; break;\
41 }
42 
43 #define CHECKRET(b) if (!(b)) { \
44   g_err << "ERR: "<< step->getName() \
45          << " failed on line " << __LINE__ << endl; \
46   return NDBT_FAILED;                             \
47 }
48 
49 
50 struct Attrib {
51   bool indexCreated;
52   int numAttribs;
53   int attribs[1024];
AttribAttrib54   Attrib(){
55     numAttribs = 0;
56     indexCreated = false;
57   }
58 };
59 class AttribList {
60 public:
AttribList()61   AttribList(){};
~AttribList()62   ~AttribList(){
63     for(size_t i = 0; i < attriblist.size(); i++){
64       delete attriblist[i];
65     }
66   };
67   void buildAttribList(const NdbDictionary::Table* pTab);
68   Vector<Attrib*> attriblist;
69 };
70 
buildAttribList(const NdbDictionary::Table * pTab)71 void AttribList::buildAttribList(const NdbDictionary::Table* pTab){
72   attriblist.clear();
73 
74   Attrib* attr;
75   // Build attrib definitions that describes which attributes to build index
76   // Try to build strange combinations, not just "all" or all PK's
77 
78   int i;
79 
80   for(i = 1; i <= pTab->getNoOfColumns(); i++){
81     attr = new Attrib;
82     attr->numAttribs = i;
83     for(int a = 0; a<i; a++)
84       attr->attribs[a] = a;
85     attriblist.push_back(attr);
86   }
87   int b = 0;
88   for(i = pTab->getNoOfColumns()-1; i > 0; i--){
89     attr = new Attrib;
90     attr->numAttribs = i;
91     b++;
92     for(int a = 0; a<i; a++)
93       attr->attribs[a] = a+b;
94     attriblist.push_back(attr);
95   }
96   for(i = pTab->getNoOfColumns(); i > 0;  i--){
97     attr = new Attrib;
98     attr->numAttribs = pTab->getNoOfColumns() - i;
99     for(int a = 0; a<pTab->getNoOfColumns() - i; a++)
100       attr->attribs[a] = pTab->getNoOfColumns()-a-1;
101     attriblist.push_back(attr);
102   }
103   for(i = 1; i < pTab->getNoOfColumns(); i++){
104     attr = new Attrib;
105     attr->numAttribs = pTab->getNoOfColumns() - i;
106     for(int a = 0; a<pTab->getNoOfColumns() - i; a++)
107       attr->attribs[a] = pTab->getNoOfColumns()-a-1;
108     attriblist.push_back(attr);
109   }
110   for(i = 1; i < pTab->getNoOfColumns(); i++){
111     attr = new Attrib;
112     attr->numAttribs = 2;
113     for(int a = 0; a<2; a++){
114       attr->attribs[a] = i%pTab->getNoOfColumns();
115     }
116     attriblist.push_back(attr);
117   }
118 
119   // Last
120   attr = new Attrib;
121   attr->numAttribs = 1;
122   attr->attribs[0] = pTab->getNoOfColumns()-1;
123   attriblist.push_back(attr);
124 
125   // Last and first
126   attr = new Attrib;
127   attr->numAttribs = 2;
128   attr->attribs[0] = pTab->getNoOfColumns()-1;
129   attr->attribs[1] = 0;
130   attriblist.push_back(attr);
131 
132   // First and last
133   attr = new Attrib;
134   attr->numAttribs = 2;
135   attr->attribs[0] = 0;
136   attr->attribs[1] = pTab->getNoOfColumns()-1;
137   attriblist.push_back(attr);
138 
139 #if 0
140   for(size_t i = 0; i < attriblist.size(); i++){
141 
142     ndbout << attriblist[i]->numAttribs << ": " ;
143     for(int a = 0; a < attriblist[i]->numAttribs; a++)
144       ndbout << attriblist[i]->attribs[a] << ", ";
145     ndbout << endl;
146   }
147 #endif
148 
149 }
150 
151 char idxName[255];
152 char pkIdxName[255];
153 
154 static const int SKIP_INDEX = 99;
155 
create_index(NDBT_Context * ctx,int indxNum,const NdbDictionary::Table * pTab,Ndb * pNdb,Attrib * attr,bool logged)156 int create_index(NDBT_Context* ctx, int indxNum,
157 		 const NdbDictionary::Table* pTab,
158 		 Ndb* pNdb, Attrib* attr, bool logged){
159   bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
160   bool notOnlyPkId = ctx->getProperty("NotOnlyPkId", (unsigned)0);
161   int result  = NDBT_OK;
162 
163   HugoCalculator calc(*pTab);
164 
165   if (attr->numAttribs == 1 &&
166       calc.isUpdateCol(attr->attribs[0]) == true){
167     // Don't create index for the Hugo update column
168     // since it's not unique
169     return SKIP_INDEX;
170   }
171 
172   // Create index
173   BaseString::snprintf(idxName, 255, "IDC%d", indxNum);
174   if (orderedIndex)
175     ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "<<idxName << " (";
176   else
177     ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index "<<idxName << " (";
178   ndbout << flush;
179   NdbDictionary::Index pIdx(idxName);
180   pIdx.setTable(pTab->getName());
181   if (orderedIndex)
182     pIdx.setType(NdbDictionary::Index::OrderedIndex);
183   else
184     pIdx.setType(NdbDictionary::Index::UniqueHashIndex);
185 
186   bool includesOnlyPkIdCols = true;
187   for (int c = 0; c< attr->numAttribs; c++){
188     int attrNo = attr->attribs[c];
189     const NdbDictionary::Column* col = pTab->getColumn(attrNo);
190     switch(col->getType())
191     {
192     case NDB_TYPE_BIT:
193     case NDB_TYPE_BLOB:
194     case NDB_TYPE_TEXT:
195       /* Not supported */
196       ndbout << col->getName() << " - bad type )" << endl;
197       return SKIP_INDEX;
198     default:
199       break;
200     }
201     if (col->getStorageType() == NDB_STORAGETYPE_DISK)
202     {
203       ndbout << col->getName() << " - disk based )" << endl;
204       return SKIP_INDEX;
205     }
206 
207     pIdx.addIndexColumn(col->getName());
208     ndbout << col->getName()<<" ";
209 
210     if (! (col->getPrimaryKey() ||
211            calc.isIdCol(attrNo)))
212       includesOnlyPkIdCols = false;
213   }
214 
215   if (notOnlyPkId && includesOnlyPkIdCols)
216   {
217     ndbout << " Only PK/id cols included - skipping" << endl;
218     return SKIP_INDEX;
219   }
220 
221   if (!orderedIndex)
222   {
223     /**
224      * For unique indexes we must add PK, otherwise it's not guaranteed
225      *  to be unique
226      */
227     for (int i = 0; i<pTab->getNoOfColumns(); i++)
228     {
229       if (pTab->getColumn(i)->getPrimaryKey())
230       {
231         for (int j = 0; j<attr->numAttribs; j++)
232         {
233           if (attr->attribs[j] == i)
234             goto next;
235         }
236         pIdx.addIndexColumn(pTab->getColumn(i)->getName());
237         ndbout << pTab->getColumn(i)->getName() << " ";
238       }
239   next:
240       (void)i;
241     }
242   }
243 
244   pIdx.setStoredIndex(logged);
245   ndbout << ") ";
246   bool noddl= ctx->getProperty("NoDDL");
247 
248   if (noddl)
249   {
250     const NdbDictionary::Index* idx= pNdb->
251       getDictionary()->getIndex(pIdx.getName(), pTab->getName());
252 
253     if (!idx)
254     {
255       ndbout << "Failed - Index does not exist and DDL not allowed" << endl;
256       return NDBT_FAILED;
257     }
258     else
259     {
260       attr->indexCreated = false;
261       // TODO : Check index definition is ok
262     }
263   }
264   else
265   {
266     if (pNdb->getDictionary()->createIndex(pIdx) != 0){
267       attr->indexCreated = false;
268       ndbout << "FAILED!" << endl;
269       const NdbError err = pNdb->getDictionary()->getNdbError();
270       ERR(err);
271       if (err.classification == NdbError::ApplicationError)
272         return SKIP_INDEX;
273 
274       if (err.status == NdbError::TemporaryError)
275         return SKIP_INDEX;
276 
277       return NDBT_FAILED;
278     } else {
279       ndbout << "OK!" << endl;
280       attr->indexCreated = true;
281     }
282   }
283   return result;
284 }
285 
286 
drop_index(int indxNum,Ndb * pNdb,const NdbDictionary::Table * pTab,Attrib * attr)287 int drop_index(int indxNum, Ndb* pNdb,
288 	       const NdbDictionary::Table* pTab, Attrib* attr){
289   int result = NDBT_OK;
290 
291   if (attr->indexCreated == false)
292     return NDBT_OK;
293 
294   BaseString::snprintf(idxName, 255, "IDC%d", indxNum);
295 
296   // Drop index
297   ndbout << "Dropping index "<<idxName<<"(" << pTab->getName() << ") ";
298   if (pNdb->getDictionary()->dropIndex(idxName, pTab->getName()) != 0){
299     ndbout << "FAILED!" << endl;
300     ERR(pNdb->getDictionary()->getNdbError());
301     result = NDBT_FAILED;
302   } else {
303     ndbout << "OK!" << endl;
304   }
305   return result;
306 }
307 
runCreateIndexes(NDBT_Context * ctx,NDBT_Step * step)308 int runCreateIndexes(NDBT_Context* ctx, NDBT_Step* step){
309   int loops = ctx->getNumLoops();
310   int l = 0;
311   const NdbDictionary::Table* pTab = ctx->getTab();
312   Ndb* pNdb = GETNDB(step);
313   int result = NDBT_OK;
314   // NOTE If we need to test creating both logged and non logged indexes
315   // this should be divided into two testcases
316   // The paramater logged should then be specified
317   // as a TC_PROPERTY. ex TC_PROPERTY("LoggedIndexes", 1);
318   // and read into the test step like
319   bool logged = ctx->getProperty("LoggedIndexes", 1);
320 
321   AttribList attrList;
322   attrList.buildAttribList(pTab);
323 
324 
325   while (l < loops && result == NDBT_OK){
326     unsigned int i;
327     for (i = 0; i < attrList.attriblist.size(); i++){
328 
329       // Try to create index
330       if (create_index(ctx, i, pTab, pNdb, attrList.attriblist[i], logged) == NDBT_FAILED)
331 	result = NDBT_FAILED;
332     }
333 
334     // Now drop all indexes that where created
335     for (i = 0; i < attrList.attriblist.size(); i++){
336 
337       // Try to drop index
338       if (drop_index(i, pNdb, pTab, attrList.attriblist[i]) != NDBT_OK)
339 	result = NDBT_FAILED;
340     }
341 
342     l++;
343   }
344 
345   return result;
346 }
347 
createRandomIndex(NDBT_Context * ctx,NDBT_Step * step)348 int createRandomIndex(NDBT_Context* ctx, NDBT_Step* step){
349   const NdbDictionary::Table* pTab = ctx->getTab();
350   Ndb* pNdb = GETNDB(step);
351   bool logged = ctx->getProperty("LoggedIndexes", 1);
352 
353   AttribList attrList;
354   attrList.buildAttribList(pTab);
355 
356   int retries = 100;
357   while(retries > 0){
358     const Uint32 i = rand() % attrList.attriblist.size();
359     int res = create_index(ctx, i, pTab, pNdb, attrList.attriblist[i],
360 			   logged);
361     if (res == SKIP_INDEX){
362       retries--;
363       continue;
364     }
365 
366     if (res == NDBT_FAILED){
367       return NDBT_FAILED;
368     }
369 
370     ctx->setProperty("createRandomIndex", i);
371     // Now drop all indexes that where created
372 
373     return NDBT_OK;
374   }
375 
376   return NDBT_FAILED;
377 }
378 
createRandomIndex_Drop(NDBT_Context * ctx,NDBT_Step * step)379 int createRandomIndex_Drop(NDBT_Context* ctx, NDBT_Step* step){
380   Ndb* pNdb = GETNDB(step);
381 
382   Uint32 i = ctx->getProperty("createRandomIndex");
383 
384   BaseString::snprintf(idxName, 255, "IDC%d", i);
385 
386   // Drop index
387   ndbout << "Dropping index " << idxName << " ";
388   if (pNdb->getDictionary()->dropIndex(idxName,
389 				       ctx->getTab()->getName()) != 0){
390     ndbout << "FAILED!" << endl;
391     ERR(pNdb->getDictionary()->getNdbError());
392     return NDBT_FAILED;
393   } else {
394     ndbout << "OK!" << endl;
395   }
396 
397   return NDBT_OK;
398 }
399 
createPkIndex(NDBT_Context * ctx,NDBT_Step * step)400 int createPkIndex(NDBT_Context* ctx, NDBT_Step* step){
401   bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
402 
403   const NdbDictionary::Table* pTab = ctx->getTab();
404   Ndb* pNdb = GETNDB(step);
405 
406   bool logged = ctx->getProperty("LoggedIndexes", 1);
407   bool noddl= ctx->getProperty("NoDDL");
408 
409   // Create index
410   BaseString::snprintf(pkIdxName, 255, "IDC_PK_%s", pTab->getName());
411   if (orderedIndex)
412     ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "
413 	   << pkIdxName << " (";
414   else
415     ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index "
416 	   << pkIdxName << " (";
417 
418   NdbDictionary::Index pIdx(pkIdxName);
419   pIdx.setTable(pTab->getName());
420   if (orderedIndex)
421     pIdx.setType(NdbDictionary::Index::OrderedIndex);
422   else
423     pIdx.setType(NdbDictionary::Index::UniqueHashIndex);
424   for (int c = 0; c< pTab->getNoOfColumns(); c++){
425     const NdbDictionary::Column * col = pTab->getColumn(c);
426     if(col->getPrimaryKey()){
427       pIdx.addIndexColumn(col->getName());
428       ndbout << col->getName() <<" ";
429     }
430   }
431 
432   pIdx.setStoredIndex(logged);
433   ndbout << ") ";
434   if (noddl)
435   {
436     const NdbDictionary::Index* idx= pNdb->
437       getDictionary()->getIndex(pkIdxName, pTab->getName());
438 
439     if (!idx)
440     {
441       ndbout << "Failed - Index does not exist and DDL not allowed" << endl;
442       ERR(pNdb->getDictionary()->getNdbError());
443       return NDBT_FAILED;
444     }
445     else
446     {
447       // TODO : Check index definition is ok
448     }
449   }
450   else
451   {
452     if (pNdb->getDictionary()->createIndex(pIdx) != 0){
453       ndbout << "FAILED!" << endl;
454       const NdbError err = pNdb->getDictionary()->getNdbError();
455       ERR(err);
456       return NDBT_FAILED;
457     }
458   }
459 
460   ndbout << "OK!" << endl;
461   return NDBT_OK;
462 }
463 
createPkIndex_Drop(NDBT_Context * ctx,NDBT_Step * step)464 int createPkIndex_Drop(NDBT_Context* ctx, NDBT_Step* step){
465   const NdbDictionary::Table* pTab = ctx->getTab();
466   Ndb* pNdb = GETNDB(step);
467 
468   bool noddl= ctx->getProperty("NoDDL");
469 
470   // Drop index
471   if (!noddl)
472   {
473     ndbout << "Dropping index " << pkIdxName << " ";
474     if (pNdb->getDictionary()->dropIndex(pkIdxName,
475                                          pTab->getName()) != 0){
476       ndbout << "FAILED!" << endl;
477       ERR(pNdb->getDictionary()->getNdbError());
478       return NDBT_FAILED;
479     } else {
480       ndbout << "OK!" << endl;
481     }
482   }
483 
484   return NDBT_OK;
485 }
486 
487 int
runVerifyIndex(NDBT_Context * ctx,NDBT_Step * step)488 runVerifyIndex(NDBT_Context* ctx, NDBT_Step* step){
489   // Verify that data in index match
490   // table data
491   Ndb* pNdb = GETNDB(step);
492   UtilTransactions utilTrans(*ctx->getTab());
493   const int batchSize = ctx->getProperty("BatchSize", 16);
494   const int parallelism = batchSize > 240 ? 240 : batchSize;
495 
496   do {
497     if (utilTrans.verifyIndex(pNdb, idxName, parallelism, true) != 0){
498       g_err << "Inconsistent index" << endl;
499       return NDBT_FAILED;
500     }
501   } while(ctx->isTestStopped() == false);
502   return NDBT_OK;
503 }
504 
505 int
runTransactions1(NDBT_Context * ctx,NDBT_Step * step)506 runTransactions1(NDBT_Context* ctx, NDBT_Step* step){
507   // Verify that data in index match
508   // table data
509   Ndb* pNdb = GETNDB(step);
510   HugoTransactions hugoTrans(*ctx->getTab());
511   const int batchSize = ctx->getProperty("BatchSize", 50);
512 
513   int rows = ctx->getNumRecords();
514   while (ctx->isTestStopped() == false) {
515     if (hugoTrans.pkUpdateRecords(pNdb, rows, batchSize) != 0){
516       g_err << "Updated table failed" << endl;
517       return NDBT_FAILED;
518     }
519 
520     ctx->sync_down("PauseThreads");
521     if(ctx->isTestStopped())
522       break;
523 
524     if (hugoTrans.scanUpdateRecords(pNdb, rows, batchSize) != 0){
525       g_err << "Updated table failed" << endl;
526       return NDBT_FAILED;
527     }
528 
529     ctx->sync_down("PauseThreads");
530   }
531   return NDBT_OK;
532 }
533 
534 int
runTransactions2(NDBT_Context * ctx,NDBT_Step * step)535 runTransactions2(NDBT_Context* ctx, NDBT_Step* step){
536   // Verify that data in index match
537   // table data
538   Ndb* pNdb = GETNDB(step);
539   HugoTransactions hugoTrans(*ctx->getTab());
540   const int batchSize = ctx->getProperty("BatchSize", 50);
541 
542   int rows = ctx->getNumRecords();
543   while (ctx->isTestStopped() == false) {
544 #if 1
545     if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchSize) != 0){
546       g_err << "Index read failed" << endl;
547       return NDBT_FAILED;
548     }
549 #endif
550     ctx->sync_down("PauseThreads");
551     if(ctx->isTestStopped())
552       break;
553 #if 1
554     if (hugoTrans.indexUpdateRecords(pNdb, pkIdxName, rows, batchSize) != 0){
555       g_err << "Index update failed" << endl;
556       return NDBT_FAILED;
557     }
558 #endif
559     ctx->sync_down("PauseThreads");
560   }
561   return NDBT_OK;
562 }
563 
564 int
runTransactions3(NDBT_Context * ctx,NDBT_Step * step)565 runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
566   // Verify that data in index match
567   // table data
568   Ndb* pNdb = GETNDB(step);
569   HugoTransactions hugoTrans(*ctx->getTab());
570   UtilTransactions utilTrans(*ctx->getTab());
571   const int batchSize = ctx->getProperty("BatchSize", 32);
572   const int parallel = batchSize > 240 ? 240 : batchSize;
573 
574   int rows = ctx->getNumRecords();
575   while (ctx->isTestStopped() == false) {
576     if(hugoTrans.loadTable(pNdb, rows, batchSize, false) != 0){
577       g_err << "Load table failed" << endl;
578       return NDBT_FAILED;
579     }
580     ctx->sync_down("PauseThreads");
581     if(ctx->isTestStopped())
582       break;
583 
584     if (hugoTrans.pkUpdateRecords(pNdb, rows, batchSize) != 0){
585       g_err << "Updated table failed" << endl;
586       return NDBT_FAILED;
587     }
588 
589     ctx->sync_down("PauseThreads");
590     if(ctx->isTestStopped())
591       break;
592 
593     if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchSize) != 0){
594       g_err << "Index read failed" << endl;
595       return NDBT_FAILED;
596     }
597 
598     ctx->sync_down("PauseThreads");
599     if(ctx->isTestStopped())
600       break;
601 
602     if (hugoTrans.indexUpdateRecords(pNdb, pkIdxName, rows, batchSize) != 0){
603       g_err << "Index update failed" << endl;
604       return NDBT_FAILED;
605     }
606 
607     ctx->sync_down("PauseThreads");
608     if(ctx->isTestStopped())
609       break;
610 
611     if (hugoTrans.scanUpdateRecords(pNdb, rows, 5, parallel) != 0){
612       g_err << "Scan updated table failed" << endl;
613       return NDBT_FAILED;
614     }
615 
616     ctx->sync_down("PauseThreads");
617     if(ctx->isTestStopped())
618       break;
619 
620     if(utilTrans.clearTable(pNdb, rows, parallel) != 0){
621       g_err << "Clear table failed" << endl;
622       return NDBT_FAILED;
623     }
624 
625     ctx->sync_down("PauseThreads");
626     if(ctx->isTestStopped())
627       break;
628 
629     int count = -1;
630     if(utilTrans.selectCount(pNdb, 64, &count) != 0 || count != 0)
631       return NDBT_FAILED;
632     ctx->sync_down("PauseThreads");
633   }
634   return NDBT_OK;
635 }
636 
runRestarts(NDBT_Context * ctx,NDBT_Step * step)637 int runRestarts(NDBT_Context* ctx, NDBT_Step* step){
638   int result = NDBT_OK;
639   int loops = ctx->getNumLoops();
640   NDBT_TestCase* pCase = ctx->getCase();
641   NdbRestarts restarts;
642   int i = 0;
643   int timeout = 240;
644   int sync_threads = ctx->getProperty("Threads", (unsigned)0);
645 
646   while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){
647     if(restarts.executeRestart(ctx, "RestartRandomNodeAbort", timeout) != 0){
648       g_err << "Failed to executeRestart(" <<pCase->getName() <<")" << endl;
649       result = NDBT_FAILED;
650       break;
651     }
652     ctx->sync_up_and_wait("PauseThreads", sync_threads);
653     i++;
654   }
655   ctx->stopTest();
656   return result;
657 }
658 
runCreateLoadDropIndex(NDBT_Context * ctx,NDBT_Step * step)659 int runCreateLoadDropIndex(NDBT_Context* ctx, NDBT_Step* step){
660   int loops = ctx->getNumLoops();
661   int records = ctx->getNumRecords();
662   int l = 0;
663   const NdbDictionary::Table* pTab = ctx->getTab();
664   Ndb* pNdb = GETNDB(step);
665   int result = NDBT_OK;
666   int batchSize = ctx->getProperty("BatchSize", 1);
667   int parallelism = batchSize > 240? 240: batchSize;
668   ndbout << "batchSize="<<batchSize<<endl;
669   bool logged = ctx->getProperty("LoggedIndexes", 1);
670 
671   HugoTransactions hugoTrans(*pTab);
672   UtilTransactions utilTrans(*pTab);
673   AttribList attrList;
674   attrList.buildAttribList(pTab);
675 
676   for (unsigned int i = 0; i < attrList.attriblist.size(); i++){
677 
678     while (l < loops && result == NDBT_OK){
679 
680       if ((l % 2) == 0){
681 	// Create index first and then load
682 
683 	// Try to create index
684 	if (create_index(ctx, i, pTab, pNdb, attrList.attriblist[i], logged) == NDBT_FAILED){
685 	  result = NDBT_FAILED;
686 	}
687 
688 	// Load the table with data
689 	ndbout << "Loading data after" << endl;
690 	CHECK(hugoTrans.loadTable(pNdb, records, batchSize) == 0);
691 
692 
693       } else {
694 	// Load table then create index
695 
696 	// Load the table with data
697 	ndbout << "Loading data before" << endl;
698 	CHECK(hugoTrans.loadTable(pNdb, records, batchSize) == 0);
699 
700 	// Try to create index
701 	if (create_index(ctx, i, pTab, pNdb, attrList.attriblist[i], logged) == NDBT_FAILED)
702 	  result = NDBT_FAILED;
703 
704       }
705 
706       // Verify that data in index match
707       // table data
708       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
709 
710       // Do it all...
711       ndbout <<"Doing it all"<<endl;
712       int count;
713       ndbout << "  pkUpdateRecords" << endl;
714       CHECK(hugoTrans.pkUpdateRecords(pNdb, records, batchSize) == 0);
715       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
716       CHECK(hugoTrans.pkUpdateRecords(pNdb, records, batchSize) == 0);
717       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
718       ndbout << "  pkDelRecords half" << endl;
719       CHECK(hugoTrans.pkDelRecords(pNdb, records/2, batchSize) == 0);
720       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
721       ndbout << "  scanUpdateRecords" << endl;
722       CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2, parallelism) == 0);
723       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
724       ndbout << "  clearTable" << endl;
725       CHECK(utilTrans.clearTable(pNdb, records/2, parallelism) == 0);
726       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
727       CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
728       CHECK(count == 0);
729       ndbout << "  loadTable" << endl;
730       CHECK(hugoTrans.loadTable(pNdb, records, batchSize) == 0);
731       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
732       ndbout << "  loadTable again" << endl;
733       CHECK(hugoTrans.loadTable(pNdb, records, batchSize) == 0);
734       CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
735       CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
736       CHECK(count == records);
737 
738 
739       if ((l % 2) == 0){
740 	// Drop index first and then clear
741 
742 	// Try to create index
743 	if (drop_index(i, pNdb, pTab, attrList.attriblist[i]) != NDBT_OK){
744 	  result = NDBT_FAILED;
745 	}
746 
747 	// Clear table
748 	ndbout << "Clearing table after" << endl;
749 	CHECK(hugoTrans.clearTable(pNdb, records, parallelism) == 0);
750 
751 
752       } else {
753 	// Clear table then drop index
754 
755 	//Clear table
756 	ndbout << "Clearing table before" << endl;
757 	CHECK(hugoTrans.clearTable(pNdb, records, parallelism) == 0);
758 
759 	// Try to drop index
760 	if (drop_index(i, pNdb, pTab, attrList.attriblist[i]) != NDBT_OK)
761 	  result = NDBT_FAILED;
762       }
763 
764       ndbout << "  Done!" << endl;
765       l++;
766     }
767 
768     // Make sure index is dropped
769     drop_index(i, pNdb, pTab, attrList.attriblist[i]);
770 
771   }
772 
773   return result;
774 }
775 
runInsertDelete(NDBT_Context * ctx,NDBT_Step * step)776 int runInsertDelete(NDBT_Context* ctx, NDBT_Step* step){
777   int loops = ctx->getNumLoops();
778   int records = ctx->getNumRecords();
779   const NdbDictionary::Table* pTab = ctx->getTab();
780   Ndb* pNdb = GETNDB(step);
781   int result = NDBT_OK;
782   int batchSize = ctx->getProperty("BatchSize", 1);
783   int parallelism = batchSize > 240? 240: batchSize;
784   ndbout << "batchSize="<<batchSize<<endl;
785   bool logged = ctx->getProperty("LoggedIndexes", 1);
786 
787   HugoTransactions hugoTrans(*pTab);
788   UtilTransactions utilTrans(*pTab);
789 
790   AttribList attrList;
791   attrList.buildAttribList(pTab);
792 
793   for (unsigned int i = 0; i < attrList.attriblist.size(); i++){
794 
795     Attrib* attr = attrList.attriblist[i];
796     // Create index
797     if (create_index(ctx, i, pTab, pNdb, attr, logged) == NDBT_OK){
798       int l = 1;
799       while (l <= loops && result == NDBT_OK){
800 
801 	CHECK(hugoTrans.loadTable(pNdb, records, batchSize) == 0);
802 	CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
803 	CHECK(utilTrans.clearTable(pNdb, records, parallelism) == 0);
804 	CHECK(utilTrans.verifyIndex(pNdb, idxName, parallelism) == 0);
805 	l++;
806       }
807 
808       // Drop index
809       if (drop_index(i, pNdb, pTab, attr) != NDBT_OK)
810 	result = NDBT_FAILED;
811     }
812   }
813 
814   return result;
815 }
816 
tryAddUniqueIndex(Ndb * pNdb,const NdbDictionary::Table * pTab,const char * idxName,HugoCalculator & calc,int & chosenCol)817 int tryAddUniqueIndex(Ndb* pNdb,
818                       const NdbDictionary::Table* pTab,
819                       const char* idxName,
820                       HugoCalculator& calc,
821                       int& chosenCol)
822 {
823   for(int c = 0; c < pTab->getNoOfColumns(); c++)
824   {
825     const NdbDictionary::Column* col = pTab->getColumn(c);
826 
827     if (!col->getPrimaryKey() &&
828         !calc.isUpdateCol(c) &&
829         !col->getNullable() &&
830         col->getStorageType() != NDB_STORAGETYPE_DISK)
831     {
832       chosenCol = c;
833       break;
834     }
835   }
836 
837   if (chosenCol == -1)
838   {
839     return 1;
840   }
841 
842 
843   /* Create unique index on chosen column */
844 
845   const char* colName = pTab->getColumn(chosenCol)->getName();
846   ndbout << "Creating unique index :" << idxName << " on ("
847          << colName << ")" << endl;
848 
849   NdbDictionary::Index idxDef(idxName);
850   idxDef.setTable(pTab->getName());
851   idxDef.setType(NdbDictionary::Index::UniqueHashIndex);
852 
853   idxDef.addIndexColumn(colName);
854   idxDef.setStoredIndex(false);
855 
856   if (pNdb->getDictionary()->createIndex(idxDef) != 0)
857   {
858     ndbout << "FAILED!" << endl;
859     const NdbError err = pNdb->getDictionary()->getNdbError();
860     ERR(err);
861     return -1;
862   }
863 
864   return 0;
865 }
866 
tryInsertUniqueRecord(NDBT_Step * step,HugoOperations & hugoOps,int & recordNum)867 int tryInsertUniqueRecord(NDBT_Step* step,
868                           HugoOperations& hugoOps,
869                           int& recordNum)
870 {
871   Ndb* pNdb = GETNDB(step);
872   do
873   {
874     CHECKRET(hugoOps.startTransaction(pNdb) == 0);
875     CHECKRET(hugoOps.pkInsertRecord(pNdb,
876                                     recordNum,
877                                     1,  // NumRecords
878                                     0)  // UpdatesValue
879              == 0);
880     if (hugoOps.execute_Commit(pNdb) != 0)
881     {
882       NdbError err = hugoOps.getTransaction()->getNdbError();
883       hugoOps.closeTransaction(pNdb);
884       if (err.code == 839)
885       {
886         /* Unique constraint violation, try again with
887          * different record
888          */
889         recordNum++;
890         continue;
891       }
892       else
893       {
894         ERR(err);
895         return NDBT_FAILED;
896       }
897     }
898 
899     hugoOps.closeTransaction(pNdb);
900     break;
901   } while (true);
902 
903   return NDBT_OK;
904 }
905 
906 
runConstraintDetails(NDBT_Context * ctx,NDBT_Step * step)907 int runConstraintDetails(NDBT_Context* ctx, NDBT_Step* step)
908 {
909   const NdbDictionary::Table* pTab = ctx->getTab();
910   Ndb* pNdb = GETNDB(step);
911 
912   /* Steps in testcase
913    * 1) Choose a column to index - not pk or updates column
914    * 2) Insert a couple of unique rows
915    * 3) For a number of different batch sizes :
916    *    i)  Insert a row with a conflicting values
917    *    ii) Update an existing row with a conflicting value
918    *    Verify :
919    *    - The correct error is received
920    *    - The failing constraint is detected
921    *    - The error details string is as expected.
922    */
923   HugoCalculator calc(*pTab);
924 
925   /* Choose column to add unique index to */
926 
927   int chosenCol = -1;
928   const char* idxName = "constraintCheck";
929 
930   int rc = tryAddUniqueIndex(pNdb, pTab, idxName, calc, chosenCol);
931 
932   if (rc)
933   {
934     if (rc == 1)
935     {
936       ndbout << "No suitable column in this table, skipping" << endl;
937       return NDBT_OK;
938     }
939     return NDBT_FAILED;
940   }
941 
942   const NdbDictionary::Index* pIdx =
943     pNdb->getDictionary()->getIndex(idxName, pTab->getName());
944   CHECKRET(pIdx != 0);
945 
946 
947   /* Now insert a couple of rows */
948 
949   HugoOperations hugoOps(*pTab);
950   int firstRecordNum = 0;
951   CHECKRET(tryInsertUniqueRecord(step, hugoOps, firstRecordNum) == NDBT_OK);
952   int secondRecordNum = firstRecordNum + 1;
953   CHECKRET(tryInsertUniqueRecord(step, hugoOps, secondRecordNum) == NDBT_OK);
954 
955 
956   /* Now we'll attempt to insert/update records
957    * in various sized batches and check the errors which
958    * are returned
959    */
960 
961   int maxBatchSize = 10;
962   int recordOffset = secondRecordNum + 1;
963   char buff[NDB_MAX_TUPLE_SIZE];
964   Uint32 real_len;
965   CHECKRET(calc.calcValue(firstRecordNum, chosenCol, 0, &buff[0],
966                           pTab->getColumn(chosenCol)->getSizeInBytes(),
967                           &real_len) != 0);
968 
969   for (int optype = 0; optype < 2; optype ++)
970   {
971     bool useInsert = (optype == 0);
972     ndbout << "Verifying constraint violation for "
973            << (useInsert?"Insert":"Update")
974            << " operations" << endl;
975 
976     for (int batchSize = 1; batchSize <= maxBatchSize; batchSize++)
977     {
978       NdbTransaction* trans = pNdb->startTransaction();
979       CHECKRET(trans != 0);
980 
981       for (int rows = 0; rows < batchSize; rows ++)
982       {
983         int rowId = recordOffset + rows;
984         NdbOperation* op = trans->getNdbOperation(pTab);
985         CHECKRET(op != 0);
986         if (useInsert)
987         {
988           CHECKRET(op->insertTuple() == 0);
989 
990           CHECKRET(hugoOps.setValues(op, rowId, 0) == 0);
991 
992           /* Now override setValue for the indexed column to cause
993            * constraint violation
994            */
995           CHECKRET(op->setValue(chosenCol, &buff[0], real_len) == 0);
996         }
997         else
998         {
999           /* Update value of 'second' row to conflict with
1000            * first
1001            */
1002           CHECKRET(op->updateTuple() == 0);
1003           CHECKRET(hugoOps.equalForRow(op, secondRecordNum) == 0);
1004 
1005           CHECKRET(op->setValue(chosenCol, &buff[0], real_len) == 0);
1006         }
1007       }
1008 
1009       CHECKRET(trans->execute(Commit) == -1);
1010 
1011       NdbError err = trans->getNdbError();
1012 
1013       ERR(err);
1014 
1015       CHECKRET(err.code == 893);
1016 
1017       /* Ugliness - current NdbApi puts index schema object id
1018        * as abs. value of char* in NdbError struct
1019        */
1020 
1021       int idxObjId = (int) ((UintPtr) err.details - UintPtr(0));
1022       char detailsBuff[100];
1023       const char* errIdxName = NULL;
1024 
1025       ndbout_c("Got details column val of %p and string of %s\n",
1026                err.details, pNdb->getNdbErrorDetail(err,
1027                                                     &detailsBuff[0],
1028                                                     100));
1029       if (idxObjId == pIdx->getObjectId())
1030       {
1031         /* Insert / update failed on the constraint we added */
1032         errIdxName = pIdx->getName();
1033       }
1034       else
1035       {
1036         /* We failed on a different constraint.
1037          * Some NDBT tables already have constraints (e.g. I3)
1038          * Check that the failing constraint contains our column
1039          */
1040         NdbDictionary::Dictionary::List tableIndices;
1041 
1042         CHECKRET(pNdb->getDictionary()->listIndexes(tableIndices,
1043                                                     pTab->getName()) == 0);
1044 
1045         bool ok = false;
1046         for (unsigned ind = 0; ind < tableIndices.count; ind ++)
1047         {
1048           if (tableIndices.elements[ind].id == (unsigned) idxObjId)
1049           {
1050             const char* otherIdxName = tableIndices.elements[ind].name;
1051             ndbout << "Found other violated constraint : " << otherIdxName << endl;
1052             const NdbDictionary::Index* otherIndex =
1053               pNdb->getDictionary()->getIndex(otherIdxName,
1054                                               pTab->getName());
1055             CHECKRET(otherIndex != NULL);
1056 
1057             for (unsigned col = 0; col < otherIndex->getNoOfColumns(); col++)
1058             {
1059               if (strcmp(otherIndex->getColumn(col)->getName(),
1060                          pTab->getColumn(chosenCol)->getName()) == 0)
1061               {
1062                 /* Found our column in the index */
1063                 ok = true;
1064                 errIdxName = otherIndex->getName();
1065                 break;
1066               }
1067             }
1068 
1069             if (ok)
1070             {
1071               ndbout << "  Constraint contains unique column " << endl;
1072               break;
1073             }
1074             ndbout << "  Constraint does not contain unique col - fail" << endl;
1075             CHECKRET(false);
1076           }
1077         }
1078 
1079         if (!ok)
1080         {
1081           ndbout << "Did not find violated constraint" << endl;
1082           CHECKRET(false);
1083         }
1084       }
1085 
1086       /* Finally verify the name returned is :
1087        * <db>/<schema>/<table>/<index>
1088        */
1089       BaseString expected;
1090 
1091       expected.assfmt("%s/%s/%s/%s",
1092                       pNdb->getDatabaseName(),
1093                       pNdb->getSchemaName(),
1094                       pTab->getName(),
1095                       errIdxName);
1096 
1097       CHECKRET(strcmp(expected.c_str(), &detailsBuff[0]) == 0);
1098 
1099       ndbout << " OK " << endl;
1100 
1101       trans->close();
1102     }
1103   }
1104 
1105   return NDBT_OK;
1106 }
1107 
runLoadTable(NDBT_Context * ctx,NDBT_Step * step)1108 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
1109   int records = ctx->getNumRecords();
1110 
1111   HugoTransactions hugoTrans(*ctx->getTab());
1112   int batchSize = ctx->getProperty("BatchSize", 1);
1113   if(hugoTrans.loadTable(GETNDB(step), records, batchSize) != 0){
1114     return NDBT_FAILED;
1115   }
1116   return NDBT_OK;
1117 }
1118 
1119 
runClearTable(NDBT_Context * ctx,NDBT_Step * step)1120 int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
1121   int records = ctx->getNumRecords();
1122 
1123   UtilTransactions utilTrans(*ctx->getTab());
1124   if (utilTrans.clearTable(GETNDB(step),  records) != 0){
1125     return NDBT_FAILED;
1126   }
1127   return NDBT_OK;
1128 }
1129 
runSystemRestart1(NDBT_Context * ctx,NDBT_Step * step)1130 int runSystemRestart1(NDBT_Context* ctx, NDBT_Step* step){
1131   Ndb* pNdb = GETNDB(step);
1132   int result = NDBT_OK;
1133   int timeout = 300;
1134   Uint32 loops = ctx->getNumLoops();
1135   int records = ctx->getNumRecords();
1136   int count;
1137   NdbRestarter restarter;
1138   Uint32 i = 1;
1139 
1140   UtilTransactions utilTrans(*ctx->getTab());
1141   HugoTransactions hugoTrans(*ctx->getTab());
1142   while(i<=loops && result != NDBT_FAILED){
1143 
1144     ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
1145     /*
1146       1. Load data
1147       2. Restart cluster and verify records
1148       3. Update records
1149       4. Restart cluster and verify records
1150       5. Delete half of the records
1151       6. Restart cluster and verify records
1152       7. Delete all records
1153       8. Restart cluster and verify records
1154       9. Insert, update, delete records
1155       10. Restart cluster and verify records
1156       11. Insert, update, delete records
1157       12. Restart cluster with error insert 5020 and verify records
1158     */
1159     ndbout << "Loading records..." << endl;
1160     CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0);
1161     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1162 
1163     ndbout << "Restarting cluster" << endl;
1164     CHECK(restarter.restartAll() == 0);
1165     CHECK(restarter.waitClusterStarted(timeout) == 0);
1166     CHECK(pNdb->waitUntilReady(timeout) == 0);
1167 
1168     ndbout << "Verifying records..." << endl;
1169     CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
1170     CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1171     CHECK(count == records);
1172     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1173 
1174     ndbout << "Updating records..." << endl;
1175     CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1176     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1177 
1178     ndbout << "Restarting cluster..." << endl;
1179     CHECK(restarter.restartAll() == 0);
1180     CHECK(restarter.waitClusterStarted(timeout) == 0);
1181     CHECK(pNdb->waitUntilReady(timeout) == 0);
1182 
1183     ndbout << "Verifying records..." << endl;
1184     CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
1185     CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1186     CHECK(count == records);
1187     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1188 
1189     ndbout << "Deleting 50% of records..." << endl;
1190     CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1191     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1192 
1193     ndbout << "Restarting cluster..." << endl;
1194     CHECK(restarter.restartAll() == 0);
1195     CHECK(restarter.waitClusterStarted(timeout) == 0);
1196     CHECK(pNdb->waitUntilReady(timeout) == 0);
1197 
1198     ndbout << "Verifying records..." << endl;
1199     CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
1200     CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1201     CHECK(count == (records/2));
1202     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1203 
1204     ndbout << "Deleting all records..." << endl;
1205     CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
1206     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1207 
1208     ndbout << "Restarting cluster..." << endl;
1209     CHECK(restarter.restartAll() == 0);
1210     CHECK(restarter.waitClusterStarted(timeout) == 0);
1211     CHECK(pNdb->waitUntilReady(timeout) == 0);
1212 
1213     ndbout << "Verifying records..." << endl;
1214     CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1215     CHECK(count == 0);
1216     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1217 
1218     ndbout << "Doing it all..." << endl;
1219     CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0);
1220     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1221     CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1222     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1223     CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1224     CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
1225     CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0);
1226     CHECK(utilTrans.clearTable(pNdb, records) == 0);
1227     CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0);
1228     CHECK(utilTrans.clearTable(pNdb, records) == 0);
1229     CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0);
1230     CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1231     CHECK(utilTrans.clearTable(pNdb, records) == 0);
1232 
1233     ndbout << "Restarting cluster..." << endl;
1234     CHECK(restarter.restartAll() == 0);
1235     CHECK(restarter.waitClusterStarted(timeout) == 0);
1236     CHECK(pNdb->waitUntilReady(timeout) == 0);
1237 
1238     ndbout << "Verifying records..." << endl;
1239     CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1240     CHECK(count == 0);
1241 
1242     ndbout << "Doing it all..." << endl;
1243     CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0);
1244     CHECK(utilTrans.verifyIndex(pNdb, idxName,  16, false) == 0);
1245     CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1246     CHECK(utilTrans.verifyIndex(pNdb, idxName,  16, false) == 0);
1247     CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1248     CHECK(utilTrans.verifyIndex(pNdb, idxName,  16, false) == 0);
1249     CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
1250     CHECK(utilTrans.verifyIndex(pNdb, idxName,  16, false) == 0);
1251     CHECK(utilTrans.clearTable(pNdb, records) == 0);
1252     CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0);
1253     CHECK(utilTrans.clearTable(pNdb, records) == 0);
1254 
1255     ndbout << "Restarting cluster with error insert 5020..." << endl;
1256     CHECK(restarter.restartAll(false, true) == 0);
1257     CHECK(restarter.waitClusterNoStart(timeout) == 0);
1258     CHECK(restarter.insertErrorInAllNodes(5020) == 0);
1259     CHECK(restarter.startAll() == 0);
1260     CHECK(restarter.waitClusterStarted(timeout) == 0);
1261     CHECK(pNdb->waitUntilReady(timeout) == 0);
1262 
1263     i++;
1264   }
1265 
1266   ctx->stopTest();
1267   ndbout << "runSystemRestart1 finished" << endl;
1268 
1269   return result;
1270 }
1271 
1272 #define CHECK2(b, t) if(!b){ g_err << __LINE__ << ": " << t << endl; break;}
1273 #define CHECKOKORTIMEOUT(e, t) { int rc= (e);        \
1274     if (rc != 0) {                                      \
1275       if (rc == 266) {                                  \
1276         g_err << "Timeout : retries left : "            \
1277               << timeoutRetries                         \
1278               << endl;                                  \
1279         continue;                                       \
1280       }                                                 \
1281       g_err << __LINE__ << ": " << (t) << endl; break;  \
1282     } }
1283 
1284 
1285 int
runMixed1(NDBT_Context * ctx,NDBT_Step * step)1286 runMixed1(NDBT_Context* ctx, NDBT_Step* step){
1287   // Verify that data in index match
1288   // table data
1289   Ndb* pNdb = GETNDB(step);
1290   HugoOperations hugoOps(*ctx->getTab());
1291 
1292   /* Old, rather ineffective testcase which nonetheless passes on 6.3 */
1293 
1294   do {
1295     // TC1
1296     g_err << "pkRead, indexRead, Commit" << endl;
1297     CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1298     CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0) == 0, "indexReadRecords");
1299     CHECK2(hugoOps.pkReadRecord(pNdb, 0) == 0, "pkReadRecord");
1300     CHECK2(hugoOps.execute_Commit(pNdb) == 0, "executeCommit");
1301     CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1302 
1303     // TC1
1304     g_err << "pkRead, indexRead, Commit" << endl;
1305     CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1306     CHECK2(hugoOps.pkReadRecord(pNdb, 0) == 0, "pkReadRecord");
1307     CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0) == 0, "indexReadRecords");
1308     CHECK2(hugoOps.execute_Commit(pNdb) == 0, "executeCommit");
1309     CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1310 
1311 
1312     // TC2
1313     g_err << "pkRead, indexRead, NoCommit, Commit" << endl;
1314     CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1315     CHECK2(hugoOps.pkReadRecord(pNdb, 0) == 0, "pkReadRecord");
1316     CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0) == 0,
1317 	   "indexReadRecords");
1318     CHECK2(hugoOps.execute_NoCommit(pNdb) == 0, "executeNoCommit");
1319     CHECK2(hugoOps.execute_Commit(pNdb) == 0, "executeCommit");
1320     CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1321 
1322     // TC3
1323     g_err << "pkRead, pkRead, Commit" << endl;
1324     CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction ");
1325     CHECK2(hugoOps.pkReadRecord(pNdb, 0) == 0, "pkReadRecords ");
1326     CHECK2(hugoOps.pkReadRecord(pNdb, 0) == 0, "pkReadRecords ");
1327     CHECK2(hugoOps.execute_Commit(pNdb) == 0, "executeCommit");
1328     CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction ");
1329 
1330     // TC4
1331     g_err << "indexRead, indexRead, Commit" << endl;
1332 
1333     CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction ");
1334     CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0) == 0, "indexReadRecords");
1335     CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0) == 0, "indexReadRecords");
1336     CHECK2(hugoOps.execute_Commit(pNdb) == 0, "executeCommit");
1337 
1338     CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction ");
1339 
1340     return NDBT_OK;
1341   } while(false);
1342 
1343 
1344   hugoOps.closeTransaction(pNdb);
1345   return NDBT_FAILED;
1346 }
1347 
1348 
1349 
1350 int
runMixedUpdateInterleaved(Ndb * pNdb,HugoOperations & hugoOps,int outOfRangeRec,int testSize,bool commit,bool abort,int pkFailRec,int ixFailRec,bool invertFail,AbortOption ao,int whatToUpdate,int updatesValue,bool ixFirst)1351 runMixedUpdateInterleaved(Ndb* pNdb,
1352                           HugoOperations& hugoOps,
1353                           int outOfRangeRec,
1354                           int testSize,
1355                           bool commit,
1356                           bool abort,
1357                           int pkFailRec,
1358                           int ixFailRec,
1359                           bool invertFail,
1360                           AbortOption ao,
1361                           int whatToUpdate,
1362                           int updatesValue,
1363                           bool ixFirst)
1364 {
1365   Uint32 execRc= 0;
1366   if ((pkFailRec != -1) || (ixFailRec != -1))
1367   {
1368     execRc= 626;
1369   }
1370 
1371   bool updateViaPk= whatToUpdate & 1;
1372   bool updateViaIx= whatToUpdate & 2;
1373 
1374   int ixOpNum= (ixFirst?0:1);
1375   int pkOpNum= (ixFirst?1:0);
1376 
1377   int timeoutRetries= 3;
1378 
1379   while (timeoutRetries--)
1380   {
1381     CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1382     for (int i=0; i < testSize; i++)
1383     {
1384       /* invertFail causes all issued reads *except* the fail record number
1385        * to fail
1386        */
1387       int indxKey= ((i == ixFailRec)^invertFail)? outOfRangeRec : i;
1388       int pkKey= ((i == pkFailRec)^invertFail)? outOfRangeRec : i;
1389 
1390       for (int opNum=0; opNum < 2; opNum++)
1391       {
1392         if (opNum == ixOpNum)
1393         {
1394           if (updateViaIx)
1395           {
1396             CHECK2(hugoOps.indexUpdateRecord(pNdb, pkIdxName, indxKey, 1, updatesValue) == 0,
1397                    "indexUpdateRecord");
1398           }
1399           else
1400           {
1401             CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, indxKey) == 0, "indexReadRecords");
1402           }
1403         }
1404 
1405         if (opNum == pkOpNum)
1406         {
1407           if (updateViaPk)
1408           {
1409             CHECK2(hugoOps.pkUpdateRecord(pNdb, pkKey, 1, updatesValue) == 0,
1410                    "pkUpdateRecord");
1411           }
1412           else
1413           {
1414             CHECK2(hugoOps.pkReadRecord(pNdb, pkKey) == 0, "pkReadRecord");
1415           }
1416         }
1417       }
1418     }
1419     if (commit)
1420     {
1421       int rc= hugoOps.execute_Commit(pNdb, ao);
1422       if (rc == 266)
1423       {
1424         /* Timeout */
1425         g_err << "Timeout : retries left=" << timeoutRetries << endl;
1426         hugoOps.closeTransaction(pNdb);
1427         continue;
1428       }
1429       CHECK2(rc == execRc, "execute_Commit");
1430       NdbError err= hugoOps.getTransaction()->getNdbError();
1431       CHECK2(err.code == execRc, "getNdbError");
1432     }
1433     else
1434     {
1435       int rc= hugoOps.execute_NoCommit(pNdb, ao);
1436       if (rc == 266)
1437       {
1438         /* Timeout */
1439         g_err << "Timeout : retries left=" << timeoutRetries << endl;
1440         hugoOps.closeTransaction(pNdb);
1441         continue;
1442       }
1443       CHECK2(rc == execRc, "execute_NoCommit");
1444       NdbError err= hugoOps.getTransaction()->getNdbError();
1445       CHECK2(err.code == execRc, "getNdbError");
1446       if (execRc && (ao == AO_IgnoreError))
1447       {
1448         /* Transaction should still be open, let's commit it */
1449         CHECK2(hugoOps.execute_Commit(pNdb, ao) == 0, "executeCommit");
1450       }
1451       else if (abort)
1452       {
1453         CHECK2(hugoOps.execute_Rollback(pNdb) == 0, "executeRollback");
1454       }
1455     }
1456     CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1457 
1458     return 1;
1459   }
1460 
1461   hugoOps.closeTransaction(pNdb);
1462   return 0;
1463 }
1464 
1465 
1466 
1467 int
runMixed2(NDBT_Context * ctx,NDBT_Step * step)1468 runMixed2(NDBT_Context* ctx, NDBT_Step* step){
1469   Ndb* pNdb = GETNDB(step);
1470   HugoOperations hugoOps(*ctx->getTab());
1471 
1472   int numRecordsInTable= ctx->getNumRecords();
1473   const int maxTestSize= 10000;
1474   int testSize= MIN(numRecordsInTable, maxTestSize);
1475 
1476   /* Avoid overloading Send Buffers */
1477   Uint32 rowSize=  NdbDictionary::getRecordRowLength(ctx->getTab()->getDefaultRecord());
1478   Uint32 dataXfer= 2 * rowSize * testSize;
1479   const Uint32 MaxDataXfer= 500000; // 0.5M
1480 
1481   if (dataXfer > MaxDataXfer)
1482   {
1483     testSize= MIN((int)(MaxDataXfer/rowSize), testSize);
1484   }
1485 
1486   g_err << "testSize= " << testSize << endl;
1487   g_err << "rowSize= " << rowSize << endl;
1488 
1489   int updatesValue= 1;
1490   const int maxTimeoutRetries= 3;
1491 
1492   do {
1493     // TC0
1494     {
1495       bool ok= false;
1496       int timeoutRetries= maxTimeoutRetries;
1497       while (timeoutRetries--)
1498       {
1499         g_err << "TC0 : indexRead, pkread, Commit" << endl;
1500         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1501         CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0, false, testSize) == 0, "indexReadRecords");
1502         CHECK2(hugoOps.pkReadRecord(pNdb, 0, testSize) == 0, "pkReadRecord");
1503         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1504         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1505 
1506         ok= true;
1507         break;
1508       }
1509       if (!ok) { break; };
1510     }
1511 
1512 
1513     // TC1
1514     {
1515       bool ok= false;
1516       int timeoutRetries= maxTimeoutRetries;
1517       while (timeoutRetries--)
1518       {
1519         g_err << "TC1 : pkRead, indexRead, Commit" << endl;
1520         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1521         CHECK2(hugoOps.pkReadRecord(pNdb, 0, testSize) == 0, "pkReadRecord");
1522         CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0, false, testSize) == 0, "indexReadRecords");
1523         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1524         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1525 
1526         ok= true;
1527         break;
1528       }
1529       if (!ok) { break; };
1530     }
1531 
1532     // TC2
1533     {
1534       bool ok= false;
1535       int timeoutRetries= maxTimeoutRetries;
1536       while (timeoutRetries--)
1537       {
1538         g_err << "TC2 : pkRead, indexRead, NoCommit, Commit" << endl;
1539         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1540         CHECK2(hugoOps.pkReadRecord(pNdb, 0, testSize) == 0, "pkReadRecord");
1541         CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0, false, testSize) == 0,
1542                "indexReadRecords");
1543         CHECKOKORTIMEOUT(hugoOps.execute_NoCommit(pNdb), "executeNoCommit");
1544         CHECK2(hugoOps.execute_Commit(pNdb) == 0, "executeCommit");
1545         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1546         ok= true;
1547         break;
1548       }
1549       if (!ok) { break; };
1550     }
1551 
1552     // TC3
1553     {
1554       bool ok= false;
1555       int timeoutRetries= maxTimeoutRetries;
1556       while (timeoutRetries--)
1557       {
1558         g_err << "TC3 : pkRead, pkRead, Commit" << endl;
1559         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction ");
1560         CHECK2(hugoOps.pkReadRecord(pNdb, 0, testSize) == 0, "pkReadRecords ");
1561         CHECK2(hugoOps.pkReadRecord(pNdb, 0, testSize) == 0, "pkReadRecords ");
1562         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1563         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction ");
1564         ok= true;
1565         break;
1566       }
1567       if (!ok) { break; };
1568     }
1569 
1570     // TC4
1571     {
1572       bool ok= false;
1573       int timeoutRetries= maxTimeoutRetries;
1574       while (timeoutRetries--)
1575       {
1576         g_err << "TC4 : indexRead, indexRead, Commit" << endl;
1577         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction ");
1578         CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0, false, testSize) == 0, "indexReadRecords");
1579         CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0, false, testSize) == 0, "indexReadRecords");
1580         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1581         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction ");
1582         ok= true;
1583         break;
1584       }
1585       if (!ok) { break; };
1586     }
1587 
1588     // TC5
1589     {
1590       bool ok= false;
1591       int timeoutRetries= maxTimeoutRetries;
1592       while (timeoutRetries--)
1593       {
1594         g_err << "TC5 : indexRead, pkUpdate, Commit" << endl;
1595         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1596         CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0, false, testSize) == 0, "indexReadRecords");
1597         CHECK2(hugoOps.pkUpdateRecord(pNdb, 0, testSize, updatesValue++) == 0, "pkUpdateRecord");
1598         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1599         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1600         ok= true;
1601         break;
1602       }
1603       if (!ok) { break; };
1604     }
1605 
1606     // TC6
1607     {
1608       bool ok= false;
1609       int timeoutRetries= maxTimeoutRetries;
1610       while (timeoutRetries--)
1611       {
1612         g_err << "TC6 : pkUpdate, indexRead, Commit" << endl;
1613         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1614         CHECK2(hugoOps.pkUpdateRecord(pNdb, 0, testSize, updatesValue++) == 0, "pkUpdateRecord");
1615         CHECK2(hugoOps.indexReadRecords(pNdb, pkIdxName, 0, false, testSize) == 0, "indexReadRecords");
1616         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1617         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1618         ok= true;
1619         break;
1620       }
1621       if (!ok) { break; };
1622     }
1623 
1624     // TC7
1625     {
1626       bool ok= false;
1627       int timeoutRetries= maxTimeoutRetries;
1628       while (timeoutRetries--)
1629       {
1630         g_err << "TC7 : pkRead, indexUpdate, Commit" << endl;
1631         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction");
1632         CHECK2(hugoOps.pkReadRecord(pNdb, 0, testSize) == 0, "pkReadRecord");
1633         CHECK2(hugoOps.indexUpdateRecord(pNdb, pkIdxName, 0, testSize, updatesValue++) == 0,
1634                "indexReadRecords");
1635         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1636         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction");
1637         ok= true;
1638         break;
1639       }
1640       if (!ok) { break; };
1641     }
1642 
1643     // TC8
1644     {
1645       bool ok= false;
1646       int timeoutRetries= maxTimeoutRetries;
1647       while (timeoutRetries--)
1648       {
1649         g_err << "TC8 : indexUpdate, pkRead, Commit" << endl;
1650         CHECK2(hugoOps.startTransaction(pNdb) == 0, "startTransaction ");
1651         CHECK2(hugoOps.indexUpdateRecord(pNdb, pkIdxName, 0, testSize, updatesValue++) == 0,
1652                "indexReadRecords ");
1653         CHECK2(hugoOps.pkReadRecord(pNdb, 0, testSize) == 0, "pkReadRecords ");
1654         CHECKOKORTIMEOUT(hugoOps.execute_Commit(pNdb), "executeCommit");
1655         CHECK2(hugoOps.closeTransaction(pNdb) == 0, "closeTransaction ");
1656         ok= true;
1657         break;
1658       }
1659       if (!ok) { break; };
1660     }
1661 
1662     for (int ao=0; ao < 2; ao++)
1663     {
1664       AbortOption abortOption= ao?AO_IgnoreError:AbortOnError;
1665 
1666       for (int exType=0; exType < 3; exType++)
1667       {
1668         bool commit= (exType == 1);
1669         bool abort= (exType == 2);
1670 
1671         const char* exTypeStr= ((exType == 0) ? "NoCommit" :
1672                                 (exType == 1) ? "Commit" :
1673                                 "Abort");
1674 
1675         for (int failType= 0; failType < 4; failType++)
1676         {
1677           for (int failPos= 0; failPos < 2; failPos++)
1678           {
1679             int failRec= (failPos == 0)? 0 : testSize -1;
1680             int pkFailRec= -1;
1681             int ixFailRec= -1;
1682             if (failType)
1683             {
1684               if (failType & 1)
1685                 pkFailRec= failRec;
1686               if (failType & 2)
1687                 ixFailRec= failRec;
1688             }
1689 
1690             for (int invFail= 0;
1691                  invFail < ((failType==0)?1:2);
1692                  invFail++)
1693             {
1694               bool invertFail= (invFail)?true:false;
1695               const char* failTypeStr= ((failType==0)? "None" :
1696                                         ((failType==1)? "Pk":
1697                                          ((failType==2)?"Ix": "Both")));
1698               for (int updateVia= 0; updateVia < 3; updateVia++)
1699               {
1700                 const char* updateViaStr= ((updateVia == 0)? "None" :
1701                                            (updateVia == 1)? "Pk" :
1702                                            (updateVia == 2)? "Ix" :
1703                                            "Both");
1704                 for (int updateOrder= 0; updateOrder < 2; updateOrder++)
1705                 {
1706                   bool updateIxFirst= (updateOrder == 0);
1707                   g_err << endl
1708                         << "AbortOption : " << (ao?"IgnoreError":"AbortOnError") << endl
1709                         << "ExecType : " << exTypeStr << endl
1710                         << "Failtype : " << failTypeStr << endl
1711                         << "Failpos : " << ((failPos == 0)? "Early" : "Late") << endl
1712                         << "Failure scenarios : " << (invFail?"All but one":"one") << endl
1713                         << "UpdateVia : " << updateViaStr << endl
1714                         << "Order : " << (updateIxFirst? "Index First" : "Pk first") << endl;
1715                   bool ok= false;
1716                   do
1717                   {
1718                     g_err << "Mixed read/update interleaved" << endl;
1719                     CHECK2(runMixedUpdateInterleaved(pNdb, hugoOps, numRecordsInTable, testSize,
1720                                                      commit,  // Commit
1721                                                      abort, // Abort
1722                                                      pkFailRec,    // PkFail
1723                                                      ixFailRec,   // IxFail
1724                                                      invertFail, // Invertfail
1725                                                      abortOption,
1726                                                      updateVia,
1727                                                      updatesValue++,
1728                                                      updateIxFirst),
1729                          "TC4");
1730 
1731                     ok= true;
1732                   } while (false);
1733 
1734                   if (!ok)
1735                   {
1736                     hugoOps.closeTransaction(pNdb);
1737                     return NDBT_FAILED;
1738                   }
1739                 }
1740               }
1741             }
1742           }
1743         }
1744       }
1745     }
1746 
1747     return NDBT_OK;
1748   } while (false);
1749 
1750   hugoOps.closeTransaction(pNdb);
1751   return NDBT_FAILED;
1752 }
1753 
1754 #define check(b, e)                                                     \
1755   if (!(b)) { g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ << ": " << e.getNdbError() << endl; return NDBT_FAILED; }
1756 
runRefreshTupleAbort(NDBT_Context * ctx,NDBT_Step * step)1757 int runRefreshTupleAbort(NDBT_Context* ctx, NDBT_Step* step){
1758   int records = ctx->getNumRecords();
1759   int loops = ctx->getNumLoops();
1760 
1761   Ndb* ndb = GETNDB(step);
1762 
1763   const NdbDictionary::Table& tab = *ctx->getTab();
1764 
1765   for (int i=0; i < tab.getNoOfColumns(); i++)
1766   {
1767     if (tab.getColumn(i)->getStorageType() == NDB_STORAGETYPE_DISK)
1768     {
1769       g_err << "Table has disk column(s) skipping." << endl;
1770       return NDBT_OK;
1771     }
1772   }
1773 
1774 
1775   g_err << "Loading table." << endl;
1776   HugoTransactions hugoTrans(*ctx->getTab());
1777   check(hugoTrans.loadTable(ndb, records) == 0, hugoTrans);
1778 
1779   HugoOperations hugoOps(*ctx->getTab());
1780 
1781   /* Check refresh, abort sequence with an ordered index
1782    * Previously this gave bugs due to corruption of the
1783    * tuple version
1784    */
1785   while (loops--)
1786   {
1787     Uint32 numRefresh = 2 + rand() % 10;
1788 
1789     g_err << "Refresh, rollback * " << numRefresh << endl;
1790 
1791     while (--numRefresh)
1792     {
1793       /* Refresh, rollback */
1794       check(hugoOps.startTransaction(ndb) == 0, hugoOps);
1795       check(hugoOps.pkRefreshRecord(ndb, 0, records, 0) == 0, hugoOps);
1796       check(hugoOps.execute_NoCommit(ndb) == 0, hugoOps);
1797       check(hugoOps.execute_Rollback(ndb) == 0, hugoOps);
1798       check(hugoOps.closeTransaction(ndb) == 0, hugoOps);
1799     }
1800 
1801     g_err << "Refresh, commit" << endl;
1802     /* Refresh, commit */
1803     check(hugoOps.startTransaction(ndb) == 0, hugoOps);
1804     check(hugoOps.pkRefreshRecord(ndb, 0, records, 0) == 0, hugoOps);
1805     check(hugoOps.execute_NoCommit(ndb) == 0, hugoOps);
1806     check(hugoOps.execute_Commit(ndb) == 0, hugoOps);
1807     check(hugoOps.closeTransaction(ndb) == 0, hugoOps);
1808 
1809     g_err << "Update, commit" << endl;
1810     /* Update */
1811     check(hugoOps.startTransaction(ndb) == 0, hugoOps);
1812     check(hugoOps.pkUpdateRecord(ndb, 0, records, 2 + loops) == 0, hugoOps);
1813     check(hugoOps.execute_NoCommit(ndb) == 0, hugoOps);
1814     check(hugoOps.execute_Commit(ndb) == 0, hugoOps);
1815     check(hugoOps.closeTransaction(ndb) == 0, hugoOps);
1816   }
1817 
1818   return NDBT_OK;
1819 }
1820 
1821 
1822 int
runBuildDuring(NDBT_Context * ctx,NDBT_Step * step)1823 runBuildDuring(NDBT_Context* ctx, NDBT_Step* step){
1824   // Verify that data in index match
1825   // table data
1826   const int Threads = ctx->getProperty("Threads", (Uint32)0);
1827   const int loops = ctx->getNumLoops();
1828 
1829   for(int i = 0; i<loops; i++){
1830 #if 1
1831     if(createPkIndex(ctx, step) != NDBT_OK){
1832       g_err << "Failed to create index" << endl;
1833       return NDBT_FAILED;
1834     }
1835 #endif
1836 
1837     if(ctx->isTestStopped())
1838       break;
1839 
1840 #if 1
1841     if(createRandomIndex(ctx, step) != NDBT_OK){
1842       g_err << "Failed to create index" << endl;
1843       return NDBT_FAILED;
1844     }
1845 #endif
1846 
1847     if(ctx->isTestStopped())
1848       break;
1849 
1850     ctx->setProperty("pause", 1);
1851     int count = 0;
1852     for(int j = 0; count < Threads && !ctx->isTestStopped();
1853 	j = (j+1) % Threads){
1854       char buf[255];
1855       sprintf(buf, "Thread%d_paused", j);
1856       int tmp = ctx->getProperty(buf, (Uint32)0);
1857       count += tmp;
1858     }
1859 
1860     if(ctx->isTestStopped())
1861       break;
1862 
1863 #if 1
1864     if(createPkIndex_Drop(ctx, step) != NDBT_OK){
1865       g_err << "Failed to drop index" << endl;
1866       return NDBT_FAILED;
1867     }
1868 #endif
1869 
1870     if(ctx->isTestStopped())
1871       break;
1872 
1873 #if 1
1874     if(createRandomIndex_Drop(ctx, step) != NDBT_OK){
1875       g_err << "Failed to drop index" << endl;
1876       return NDBT_FAILED;
1877     }
1878 #endif
1879 
1880     ctx->setProperty("pause", (Uint32)0);
1881     NdbSleep_SecSleep(2);
1882   }
1883 
1884   ctx->stopTest();
1885   return NDBT_OK;
1886 }
1887 
1888 static NdbLockable g_lock;
1889 static int threadCounter = 0;
1890 
1891 void
wait_paused(NDBT_Context * ctx,int id)1892 wait_paused(NDBT_Context* ctx, int id){
1893   if(ctx->getProperty("pause", (Uint32)0) == 1){
1894     char buf[255];
1895     sprintf(buf, "Thread%d_paused", id);
1896     ctx->setProperty(buf, 1);
1897     while(!ctx->isTestStopped() && ctx->getProperty("pause", (Uint32)0) == 1){
1898       NdbSleep_MilliSleep(250);
1899     }
1900     ctx->setProperty(buf, (Uint32)0);
1901   }
1902 }
1903 
1904 int
runTransactions4(NDBT_Context * ctx,NDBT_Step * step)1905 runTransactions4(NDBT_Context* ctx, NDBT_Step* step){
1906 
1907   g_lock.lock();
1908   const int ThreadId = threadCounter++;
1909   g_lock.unlock();
1910 
1911   // Verify that data in index match
1912   // table data
1913   Ndb* pNdb = GETNDB(step);
1914   HugoTransactions hugoTrans(*ctx->getTab());
1915   UtilTransactions utilTrans(*ctx->getTab());
1916   const int batchSize = ctx->getProperty("BatchSize", 32);
1917   const int parallel = batchSize > 240 ? 240 : batchSize;
1918 
1919   int rows = ctx->getNumRecords();
1920   while (ctx->isTestStopped() == false) {
1921     if(hugoTrans.loadTable(pNdb, rows, batchSize, false) != 0){
1922       g_err << "Load table failed" << endl;
1923       return NDBT_FAILED;
1924     }
1925 
1926     wait_paused(ctx, ThreadId);
1927 
1928     if(ctx->isTestStopped())
1929       break;
1930 
1931     if (hugoTrans.pkUpdateRecords(pNdb, rows, batchSize) != 0){
1932       g_err << "Updated table failed" << endl;
1933       return NDBT_FAILED;
1934     }
1935 
1936     wait_paused(ctx, ThreadId);
1937 
1938     if(ctx->isTestStopped())
1939       break;
1940 
1941     if (hugoTrans.scanUpdateRecords(pNdb, rows, 5, parallel) != 0){
1942       g_err << "Scan updated table failed" << endl;
1943       return NDBT_FAILED;
1944     }
1945 
1946     wait_paused(ctx, ThreadId);
1947 
1948     if(ctx->isTestStopped())
1949       break;
1950 
1951     if(utilTrans.clearTable(pNdb, rows, parallel) != 0){
1952       g_err << "Clear table failed" << endl;
1953       return NDBT_FAILED;
1954     }
1955   }
1956   return NDBT_OK;
1957 }
1958 
1959 int
runUniqueNullTransactions(NDBT_Context * ctx,NDBT_Step * step)1960 runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){
1961   Ndb* pNdb = GETNDB(step);
1962 
1963   bool logged = ctx->getProperty("LoggedIndexes", 1);
1964   bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
1965   NdbConnection * pTrans = 0;
1966 
1967   const NdbDictionary::Table* pTab = ctx->getTab();
1968   // Create index
1969   char nullIndex[255];
1970   BaseString::snprintf(nullIndex, 255, "IDC_PK_%s_NULL", pTab->getName());
1971   if (orderedIndex)
1972     ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "
1973 	   << pkIdxName << " (";
1974   else
1975     ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index "
1976 	   << pkIdxName << " (";
1977 
1978   NdbDictionary::Index pIdx(pkIdxName);
1979   pIdx.setTable(pTab->getName());
1980   if (orderedIndex)
1981     pIdx.setType(NdbDictionary::Index::OrderedIndex);
1982   else
1983     pIdx.setType(NdbDictionary::Index::UniqueHashIndex);
1984   pIdx.setStoredIndex(logged);
1985   int c;
1986   for (c = 0; c< pTab->getNoOfColumns(); c++){
1987     const NdbDictionary::Column * col = pTab->getColumn(c);
1988     if(col->getPrimaryKey()){
1989       pIdx.addIndexColumn(col->getName());
1990       ndbout << col->getName() <<" ";
1991     }
1992   }
1993 
1994   int colId = -1;
1995   for (c = 0; c< pTab->getNoOfColumns(); c++){
1996     const NdbDictionary::Column * col = pTab->getColumn(c);
1997     if(col->getNullable()){
1998       pIdx.addIndexColumn(col->getName());
1999       ndbout << col->getName() <<" ";
2000       colId = c;
2001       break;
2002     }
2003   }
2004   ndbout << ") ";
2005 
2006   if(colId == -1){
2007     ndbout << endl << "No nullable column found -> NDBT_FAILED" << endl;
2008     return NDBT_FAILED;
2009   }
2010 
2011   bool noddl= ctx->getProperty("NoDDL");
2012   if (noddl)
2013   {
2014     const NdbDictionary::Index* idx= pNdb->
2015       getDictionary()->getIndex(pIdx.getName(), pTab->getName());
2016 
2017     if (!idx)
2018     {
2019       ndbout << "Failed - Index does not exist and DDL not allowed" << endl;
2020       ERR(pNdb->getDictionary()->getNdbError());
2021       return NDBT_FAILED;
2022     }
2023     else
2024     {
2025       // TODO : Check index definition is ok
2026     }
2027   }
2028   else
2029   {
2030     if (pNdb->getDictionary()->createIndex(pIdx) != 0){
2031       ndbout << "FAILED!" << endl;
2032       const NdbError err = pNdb->getDictionary()->getNdbError();
2033       ERR(err);
2034       return NDBT_FAILED;
2035     }
2036   }
2037 
2038   int result = NDBT_OK;
2039 
2040   HugoTransactions hugoTrans(*ctx->getTab());
2041   const int batchSize = ctx->getProperty("BatchSize", 50);
2042   int loops = ctx->getNumLoops();
2043   int rows = ctx->getNumRecords();
2044   while (loops-- > 0 && ctx->isTestStopped() == false) {
2045     if (hugoTrans.pkUpdateRecords(pNdb, rows, batchSize) != 0){
2046       g_err << "Updated table failed" << endl;
2047       result = NDBT_FAILED;
2048       goto done;
2049     }
2050   }
2051 
2052   if(ctx->isTestStopped()){
2053     goto done;
2054   }
2055 
2056   ctx->stopTest();
2057   while(ctx->getNoOfRunningSteps() > 1){
2058     NdbSleep_MilliSleep(100);
2059   }
2060 
2061   result = NDBT_FAILED;
2062   pTrans = pNdb->startTransaction();
2063   NdbScanOperation * sOp;
2064 
2065   int eof;
2066   if(!pTrans) goto done;
2067   sOp = pTrans->getNdbScanOperation(pTab->getName());
2068   if(!sOp) goto done;
2069   if(sOp->readTuples(NdbScanOperation::LM_Exclusive)) goto done;
2070   if(pTrans->execute(NoCommit) == -1) goto done;
2071   while((eof = sOp->nextResult(true)) == 0){
2072     do {
2073       NdbOperation * uOp = sOp->updateCurrentTuple();
2074       if(uOp == 0) goto done;
2075       uOp->setValue(colId, 0);
2076     } while((eof = sOp->nextResult(false)) == 0);
2077     eof = pTrans->execute(Commit);
2078     if(eof == -1) goto done;
2079   }
2080 
2081  done:
2082   if(pTrans) pNdb->closeTransaction(pTrans);
2083   pNdb->getDictionary()->dropIndex(nullIndex, pTab->getName());
2084   return result;
2085 }
2086 
runLQHKEYREF(NDBT_Context * ctx,NDBT_Step * step)2087 int runLQHKEYREF(NDBT_Context* ctx, NDBT_Step* step){
2088   int loops = ctx->getNumLoops() * 100;
2089   NdbRestarter restarter;
2090 
2091   myRandom48Init((long)NdbTick_CurrentMillisecond());
2092 
2093 #if 0
2094   int val = DumpStateOrd::DihMinTimeBetweenLCP;
2095   if(restarter.dumpStateAllNodes(&val, 1) != 0){
2096     g_err << "Failed to dump DihMinTimeBetweenLCP" << endl;
2097     return NDBT_FAILED;
2098   }
2099 #endif
2100 
2101   for(int i = 0; i<loops && !ctx->isTestStopped(); i++){
2102     int randomId = myRandom48(restarter.getNumDbNodes());
2103     int nodeId = restarter.getDbNodeId(randomId);
2104 
2105     const Uint32 error = 5031 + (i % 3);
2106 
2107     if(restarter.insertErrorInNode(nodeId, error) != 0){
2108       g_err << "Failed to error insert( " << error << ") in node "
2109 	    << nodeId << endl;
2110       return NDBT_FAILED;
2111     }
2112   }
2113 
2114   ctx->stopTest();
2115   return NDBT_OK;
2116 }
2117 
2118 int
runBug21384(NDBT_Context * ctx,NDBT_Step * step)2119 runBug21384(NDBT_Context* ctx, NDBT_Step* step)
2120 {
2121   Ndb* pNdb = GETNDB(step);
2122   HugoTransactions hugoTrans(*ctx->getTab());
2123   NdbRestarter restarter;
2124 
2125   int loops = ctx->getNumLoops();
2126   const int rows = ctx->getNumRecords();
2127   const int batchsize = ctx->getProperty("BatchSize", 50);
2128 
2129   while (loops--)
2130   {
2131     if(restarter.insertErrorInAllNodes(8037) != 0)
2132     {
2133       g_err << "Failed to error insert(8037)" << endl;
2134       return NDBT_FAILED;
2135     }
2136 
2137     if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchsize) == 0)
2138     {
2139       g_err << "Index succeded (it should have failed" << endl;
2140       return NDBT_FAILED;
2141     }
2142 
2143     if(restarter.insertErrorInAllNodes(0) != 0)
2144     {
2145       g_err << "Failed to error insert(0)" << endl;
2146       return NDBT_FAILED;
2147     }
2148 
2149     if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchsize) != 0){
2150       g_err << "Index read failed" << endl;
2151       return NDBT_FAILED;
2152     }
2153   }
2154 
2155   return NDBT_OK;
2156 }
2157 
2158 int
runReadIndexUntilStopped(NDBT_Context * ctx,NDBT_Step * step)2159 runReadIndexUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
2160 {
2161   Ndb* pNdb = GETNDB(step);
2162   HugoTransactions hugoTrans(*ctx->getTab());
2163   int rows = ctx->getNumRecords();
2164   while (!ctx->isTestStopped())
2165   {
2166     hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, 1);
2167   }
2168   return NDBT_OK;
2169 }
2170 
2171 int
runBug25059(NDBT_Context * ctx,NDBT_Step * step)2172 runBug25059(NDBT_Context* ctx, NDBT_Step* step)
2173 {
2174   Ndb* pNdb = GETNDB(step);
2175   NdbDictionary::Dictionary * dict = pNdb->getDictionary();
2176   const NdbDictionary::Index * idx = dict->getIndex(pkIdxName,
2177 						    ctx->getTab()->getName());
2178 
2179   HugoOperations ops(*ctx->getTab(), idx);
2180 
2181   int res = NDBT_OK;
2182   int loops = ctx->getNumLoops();
2183   const int rows = ctx->getNumRecords();
2184 
2185   while (res == NDBT_OK && loops--)
2186   {
2187     ops.startTransaction(pNdb);
2188     ops.pkReadRecord(pNdb, 10 + rand() % rows, rows);
2189     int tmp;
2190     if ((tmp = ops.execute_Commit(pNdb, AO_IgnoreError)))
2191     {
2192       if (tmp == 4012)
2193 	res = NDBT_FAILED;
2194       else
2195 	if (ops.getTransaction()->getNdbError().code == 4012)
2196 	  res = NDBT_FAILED;
2197     }
2198     ops.closeTransaction(pNdb);
2199   }
2200 
2201   loops = ctx->getNumLoops();
2202   while (res == NDBT_OK && loops--)
2203   {
2204     ops.startTransaction(pNdb);
2205     ops.pkUpdateRecord(pNdb, 10 + rand() % rows, rows);
2206     int tmp;
2207     int arg;
2208     switch(rand() % 2){
2209     case 0:
2210       arg = AbortOnError;
2211       break;
2212     case 1:
2213       arg = AO_IgnoreError;
2214       ndbout_c("ignore error");
2215       break;
2216     }
2217     if ((tmp = ops.execute_Commit(pNdb, (AbortOption)arg)))
2218     {
2219       if (tmp == 4012)
2220 	res = NDBT_FAILED;
2221       else
2222 	if (ops.getTransaction()->getNdbError().code == 4012)
2223 	  res = NDBT_FAILED;
2224     }
2225     ops.closeTransaction(pNdb);
2226   }
2227 
2228   return res;
2229 }
2230 
2231 // From 6.3.X, Unique index operations do not use
2232 // TransactionBufferMemory.
2233 // Long signal KeyInfo and AttrInfo storage exhaustion
2234 // is already tested by testLimits
2235 // Testing of segment exhaustion when accumulating from
2236 // signal trains cannot be tested from 7.0 as we cannot
2237 // generate short signal trains.
2238 // TODO : Execute testcase as part of upgrade testing -
2239 // 6.3 to 7.0?
tcSaveINDX_test(NDBT_Context * ctx,NDBT_Step * step,int inject_err)2240 int tcSaveINDX_test(NDBT_Context* ctx, NDBT_Step* step, int inject_err)
2241 {
2242   int result= NDBT_OK;
2243   Ndb* pNdb = GETNDB(step);
2244   NdbDictionary::Dictionary * dict = pNdb->getDictionary();
2245   const NdbDictionary::Index * idx = dict->getIndex(pkIdxName,
2246                                                     ctx->getTab()->getName());
2247 
2248   HugoOperations ops(*ctx->getTab(), idx);
2249 
2250   g_err << "Using INDEX: " << pkIdxName << endl;
2251 
2252   NdbRestarter restarter;
2253 
2254   int loops = ctx->getNumLoops();
2255   const int rows = ctx->getNumRecords();
2256 
2257   for(int bs=1; bs < loops; bs++)
2258   {
2259     int c= 0;
2260     while (c++ < loops)
2261     {
2262       g_err << "BS " << bs << " LOOP #" << c << endl;
2263 
2264       g_err << "inserting error on op#" << c << endl;
2265 
2266       CHECK(ops.startTransaction(pNdb) == 0);
2267       for(int i=1;i<=c;i++)
2268       {
2269         if(i==c)
2270         {
2271           if(restarter.insertErrorInAllNodes(inject_err)!=0)
2272           {
2273             g_err << "**** FAILED to insert error" << endl;
2274             result= NDBT_FAILED;
2275             break;
2276           }
2277         }
2278         CHECK(ops.indexReadRecords(pNdb, pkIdxName, i,false,1) == 0);
2279         if(i%bs==0 || i==c)
2280         {
2281           if(i<c)
2282           {
2283             if(ops.execute_NoCommit(pNdb, AO_IgnoreError)!=NDBT_OK)
2284             {
2285               g_err << "**** executeNoCommit should have succeeded" << endl;
2286               result= NDBT_FAILED;
2287             }
2288           }
2289           else
2290           {
2291             if(ops.execute_NoCommit(pNdb, AO_IgnoreError)!=289)
2292             {
2293               g_err << "**** executeNoCommit should have failed with 289"
2294                     << endl;
2295               result= NDBT_FAILED;
2296             }
2297             g_err << "NdbError.code= " <<
2298               ops.getTransaction()->getNdbError().code << endl;
2299             break;
2300           }
2301         }
2302       }
2303 
2304       CHECK(ops.closeTransaction(pNdb) == 0);
2305 
2306       if(restarter.insertErrorInAllNodes(0) != 0)
2307       {
2308         g_err << "**** Failed to error insert(0)" << endl;
2309         return NDBT_FAILED;
2310       }
2311 
2312       CHECK(ops.startTransaction(pNdb) == 0);
2313       if (ops.indexReadRecords(pNdb, pkIdxName,0,0,rows) != 0){
2314         g_err << "**** Index read failed" << endl;
2315         return NDBT_FAILED;
2316       }
2317       CHECK(ops.closeTransaction(pNdb) == 0);
2318     }
2319   }
2320 
2321   return result;
2322 }
2323 
2324 int
runBug28804(NDBT_Context * ctx,NDBT_Step * step)2325 runBug28804(NDBT_Context* ctx, NDBT_Step* step)
2326 {
2327   return tcSaveINDX_test(ctx, step, 8052);
2328 }
2329 
2330 int
runBug28804_ATTRINFO(NDBT_Context * ctx,NDBT_Step * step)2331 runBug28804_ATTRINFO(NDBT_Context* ctx, NDBT_Step* step)
2332 {
2333   return tcSaveINDX_test(ctx, step, 8051);
2334 }
2335 
2336 int
runBug46069(NDBT_Context * ctx,NDBT_Step * step)2337 runBug46069(NDBT_Context* ctx, NDBT_Step* step)
2338 {
2339   HugoTransactions hugoTrans(*ctx->getTab());
2340   Ndb* pNdb = GETNDB(step);
2341   const int rows = ctx->getNumRecords();
2342   Uint32 threads = ctx->getProperty("THREADS", 12);
2343   int loops = ctx->getNumLoops();
2344 
2345   ctx->getPropertyWait("STARTED", threads);
2346 
2347   for (int i = 0; i<loops; i++)
2348   {
2349     ndbout << "Loop: " << i << endl;
2350     if (hugoTrans.loadTable(pNdb, rows) != 0)
2351       return NDBT_FAILED;
2352 
2353     ctx->setProperty("STARTED", Uint32(0));
2354     ctx->getPropertyWait("STARTED", threads);
2355   }
2356 
2357   ctx->stopTest();
2358   return NDBT_OK;
2359 }
2360 
2361 int
runBug46069_pkdel(NDBT_Context * ctx,NDBT_Step * step)2362 runBug46069_pkdel(NDBT_Context* ctx, NDBT_Step* step)
2363 {
2364   HugoOperations hugoOps(*ctx->getTab());
2365   Ndb* pNdb = GETNDB(step);
2366   const int rows = ctx->getNumRecords();
2367 
2368   while(!ctx->isTestStopped())
2369   {
2370     ctx->incProperty("STARTED");
2371     ctx->getPropertyWait("STARTED", Uint32(0));
2372     if (ctx->isTestStopped())
2373       break;
2374 
2375     for (int i = 0; i<rows && !ctx->isTestStopped(); )
2376     {
2377       int cnt = (rows - i);
2378       if (cnt > 100)
2379         cnt = 100;
2380       cnt = 1 + (rand() % cnt);
2381       if (hugoOps.startTransaction(pNdb) != 0)
2382       {
2383         break;
2384       }
2385       hugoOps.pkDeleteRecord(pNdb, i, cnt);
2386       int res = hugoOps.execute_Commit(pNdb, AO_IgnoreError);
2387       if (res != -1)
2388       {
2389         i += cnt;
2390       }
2391       hugoOps.closeTransaction(pNdb);
2392     }
2393   }
2394 
2395   return NDBT_OK;
2396 }
2397 
2398 int
runBug46069_scandel(NDBT_Context * ctx,NDBT_Step * step)2399 runBug46069_scandel(NDBT_Context* ctx, NDBT_Step* step)
2400 {
2401   Ndb* pNdb = GETNDB(step);
2402   NdbDictionary::Dictionary * dict = pNdb->getDictionary();
2403   const NdbDictionary::Index * idx = dict->getIndex(pkIdxName,
2404 						    ctx->getTab()->getName());
2405   if (idx == 0)
2406   {
2407     return NDBT_FAILED;
2408   }
2409   UtilTransactions hugoTrans(*ctx->getTab(), idx);
2410 
2411   while(!ctx->isTestStopped())
2412   {
2413     ctx->incProperty("STARTED");
2414     ctx->getPropertyWait("STARTED", Uint32(0));
2415     if (ctx->isTestStopped())
2416       break;
2417 
2418     hugoTrans.clearTable(pNdb);
2419   }
2420 
2421   return NDBT_OK;
2422 }
2423 
2424 int
runBug50118(NDBT_Context * ctx,NDBT_Step * step)2425 runBug50118(NDBT_Context* ctx, NDBT_Step* step)
2426 {
2427   NdbSleep_MilliSleep(500);
2428   int loops = ctx->getNumLoops();
2429   while (loops--)
2430   {
2431     createPkIndex_Drop(ctx, step);
2432     createPkIndex(ctx, step);
2433   }
2434   ctx->stopTest();
2435   return NDBT_OK;
2436 }
2437 
2438 int
runTrigOverload(NDBT_Context * ctx,NDBT_Step * step)2439 runTrigOverload(NDBT_Context* ctx, NDBT_Step* step)
2440 {
2441   /* Test inserts, deletes and updates via
2442    * PK with error inserts
2443    */
2444   Ndb* pNdb = GETNDB(step);
2445   HugoOperations hugoOps(*ctx->getTab());
2446   NdbRestarter restarter;
2447 
2448   unsigned numScenarios = 3;
2449   unsigned errorInserts[3] = {8085, 8086, 0};
2450   int results[3] = {218, 218, 0};
2451 
2452   unsigned iterations = 50;
2453 
2454   /* Insert some records */
2455   if (hugoOps.startTransaction(pNdb) ||
2456       hugoOps.pkInsertRecord(pNdb, 0, iterations) ||
2457       hugoOps.execute_Commit(pNdb))
2458   {
2459     g_err << "Failed on initial insert "
2460           << pNdb->getNdbError()
2461           << endl;
2462     return NDBT_FAILED;
2463   }
2464 
2465   hugoOps.closeTransaction(pNdb);
2466 
2467   for(unsigned i = 0 ; i < iterations; i++)
2468   {
2469     unsigned scenario = i % numScenarios;
2470     unsigned errorVal = errorInserts[ scenario ];
2471     g_err << "Iteration :" << i
2472           << " inserting error " << errorVal
2473           << " expecting result : " << results[scenario]
2474           << endl;
2475     restarter.insertErrorInAllNodes(errorVal);
2476     //    NdbSleep_MilliSleep(500); // Error insert latency?
2477 
2478     CHECKRET(hugoOps.startTransaction(pNdb) == 0);
2479 
2480     CHECKRET(hugoOps.pkInsertRecord(pNdb, iterations + i, 1) == 0);
2481 
2482     hugoOps.execute_Commit(pNdb);
2483 
2484     int errorCode = hugoOps.getTransaction()->getNdbError().code;
2485 
2486     if (errorCode != results[scenario])
2487     {
2488       g_err << "For Insert in scenario " << scenario
2489             << " expected code " << results[scenario]
2490             << " but got " << hugoOps.getTransaction()->getNdbError()
2491             << endl;
2492       return NDBT_FAILED;
2493     }
2494 
2495     hugoOps.closeTransaction(pNdb);
2496 
2497     CHECKRET(hugoOps.startTransaction(pNdb) == 0);
2498 
2499     CHECKRET(hugoOps.pkUpdateRecord(pNdb, i, 1, iterations) == 0);
2500 
2501     hugoOps.execute_Commit(pNdb);
2502 
2503     errorCode = hugoOps.getTransaction()->getNdbError().code;
2504 
2505     if (errorCode != results[scenario])
2506     {
2507       g_err << "For Update in scenario " << scenario
2508             << " expected code " << results[scenario]
2509             << " but got " << hugoOps.getTransaction()->getNdbError()
2510             << endl;
2511       return NDBT_FAILED;
2512     }
2513 
2514     hugoOps.closeTransaction(pNdb);
2515 
2516     CHECKRET(hugoOps.startTransaction(pNdb) == 0);
2517 
2518     CHECKRET(hugoOps.pkDeleteRecord(pNdb, i, 1) == 0);
2519 
2520     hugoOps.execute_Commit(pNdb);
2521 
2522     errorCode = hugoOps.getTransaction()->getNdbError().code;
2523 
2524     if (errorCode != results[scenario])
2525     {
2526       g_err << "For Delete in scenario " << scenario
2527             << " expected code " << results[scenario]
2528             << " but got " << hugoOps.getTransaction()->getNdbError()
2529             << endl;
2530       return NDBT_FAILED;
2531     }
2532 
2533     hugoOps.closeTransaction(pNdb);
2534 
2535   }
2536 
2537   restarter.insertErrorInAllNodes(0);
2538 
2539   return NDBT_OK;
2540 }
2541 
2542 int
runClearError(NDBT_Context * ctx,NDBT_Step * step)2543 runClearError(NDBT_Context* ctx, NDBT_Step* step)
2544 {
2545   NdbRestarter restarter;
2546 
2547   restarter.insertErrorInAllNodes(0);
2548 
2549   return NDBT_OK;
2550 }
2551 
2552 // bug#56829
2553 
2554 #undef CHECK2 // previous no good
2555 #define CHECK2(b, e) \
2556   if (!(b)) { \
2557     g_err << "ERR: " << #b << " failed at line " << __LINE__ \
2558           << ": " << e << endl; \
2559     result = NDBT_FAILED; \
2560     break; \
2561   }
2562 
2563 static int
get_data_memory_pages(NdbMgmHandle h,NdbNodeBitmask dbmask,int * pages_out)2564 get_data_memory_pages(NdbMgmHandle h, NdbNodeBitmask dbmask, int* pages_out)
2565 {
2566   int result = NDBT_OK;
2567   int pages = 0;
2568 
2569   while (1)
2570   {
2571     // sends dump 1000 and retrieves all replies
2572     ndb_mgm_events* e = 0;
2573     CHECK2((e = ndb_mgm_dump_events(h, NDB_LE_MemoryUsage, 0, 0)) != 0, ndb_mgm_get_latest_error_msg(h));
2574 
2575     // sum up pages (also verify sanity)
2576     for (int i = 0; i < e->no_of_events; i++)
2577     {
2578       ndb_logevent* le = &e->events[i];
2579       CHECK2(le->type == NDB_LE_MemoryUsage, "bad event type " << le->type);
2580       const ndb_logevent_MemoryUsage* lem = &le->MemoryUsage;
2581       if (lem->block != DBTUP)
2582         continue;
2583       int nodeId = le->source_nodeid;
2584       CHECK2(dbmask.get(nodeId), "duplicate event from node " << nodeId);
2585       dbmask.clear(nodeId);
2586       pages += lem->pages_used;
2587       g_info << "i:" << i << " node:" << le->source_nodeid << " pages:" << lem->pages_used << endl;
2588     }
2589     free(e);
2590     CHECK2(result == NDBT_OK, "failed");
2591 
2592     char buf[NdbNodeBitmask::TextLength + 1];
2593     CHECK2(dbmask.isclear(), "no response from nodes " << dbmask.getText(buf));
2594     break;
2595   }
2596 
2597   *pages_out = pages;
2598   return result;
2599 }
2600 
2601 int
runBug56829(NDBT_Context * ctx,NDBT_Step * step)2602 runBug56829(NDBT_Context* ctx, NDBT_Step* step)
2603 {
2604   Ndb* pNdb = GETNDB(step);
2605   NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2606   const int loops = ctx->getNumLoops();
2607   int result = NDBT_OK;
2608   const NdbDictionary::Table tab(*ctx->getTab());
2609   const int rows = ctx->getNumRecords();
2610   const char* mgm = 0;//XXX ctx->getRemoteMgm();
2611 
2612   char tabname[100];
2613   strcpy(tabname, tab.getName());
2614   char indname[100];
2615   strcpy(indname, tabname);
2616   strcat(indname, "X1");
2617 
2618   (void)pDic->dropTable(tabname);
2619 
2620   NdbMgmHandle h = 0;
2621   NdbNodeBitmask dbmask;
2622   // entry n marks if row with PK n exists
2623   char* rowmask = new char [rows];
2624   memset(rowmask, 0, rows);
2625   int loop = 0;
2626   while (loop < loops)
2627   {
2628     CHECK2(rows > 0, "rows must be != 0");
2629     g_info << "loop " << loop << "<" << loops << endl;
2630 
2631     // at first loop connect to mgm
2632     if (loop == 0)
2633     {
2634       CHECK2((h = ndb_mgm_create_handle()) != 0, "mgm: failed to create handle");
2635       CHECK2(ndb_mgm_set_connectstring(h, mgm) == 0, ndb_mgm_get_latest_error_msg(h));
2636       CHECK2(ndb_mgm_connect(h, 0, 0, 0) == 0, ndb_mgm_get_latest_error_msg(h));
2637       g_info << "mgm: connected to " << (mgm ? mgm : "default") << endl;
2638 
2639       // make bitmask of DB nodes
2640       dbmask.clear();
2641       ndb_mgm_cluster_state* cs = 0;
2642       CHECK2((cs = ndb_mgm_get_status(h)) != 0, ndb_mgm_get_latest_error_msg(h));
2643       for (int j = 0; j < cs->no_of_nodes; j++)
2644       {
2645         ndb_mgm_node_state* ns = &cs->node_states[j];
2646         if (ns->node_type == NDB_MGM_NODE_TYPE_NDB)
2647         {
2648           CHECK2(ns->node_status == NDB_MGM_NODE_STATUS_STARTED, "node " << ns->node_id << " not started status " << ns->node_status);
2649           CHECK2(!dbmask.get(ns->node_id), "duplicate node id " << ns->node_id);
2650           dbmask.set(ns->node_id);
2651           g_info << "added DB node " << ns->node_id << endl;
2652         }
2653       }
2654       free(cs);
2655       CHECK2(result == NDBT_OK, "some DB nodes are not started");
2656       CHECK2(!dbmask.isclear(), "found no DB nodes");
2657     }
2658 
2659     // data memory pages after following events
2660     // 0-initial 1,2-create table,index 3-load 4-delete 5,6-drop index,table
2661     int pages[7];
2662 
2663     // initial
2664     CHECK2(get_data_memory_pages(h, dbmask, &pages[0]) == NDBT_OK, "failed");
2665     g_info << "initial pages " << pages[0] << endl;
2666 
2667     // create table
2668     g_info << "create table " << tabname << endl;
2669     const NdbDictionary::Table* pTab = 0;
2670     CHECK2(pDic->createTable(tab) == 0, pDic->getNdbError());
2671     CHECK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
2672     CHECK2(get_data_memory_pages(h, dbmask, &pages[1]) == NDBT_OK, "failed");
2673     g_info << "create table pages " << pages[1] << endl;
2674 
2675     // choice of index attributes is not relevant to this bug
2676     // choose one non-PK updateable column
2677     NdbDictionary::Index ind;
2678     ind.setName(indname);
2679     ind.setTable(tabname);
2680     ind.setType(NdbDictionary::Index::OrderedIndex);
2681     ind.setLogging(false);
2682     {
2683       HugoCalculator calc(*pTab);
2684       for (int j = 0; j < pTab->getNoOfColumns(); j++)
2685       {
2686         const NdbDictionary::Column* col = pTab->getColumn(j);
2687         if (col->getPrimaryKey() || calc.isUpdateCol(j))
2688           continue;
2689         //CHARSET_INFO* cs = col->getCharset();
2690         if (NdbSqlUtil::check_column_for_ordered_index(col->getType(), col->getCharset()) == 0)
2691         {
2692           ind.addColumn(*col);
2693           break;
2694         }
2695       }
2696     }
2697     CHECK2(ind.getNoOfColumns() == 1, "cannot use table " << tabname);
2698 
2699     // create index
2700     g_info << "create index " << indname << " on " << ind.getColumn(0)->getName() << endl;
2701     const NdbDictionary::Index* pInd = 0;
2702     CHECK2(pDic->createIndex(ind, *pTab) == 0, pDic->getNdbError());
2703     CHECK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
2704     CHECK2(get_data_memory_pages(h, dbmask, &pages[2]) == NDBT_OK, "failed");
2705     g_info << "create index pages " << pages[2] << endl;
2706 
2707     HugoTransactions trans(*pTab);
2708 
2709     // load all records
2710     g_info << "load records" << endl;
2711     CHECK2(trans.loadTable(pNdb, rows) == 0, trans.getNdbError());
2712     memset(rowmask, 1, rows);
2713     CHECK2(get_data_memory_pages(h, dbmask, &pages[3]) == NDBT_OK, "failed");
2714     g_info << "load records pages " << pages[3] << endl;
2715 
2716     // test index with random ops
2717     g_info << "test index ops" << endl;
2718     {
2719       HugoOperations ops(*pTab);
2720       for (int i = 0; i < rows; i++)
2721       {
2722         CHECK2(ops.startTransaction(pNdb) == 0, ops.getNdbError());
2723         for (int j = 0; j < 32; j++)
2724         {
2725           int n = rand() % rows;
2726           if (!rowmask[n])
2727           {
2728             CHECK2(ops.pkInsertRecord(pNdb, n) == 0, ops.getNdbError());
2729             rowmask[n] = 1;
2730           }
2731           else if (rand() % 2 == 0)
2732           {
2733             CHECK2(ops.pkDeleteRecord(pNdb, n) == 0, ops.getNdbError());
2734             rowmask[n] = 0;
2735           }
2736           else
2737           {
2738             CHECK2(ops.pkUpdateRecord(pNdb, n) == 0, ops.getNdbError());
2739           }
2740         }
2741         CHECK2(result == NDBT_OK, "index ops batch failed");
2742         CHECK2(ops.execute_Commit(pNdb) == 0, ops.getNdbError());
2743         ops.closeTransaction(pNdb);
2744       }
2745       CHECK2(result == NDBT_OK, "index ops failed");
2746     }
2747 
2748     // delete all records
2749     g_info << "delete records" << endl;
2750     CHECK2(trans.clearTable(pNdb) == 0, trans.getNdbError());
2751     memset(rowmask, 0, rows);
2752     CHECK2(get_data_memory_pages(h, dbmask, &pages[4]) == NDBT_OK, "failed");
2753     g_info << "delete records pages " << pages[4] << endl;
2754 
2755     // drop index
2756     g_info << "drop index" <<  endl;
2757     CHECK2(pDic->dropIndex(indname, tabname) == 0, pDic->getNdbError());
2758     CHECK2(get_data_memory_pages(h, dbmask, &pages[5]) == NDBT_OK, "failed");
2759     g_info << "drop index pages " << pages[5] << endl;
2760 
2761     // drop table
2762     g_info << "drop table" << endl;
2763     CHECK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
2764     CHECK2(get_data_memory_pages(h, dbmask, &pages[6]) == NDBT_OK, "failed");
2765     g_info << "drop table pages " << pages[6] << endl;
2766 
2767     // verify
2768     CHECK2(pages[1] == pages[0], "pages after create table " << pages[1]
2769                                   << " not == initial pages " << pages[0]);
2770     CHECK2(pages[2] == pages[0], "pages after create index " << pages[2]
2771                                   << " not == initial pages " << pages[0]);
2772     CHECK2(pages[3] >  pages[0], "pages after load " << pages[3]
2773                                   << " not >  initial pages " << pages[0]);
2774     CHECK2(pages[4] == pages[0], "pages after delete " << pages[4]
2775                                   << " not == initial pages " << pages[0]);
2776     CHECK2(pages[5] == pages[0], "pages after drop index " << pages[5]
2777                                   << " not == initial pages " << pages[0]);
2778     CHECK2(pages[6] == pages[0], "pages after drop table " << pages[6]
2779                                   << " not == initial pages " << pages[0]);
2780 
2781     loop++;
2782 
2783     // at last loop disconnect from mgm
2784     if (loop == loops)
2785     {
2786       CHECK2(ndb_mgm_disconnect(h) == 0, ndb_mgm_get_latest_error_msg(h));
2787       ndb_mgm_destroy_handle(&h);
2788       g_info << "mgm: disconnected" << endl;
2789     }
2790   }
2791   delete [] rowmask;
2792 
2793   return result;
2794 }
2795 
2796 #define CHK_RET_FAILED(x) if (!(x)) { ndbout_c("Failed on line: %u", __LINE__); return NDBT_FAILED; }
2797 
2798 int
runBug12315582(NDBT_Context * ctx,NDBT_Step * step)2799 runBug12315582(NDBT_Context* ctx, NDBT_Step* step)
2800 {
2801   const NdbDictionary::Table * pTab = ctx->getTab();
2802   Ndb* pNdb = GETNDB(step);
2803   NdbDictionary::Dictionary * dict = pNdb->getDictionary();
2804 
2805   const NdbDictionary::Index* pIdx= dict->getIndex(pkIdxName, pTab->getName());
2806   CHK_RET_FAILED(pIdx != 0);
2807 
2808   const NdbRecord * pRowRecord = pTab->getDefaultRecord();
2809   CHK_RET_FAILED(pRowRecord != 0);
2810   const NdbRecord * pIdxRecord = pIdx->getDefaultRecord();
2811   CHK_RET_FAILED(pIdxRecord != 0);
2812 
2813   const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
2814   Uint8 * pRow = new Uint8[len];
2815   bzero(pRow, len);
2816 
2817   HugoCalculator calc(* pTab);
2818   calc.equalForRow(pRow, pRowRecord, 0);
2819 
2820   NdbTransaction* pTrans = pNdb->startTransaction();
2821   CHK_RET_FAILED(pTrans != 0);
2822 
2823   const NdbOperation * pOp[2] = { 0, 0 };
2824   for (Uint32 i = 0; i<2; i++)
2825   {
2826     NdbInterpretedCode code;
2827     if (i == 0)
2828       code.interpret_exit_ok();
2829     else
2830       code.interpret_exit_nok();
2831 
2832     code.finalise();
2833 
2834     NdbOperation::OperationOptions opts;
2835     bzero(&opts, sizeof(opts));
2836     opts.optionsPresent = NdbOperation::OperationOptions::OO_INTERPRETED;
2837     opts.interpretedCode = &code;
2838 
2839     pOp[i] = pTrans->readTuple(pIdxRecord, (char*)pRow,
2840                                pRowRecord, (char*)pRow,
2841                                NdbOperation::LM_Read,
2842                                0,
2843                                &opts,
2844                                sizeof(opts));
2845     CHK_RET_FAILED(pOp[i]);
2846   }
2847 
2848   int res = pTrans->execute(Commit, AO_IgnoreError);
2849 
2850   CHK_RET_FAILED(res == 0);
2851   CHK_RET_FAILED(pOp[0]->getNdbError().code == 0);
2852   CHK_RET_FAILED(pOp[1]->getNdbError().code != 0);
2853 
2854   delete [] pRow;
2855 
2856   return NDBT_OK;
2857 }
2858 
2859 int
runBug60851(NDBT_Context * ctx,NDBT_Step * step)2860 runBug60851(NDBT_Context* ctx, NDBT_Step* step)
2861 {
2862   const NdbDictionary::Table * pTab = ctx->getTab();
2863   Ndb* pNdb = GETNDB(step);
2864   NdbDictionary::Dictionary * dict = pNdb->getDictionary();
2865 
2866   const NdbDictionary::Index* pIdx= dict->getIndex(pkIdxName, pTab->getName());
2867   CHK_RET_FAILED(pIdx != 0);
2868 
2869   const NdbRecord * pRowRecord = pTab->getDefaultRecord();
2870   CHK_RET_FAILED(pRowRecord != 0);
2871   const NdbRecord * pIdxRecord = pIdx->getDefaultRecord();
2872   CHK_RET_FAILED(pIdxRecord != 0);
2873 
2874   const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
2875   Uint8 * pRow = new Uint8[len];
2876 
2877   NdbTransaction* pTrans = pNdb->startTransaction();
2878   CHK_RET_FAILED(pTrans != 0);
2879 
2880   const NdbOperation * pOp[3] = { 0, 0, 0};
2881   for (Uint32 i = 0; i<3; i++)
2882   {
2883     NdbInterpretedCode code;
2884     if (i == 1)
2885       code.interpret_exit_nok();
2886     else
2887       code.interpret_exit_ok();
2888 
2889     code.finalise();
2890 
2891     bzero(pRow, len);
2892     HugoCalculator calc(* pTab);
2893     calc.equalForRow(pRow, pRowRecord, i);
2894 
2895     NdbOperation::OperationOptions opts;
2896     bzero(&opts, sizeof(opts));
2897     opts.optionsPresent = NdbOperation::OperationOptions::OO_INTERPRETED;
2898     opts.interpretedCode = &code;
2899 
2900     pOp[i] = pTrans->deleteTuple(pIdxRecord, (char*)pRow,
2901                                  pRowRecord, (char*)pRow,
2902                                  0,
2903                                  &opts,
2904                                  sizeof(opts));
2905     CHK_RET_FAILED(pOp[i]);
2906   }
2907 
2908   int res = pTrans->execute(Commit, AO_IgnoreError);
2909 
2910   CHK_RET_FAILED(res == 0);
2911   CHK_RET_FAILED(pOp[0]->getNdbError().code == 0);
2912   CHK_RET_FAILED(pOp[1]->getNdbError().code != 0);
2913   CHK_RET_FAILED(pOp[2]->getNdbError().code == 0);
2914 
2915   delete [] pRow;
2916 
2917   return NDBT_OK;
2918 }
2919 
2920 static
2921 const int
2922 deferred_errors[] = {
2923   5064, 0,
2924   5065, 0,
2925   5066, 0,
2926   5067, 0,
2927   5068, 0,
2928   5069, 0,
2929   5070, 0,
2930   5071, 0,
2931   5072, 1,
2932   8090, 0,
2933   8091, 0,
2934   8092, 2, // connected tc
2935   0, 0 // trailer
2936 };
2937 
2938 int
runTestDeferredError(NDBT_Context * ctx,NDBT_Step * step)2939 runTestDeferredError(NDBT_Context* ctx, NDBT_Step* step)
2940 {
2941   NdbRestarter res;
2942   Ndb* pNdb = GETNDB(step);
2943   const NdbDictionary::Table* pTab = ctx->getTab();
2944 
2945   const int rows = ctx->getNumRecords();
2946 
2947   const NdbRecord * pRowRecord = pTab->getDefaultRecord();
2948   CHK_RET_FAILED(pRowRecord != 0);
2949 
2950   const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
2951   Uint8 * pRow = new Uint8[len];
2952 
2953   for (int i = 0; deferred_errors[i] != 0; i += 2)
2954   {
2955     const int errorno = deferred_errors[i];
2956     const int nodefail = deferred_errors[i+1];
2957 
2958     for (int j = 0; j<3; j++)
2959     {
2960       NdbTransaction* pTrans = pNdb->startTransaction();
2961       CHK_RET_FAILED(pTrans != 0);
2962 
2963       int nodeId =
2964         nodefail == 0 ? 0 :
2965         nodefail == 1 ? res.getNode(NdbRestarter::NS_RANDOM) :
2966         nodefail == 2 ? pTrans->getConnectedNodeId() :
2967         0;
2968 
2969       ndbout_c("errorno: %u(nf: %u - %u) j: %u : %s", errorno,
2970                nodefail, nodeId, j,
2971                j == 0 ? "test before error insert" :
2972                j == 1 ? "test with error insert" :
2973                j == 2 ? "test after error insert" :
2974                "");
2975       if (j == 0 || j == 2)
2976       {
2977         // First time succeed
2978         // Last time succeed
2979       }
2980       else if (nodefail == 0)
2981       {
2982         CHK_RET_FAILED(res.insertErrorInAllNodes(errorno) == 0);
2983       }
2984       else
2985       {
2986         int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
2987         CHK_RET_FAILED(res.dumpStateOneNode(nodeId, val2, 2) == 0);
2988         CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
2989       }
2990 
2991       for (int rowNo = 0; rowNo < 100; rowNo++)
2992       {
2993         int rowId = rand() % rows;
2994         bzero(pRow, len);
2995 
2996         HugoCalculator calc(* pTab);
2997         calc.setValues(pRow, pRowRecord, rowId, rand());
2998 
2999         NdbOperation::OperationOptions opts;
3000         bzero(&opts, sizeof(opts));
3001         opts.optionsPresent =
3002           NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS;
3003 
3004         const NdbOperation * pOp = pTrans->updateTuple(pRowRecord, (char*)pRow,
3005                                                        pRowRecord, (char*)pRow,
3006                                                        0,
3007                                                        &opts,
3008                                                        sizeof(opts));
3009         CHK_RET_FAILED(pOp != 0);
3010       }
3011 
3012       int result = pTrans->execute(Commit, AO_IgnoreError);
3013       if (j == 0 || j == 2)
3014       {
3015         CHK_RET_FAILED(result == 0);
3016       }
3017       else
3018       {
3019         CHK_RET_FAILED(result != 0);
3020       }
3021       pTrans->close();
3022 
3023 
3024       if (j == 0 || j == 2)
3025       {
3026       }
3027       else
3028       {
3029         if (nodefail)
3030         {
3031           ndbout_c("  waiting for %u to enter not-started", nodeId);
3032           // Wait for a node to enter not-started
3033           CHK_RET_FAILED(res.waitNodesNoStart(&nodeId, 1) == 0);
3034 
3035           ndbout_c("  starting all");
3036           CHK_RET_FAILED(res.startAll() == 0);
3037           ndbout_c("  wait cluster started");
3038           CHK_RET_FAILED(res.waitClusterStarted() == 0);
3039           ndbout_c("  cluster started");
3040         }
3041         CHK_RET_FAILED(res.insertErrorInAllNodes(0) == 0);
3042       }
3043     }
3044   }
3045 
3046   delete [] pRow;
3047 
3048   return NDBT_OK;
3049 }
3050 
3051 int
runMixedDML(NDBT_Context * ctx,NDBT_Step * step)3052 runMixedDML(NDBT_Context* ctx, NDBT_Step* step)
3053 {
3054   Ndb* pNdb = GETNDB(step);
3055   const NdbDictionary::Table* pTab = ctx->getTab();
3056 
3057   unsigned seed = (unsigned)NdbTick_CurrentMillisecond();
3058 
3059   const int rows = ctx->getNumRecords();
3060   const int loops = 10 * ctx->getNumLoops();
3061   const int until_stopped = ctx->getProperty("UntilStopped");
3062   const int deferred = ctx->getProperty("Deferred");
3063   const int batch = ctx->getProperty("Batch", Uint32(50));
3064 
3065   const NdbRecord * pRowRecord = pTab->getDefaultRecord();
3066   CHK_RET_FAILED(pRowRecord != 0);
3067 
3068   const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
3069   Uint8 * pRow = new Uint8[len];
3070 
3071   int count_ok = 0;
3072   int count_failed = 0;
3073   for (int i = 0; i < loops || (until_stopped && !ctx->isTestStopped()); i++)
3074   {
3075     NdbTransaction* pTrans = pNdb->startTransaction();
3076     CHK_RET_FAILED(pTrans != 0);
3077 
3078     int lastrow = 0;
3079     int result = 0;
3080     for (int rowNo = 0; rowNo < batch; rowNo++)
3081     {
3082       int left = rows - lastrow;
3083       int rowId = lastrow;
3084       if (left)
3085       {
3086         rowId += ndb_rand_r(&seed) % (left / 10 + 1);
3087       }
3088       else
3089       {
3090         break;
3091       }
3092       lastrow = rowId;
3093 
3094       bzero(pRow, len);
3095 
3096       HugoCalculator calc(* pTab);
3097       calc.setValues(pRow, pRowRecord, rowId, rand());
3098 
3099       NdbOperation::OperationOptions opts;
3100       bzero(&opts, sizeof(opts));
3101       if (deferred)
3102       {
3103         opts.optionsPresent =
3104           NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS;
3105       }
3106 
3107       const NdbOperation* pOp = 0;
3108       switch(ndb_rand_r(&seed) % 3){
3109       case 0:
3110         pOp = pTrans->writeTuple(pRowRecord, (char*)pRow,
3111                                  pRowRecord, (char*)pRow,
3112                                  0,
3113                                  &opts,
3114                                  sizeof(opts));
3115         break;
3116       case 1:
3117         pOp = pTrans->deleteTuple(pRowRecord, (char*)pRow,
3118                                   pRowRecord, (char*)pRow,
3119                                   0,
3120                                   &opts,
3121                                   sizeof(opts));
3122         break;
3123       case 2:
3124         pOp = pTrans->updateTuple(pRowRecord, (char*)pRow,
3125                                   pRowRecord, (char*)pRow,
3126                                   0,
3127                                   &opts,
3128                                   sizeof(opts));
3129         break;
3130       }
3131       CHK_RET_FAILED(pOp != 0);
3132       result = pTrans->execute(NoCommit, AO_IgnoreError);
3133       if (result != 0)
3134       {
3135         goto found_error;
3136       }
3137     }
3138 
3139     result = pTrans->execute(Commit, AO_IgnoreError);
3140     if (result != 0)
3141     {
3142   found_error:
3143       count_failed++;
3144       NdbError err = pTrans->getNdbError();
3145       ndbout << err << endl;
3146       CHK_RET_FAILED(err.code == 1235 ||
3147                      err.code == 1236 ||
3148                      err.code == 5066 ||
3149                      err.status == NdbError::TemporaryError ||
3150                      err.classification == NdbError::NoDataFound ||
3151                      err.classification == NdbError::ConstraintViolation);
3152     }
3153     else
3154     {
3155       count_ok++;
3156     }
3157     pTrans->close();
3158   }
3159 
3160   ndbout_c("count_ok: %d count_failed: %d",
3161            count_ok, count_failed);
3162   delete [] pRow;
3163 
3164   return NDBT_OK;
3165 }
3166 
3167 int
runDeferredError(NDBT_Context * ctx,NDBT_Step * step)3168 runDeferredError(NDBT_Context* ctx, NDBT_Step* step)
3169 {
3170   NdbRestarter res;
3171 
3172   for (int l = 0; l<ctx->getNumLoops() && !ctx->isTestStopped(); l++)
3173   {
3174     for (int i = 0; deferred_errors[i] != 0 && !ctx->isTestStopped(); i += 2)
3175     {
3176       const int errorno = deferred_errors[i];
3177       const int nodefail = deferred_errors[i+1];
3178 
3179       int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
3180 
3181       ndbout_c("errorno: %u (nf: %u - %u)",
3182                errorno,
3183                nodefail, nodeId);
3184 
3185       if (nodefail == 0)
3186       {
3187         CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
3188         NdbSleep_MilliSleep(300);
3189         CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
3190       }
3191       else
3192       {
3193         int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
3194         CHK_RET_FAILED(res.dumpStateOneNode(nodeId, val2, 2) == 0);
3195         CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
3196         ndbout_c("  waiting for %u to enter not-started", nodeId);
3197         // Wait for a node to enter not-started
3198         CHK_RET_FAILED(res.waitNodesNoStart(&nodeId, 1) == 0);
3199 
3200         ndbout_c("  starting all");
3201         CHK_RET_FAILED(res.startAll() == 0);
3202         ndbout_c("  wait cluster started");
3203         CHK_RET_FAILED(res.waitClusterStarted() == 0);
3204         ndbout_c("  cluster started");
3205       }
3206     }
3207   }
3208 
3209   ctx->stopTest();
3210   return NDBT_OK;
3211 }
3212 
3213 NDBT_TESTSUITE(testIndex);
3214 TESTCASE("CreateAll",
3215 	 "Test that we can create all various indexes on each table\n"
3216 	 "Then drop the indexes\n"){
3217   INITIALIZER(runCreateIndexes);
3218 }
3219 TESTCASE("CreateAll_O",
3220 	 "Test that we can create all various indexes on each table\n"
3221 	 "Then drop the indexes\n"){
3222   TC_PROPERTY("OrderedIndex", 1);
3223   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3224   INITIALIZER(runCreateIndexes);
3225 }
3226 TESTCASE("InsertDeleteGentle",
3227 	 "Create one index, then perform insert and delete in the table\n"
3228 	 "loop number of times. Use batch size 1."){
3229   TC_PROPERTY("BatchSize", 1);
3230   INITIALIZER(runInsertDelete);
3231   FINALIZER(runClearTable);
3232 }
3233 TESTCASE("InsertDeleteGentle_O",
3234 	 "Create one index, then perform insert and delete in the table\n"
3235 	 "loop number of times. Use batch size 1."){
3236   TC_PROPERTY("OrderedIndex", 1);
3237   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3238   TC_PROPERTY("BatchSize", 1);
3239   INITIALIZER(runInsertDelete);
3240   FINALIZER(runClearTable);
3241 }
3242 TESTCASE("InsertDelete",
3243 	 "Create one index, then perform insert and delete in the table\n"
3244 	 "loop number of times. Use batchsize 512 to stress db more"){
3245   TC_PROPERTY("BatchSize", 512);
3246   INITIALIZER(runInsertDelete);
3247   FINALIZER(runClearTable);
3248 
3249 }
3250 TESTCASE("InsertDelete_O",
3251 	 "Create one index, then perform insert and delete in the table\n"
3252 	 "loop number of times. Use batchsize 512 to stress db more"){
3253   TC_PROPERTY("OrderedIndex", 1);
3254   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3255   TC_PROPERTY("BatchSize", 512);
3256   INITIALIZER(runInsertDelete);
3257   FINALIZER(runClearTable);
3258 
3259 }
3260 TESTCASE("CreateLoadDropGentle",
3261 	 "Try to create, drop and load various indexes \n"
3262 	 "on table loop number of times.Usa batch size 1.\n"){
3263   TC_PROPERTY("BatchSize", 1);
3264   INITIALIZER(runCreateLoadDropIndex);
3265 }
3266 TESTCASE("CreateLoadDropGentle_O",
3267 	 "Try to create, drop and load various indexes \n"
3268 	 "on table loop number of times.Usa batch size 1.\n"){
3269   TC_PROPERTY("OrderedIndex", 1);
3270   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3271   TC_PROPERTY("BatchSize", 1);
3272   INITIALIZER(runCreateLoadDropIndex);
3273 }
3274 TESTCASE("CreateLoadDrop",
3275 	 "Try to create, drop and load various indexes \n"
3276 	 "on table loop number of times. Use batchsize 512 to stress db more\n"){
3277   TC_PROPERTY("BatchSize", 512);
3278   INITIALIZER(runCreateLoadDropIndex);
3279 }
3280 TESTCASE("CreateLoadDrop_O",
3281 	 "Try to create, drop and load various indexes \n"
3282 	 "on table loop number of times. Use batchsize 512 to stress db more\n"){
3283   TC_PROPERTY("OrderedIndex", 1);
3284   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3285   TC_PROPERTY("BatchSize", 512);
3286   INITIALIZER(runCreateLoadDropIndex);
3287 }
3288 TESTCASE("NFNR1",
3289 	 "Test that indexes are correctly maintained during node fail and node restart"){
3290   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3291   TC_PROPERTY("PauseThreads", 2);
3292   INITIALIZER(runClearTable);
3293   INITIALIZER(createRandomIndex);
3294   INITIALIZER(runLoadTable);
3295   STEP(runRestarts);
3296   STEP(runTransactions1);
3297   STEP(runTransactions1);
3298   FINALIZER(runVerifyIndex);
3299   FINALIZER(createRandomIndex_Drop);
3300   FINALIZER(runClearTable);
3301 }
3302 TESTCASE("NFNR1_O",
3303 	 "Test that indexes are correctly maintained during node fail and node restart"){
3304   TC_PROPERTY("OrderedIndex", 1);
3305   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3306   TC_PROPERTY("PauseThreads", 2);
3307   INITIALIZER(runClearTable);
3308   INITIALIZER(createRandomIndex);
3309   INITIALIZER(runLoadTable);
3310   STEP(runRestarts);
3311   STEP(runTransactions1);
3312   STEP(runTransactions1);
3313   FINALIZER(runVerifyIndex);
3314   FINALIZER(createRandomIndex_Drop);
3315   FINALIZER(runClearTable);
3316 }
3317 TESTCASE("NFNR2",
3318 	 "Test that indexes are correctly maintained during node fail and node restart"){
3319   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3320   TC_PROPERTY("PauseThreads", 2);
3321   INITIALIZER(runClearTable);
3322   INITIALIZER(createRandomIndex);
3323   INITIALIZER(createPkIndex);
3324   INITIALIZER(runLoadTable);
3325   STEP(runRestarts);
3326   STEP(runTransactions2);
3327   STEP(runTransactions2);
3328   FINALIZER(runVerifyIndex);
3329   FINALIZER(createRandomIndex_Drop);
3330   FINALIZER(createPkIndex_Drop);
3331   FINALIZER(runClearTable);
3332 }
3333 TESTCASE("NFNR2_O",
3334 	 "Test that indexes are correctly maintained during node fail and node restart"){
3335   TC_PROPERTY("OrderedIndex", 1);
3336   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3337   TC_PROPERTY("PauseThreads", 1);
3338   INITIALIZER(runClearTable);
3339   INITIALIZER(createRandomIndex);
3340   INITIALIZER(createPkIndex);
3341   INITIALIZER(runLoadTable);
3342   STEP(runRestarts);
3343   STEP(runTransactions2);
3344   //STEP(runTransactions2);
3345   FINALIZER(runVerifyIndex);
3346   FINALIZER(createRandomIndex_Drop);
3347   FINALIZER(createPkIndex_Drop);
3348   FINALIZER(runClearTable);
3349 }
3350 TESTCASE("NFNR3",
3351 	 "Test that indexes are correctly maintained during node fail and node restart"){
3352   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3353   TC_PROPERTY("PauseThreads", 2);
3354   INITIALIZER(runClearTable);
3355   INITIALIZER(createRandomIndex);
3356   INITIALIZER(createPkIndex);
3357   STEP(runRestarts);
3358   STEP(runTransactions3);
3359   STEP(runVerifyIndex);
3360   FINALIZER(runVerifyIndex);
3361   FINALIZER(createPkIndex_Drop);
3362   FINALIZER(createRandomIndex_Drop);
3363   FINALIZER(runClearTable);
3364 }
3365 TESTCASE("NFNR3_O",
3366 	 "Test that indexes are correctly maintained during node fail and node restart"){
3367   TC_PROPERTY("OrderedIndex", 1);
3368   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3369   TC_PROPERTY("PauseThreads", 2);
3370   INITIALIZER(runClearTable);
3371   INITIALIZER(createRandomIndex);
3372   INITIALIZER(createPkIndex);
3373   STEP(runRestarts);
3374   STEP(runTransactions3);
3375   STEP(runVerifyIndex);
3376   FINALIZER(runVerifyIndex);
3377   FINALIZER(createPkIndex_Drop);
3378   FINALIZER(createRandomIndex_Drop);
3379   FINALIZER(runClearTable);
3380 }
3381 TESTCASE("NFNR4",
3382 	 "Test that indexes are correctly maintained during node fail and node restart"){
3383   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3384   TC_PROPERTY("PauseThreads", 4);
3385   INITIALIZER(runClearTable);
3386   INITIALIZER(createRandomIndex);
3387   INITIALIZER(createPkIndex);
3388   INITIALIZER(runLoadTable);
3389   STEP(runRestarts);
3390   STEP(runTransactions1);
3391   STEP(runTransactions1);
3392   STEP(runTransactions2);
3393   STEP(runTransactions2);
3394   FINALIZER(runVerifyIndex);
3395   FINALIZER(createRandomIndex_Drop);
3396   FINALIZER(createPkIndex_Drop);
3397   FINALIZER(runClearTable);
3398 }
3399 TESTCASE("NFNR4_O",
3400 	 "Test that indexes are correctly maintained during node fail and node restart"){
3401   TC_PROPERTY("OrderedIndex", 1);
3402   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3403   TC_PROPERTY("PauseThreads", 4);
3404   INITIALIZER(runClearTable);
3405   INITIALIZER(createRandomIndex);
3406   INITIALIZER(createPkIndex);
3407   INITIALIZER(runLoadTable);
3408   STEP(runRestarts);
3409   STEP(runTransactions1);
3410   STEP(runTransactions1);
3411   STEP(runTransactions2);
3412   STEP(runTransactions2);
3413   FINALIZER(runVerifyIndex);
3414   FINALIZER(createRandomIndex_Drop);
3415   FINALIZER(createPkIndex_Drop);
3416   FINALIZER(runClearTable);
3417 }
3418 TESTCASE("NFNR5",
3419 	 "Test that indexes are correctly maintained during node fail and node restart"){
3420   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3421   TC_PROPERTY("BatchSize", (unsigned)1);
3422   INITIALIZER(runClearTable);
3423   INITIALIZER(createRandomIndex);
3424   INITIALIZER(createPkIndex);
3425   INITIALIZER(runLoadTable);
3426   STEP(runLQHKEYREF);
3427   STEP(runTransactions1);
3428   STEP(runTransactions1);
3429   STEP(runTransactions2);
3430   STEP(runTransactions2);
3431   FINALIZER(runVerifyIndex);
3432   FINALIZER(createRandomIndex_Drop);
3433   FINALIZER(createPkIndex_Drop);
3434   FINALIZER(runClearTable);
3435 }
3436 TESTCASE("NFNR5_O",
3437 	 "Test that indexes are correctly maintained during node fail and node restart"){
3438   TC_PROPERTY("OrderedIndex", 1);
3439   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3440   TC_PROPERTY("BatchSize", (unsigned)1);
3441   INITIALIZER(runClearTable);
3442   INITIALIZER(createRandomIndex);
3443   INITIALIZER(createPkIndex);
3444   INITIALIZER(runLoadTable);
3445   STEP(runLQHKEYREF);
3446   STEP(runTransactions1);
3447   STEP(runTransactions1);
3448   STEP(runTransactions2);
3449   STEP(runTransactions2);
3450   FINALIZER(runVerifyIndex);
3451   FINALIZER(createRandomIndex_Drop);
3452   FINALIZER(createPkIndex_Drop);
3453   FINALIZER(runClearTable);
3454 }
3455 TESTCASE("SR1",
3456 	 "Test that indexes are correctly maintained during SR"){
3457   INITIALIZER(runClearTable);
3458   INITIALIZER(createRandomIndex);
3459   INITIALIZER(createPkIndex);
3460   STEP(runSystemRestart1);
3461   FINALIZER(runVerifyIndex);
3462   FINALIZER(createPkIndex_Drop);
3463   FINALIZER(createRandomIndex_Drop);
3464   FINALIZER(runClearTable);
3465 }
3466 TESTCASE("MixedTransaction",
3467 	 "Test mixing of index and normal operations"){
3468   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3469   INITIALIZER(runClearTable);
3470   INITIALIZER(createPkIndex);
3471   INITIALIZER(runLoadTable);
3472   STEP(runMixed1);
3473   FINALIZER(createPkIndex_Drop);
3474   FINALIZER(runClearTable);
3475 }
3476 TESTCASE("MixedTransaction2",
3477 	 "Test mixing of index and normal operations with batching"){
3478   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3479   INITIALIZER(runClearTable);
3480   INITIALIZER(createPkIndex);
3481   INITIALIZER(runLoadTable);
3482   STEP(runMixed2);
3483   FINALIZER(createPkIndex_Drop);
3484   FINALIZER(runClearTable);
3485 }
3486 TESTCASE("SR1_O",
3487 	 "Test that indexes are correctly maintained during SR"){
3488   TC_PROPERTY("OrderedIndex", 1);
3489   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3490   INITIALIZER(runClearTable);
3491   INITIALIZER(createRandomIndex);
3492   INITIALIZER(createPkIndex);
3493   STEP(runSystemRestart1);
3494   FINALIZER(runVerifyIndex);
3495   FINALIZER(createPkIndex_Drop);
3496   FINALIZER(createRandomIndex_Drop);
3497   FINALIZER(runClearTable);
3498 }
3499 TESTCASE("BuildDuring",
3500 	 "Test that index build when running transactions work"){
3501   TC_PROPERTY("OrderedIndex", (unsigned)0);
3502   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3503   TC_PROPERTY("Threads", 1); // # runTransactions4
3504   TC_PROPERTY("BatchSize", 1);
3505   INITIALIZER(runClearTable);
3506   STEP(runBuildDuring);
3507   STEP(runTransactions4);
3508   //STEP(runTransactions4);
3509   FINALIZER(runClearTable);
3510 }
3511 TESTCASE("BuildDuring_O",
3512 	 "Test that index build when running transactions work"){
3513   TC_PROPERTY("OrderedIndex", (unsigned)1);
3514   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3515   TC_PROPERTY("Threads", 1); // # runTransactions4
3516   INITIALIZER(runClearTable);
3517   STEP(runBuildDuring);
3518   STEP(runTransactions4);
3519   //STEP(runTransactions4);
3520   FINALIZER(runClearTable);
3521 }
3522 TESTCASE("UniqueNull",
3523 	 "Test that unique indexes and nulls"){
3524   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3525   INITIALIZER(runClearTable);
3526   INITIALIZER(createRandomIndex);
3527   INITIALIZER(createPkIndex);
3528   INITIALIZER(runLoadTable);
3529   STEP(runTransactions1);
3530   STEP(runTransactions2);
3531   STEP(runUniqueNullTransactions);
3532   FINALIZER(runVerifyIndex);
3533   FINALIZER(createRandomIndex_Drop);
3534   FINALIZER(createPkIndex_Drop);
3535   FINALIZER(runClearTable);
3536 }
3537 TESTCASE("Bug21384",
3538 	 "Test that unique indexes and nulls"){
3539   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3540   INITIALIZER(runClearTable);
3541   INITIALIZER(createPkIndex);
3542   INITIALIZER(runLoadTable);
3543   STEP(runBug21384);
3544   FINALIZER(createPkIndex_Drop);
3545   FINALIZER(runClearTable);
3546 }
3547 TESTCASE("Bug25059",
3548 	 "Test that unique indexes and nulls"){
3549   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3550   INITIALIZER(createPkIndex);
3551   INITIALIZER(runLoadTable);
3552   STEP(runBug25059);
3553   FINALIZER(createPkIndex_Drop);
3554 }
3555 TESTCASE("Bug28804",
3556 	 "Test behaviour on out of TransactionBufferMemory for index lookup"){
3557   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3558   INITIALIZER(runClearTable);
3559   INITIALIZER(createPkIndex);
3560   INITIALIZER(runLoadTable);
3561   STEP(runBug28804);
3562   FINALIZER(createPkIndex_Drop);
3563   FINALIZER(runClearTable);
3564 }
3565 TESTCASE("Bug28804_ATTRINFO",
3566 	 "Test behaviour on out of TransactionBufferMemory for index lookup"
3567          " in saveINDXATTRINFO"){
3568   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3569   INITIALIZER(runClearTable);
3570   INITIALIZER(createPkIndex);
3571   INITIALIZER(runLoadTable);
3572   STEP(runBug28804_ATTRINFO);
3573   FINALIZER(createPkIndex_Drop);
3574   FINALIZER(runClearTable);
3575 }
3576 TESTCASE("Bug46069", ""){
3577   TC_PROPERTY("OrderedIndex", 1);
3578   TC_PROPERTY("THREADS", 12);
3579   TC_PROPERTY("LoggedIndexes", Uint32(0));
3580   INITIALIZER(createPkIndex);
3581   STEP(runBug46069);
3582   STEPS(runBug46069_pkdel, 10);
3583   STEPS(runBug46069_scandel, 2);
3584   FINALIZER(createPkIndex_Drop);
3585 }
3586 TESTCASE("ConstraintDetails",
3587          "Test that the details part of the returned NdbError is as "
3588          "expected"){
3589   INITIALIZER(runConstraintDetails);
3590 }
3591 TESTCASE("Bug50118", ""){
3592   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3593   INITIALIZER(runClearTable);
3594   INITIALIZER(runLoadTable);
3595   INITIALIZER(createPkIndex);
3596   STEP(runReadIndexUntilStopped);
3597   STEP(runReadIndexUntilStopped);
3598   STEP(runReadIndexUntilStopped);
3599   STEP(runBug50118);
3600   FINALIZER(createPkIndex_Drop);
3601   FINALIZER(runClearTable);
3602 }
3603 TESTCASE("FireTrigOverload", ""){
3604   TC_PROPERTY("LoggedIndexes", (unsigned)0);
3605   TC_PROPERTY("NotOnlyPkId", (unsigned)1); // Index must be non PK to fire triggers
3606   TC_PROPERTY(NDBT_TestCase::getStepThreadStackSizePropName(), 128*1024);
3607   INITIALIZER(createRandomIndex);
3608   INITIALIZER(runClearTable);
3609   STEP(runTrigOverload);
3610   FINALIZER(runClearError);
3611   FINALIZER(createRandomIndex_Drop);
3612 }
3613 TESTCASE("DeferredError",
3614          "Test with deferred unique index handling and error inserts")
3615 {
3616   TC_PROPERTY("LoggedIndexes", Uint32(0));
3617   TC_PROPERTY("OrderedIndex", Uint32(0));
3618   INITIALIZER(createPkIndex);
3619   INITIALIZER(runLoadTable);
3620   STEP(runTestDeferredError);
3621   FINALIZER(createPkIndex_Drop);
3622 }
3623 TESTCASE("DeferredMixedLoad",
3624          "Test mixed load of DML with deferred indexes")
3625 {
3626   TC_PROPERTY("LoggedIndexes", Uint32(0));
3627   TC_PROPERTY("OrderedIndex", Uint32(0));
3628   TC_PROPERTY("UntilStopped", Uint32(0));
3629   TC_PROPERTY("Deferred", Uint32(1));
3630   INITIALIZER(createPkIndex);
3631   INITIALIZER(runLoadTable);
3632   STEPS(runMixedDML, 10);
3633   FINALIZER(createPkIndex_Drop);
3634 }
3635 TESTCASE("DeferredMixedLoadError",
3636          "Test mixed load of DML with deferred indexes")
3637 {
3638   TC_PROPERTY("LoggedIndexes", Uint32(0));
3639   TC_PROPERTY("OrderedIndex", Uint32(0));
3640   TC_PROPERTY("UntilStopped", Uint32(1));
3641   TC_PROPERTY("Deferred", Uint32(1));
3642   INITIALIZER(createPkIndex);
3643   INITIALIZER(runLoadTable);
3644   STEPS(runMixedDML, 4);
3645   STEP(runDeferredError);
3646   FINALIZER(createPkIndex_Drop);
3647 }
3648 TESTCASE("NF_DeferredMixed",
3649          "Test mixed load of DML with deferred indexes")
3650 {
3651   TC_PROPERTY("LoggedIndexes", Uint32(0));
3652   TC_PROPERTY("OrderedIndex", Uint32(0));
3653   TC_PROPERTY("UntilStopped", Uint32(1));
3654   TC_PROPERTY("Deferred", Uint32(1));
3655   INITIALIZER(createPkIndex);
3656   INITIALIZER(runLoadTable);
3657   STEPS(runMixedDML, 4);
3658   STEP(runRestarts);
3659   FINALIZER(createPkIndex_Drop);
3660 }
3661 TESTCASE("NF_Mixed",
3662          "Test mixed load of DML")
3663 {
3664   TC_PROPERTY("LoggedIndexes", Uint32(0));
3665   TC_PROPERTY("OrderedIndex", Uint32(0));
3666   TC_PROPERTY("UntilStopped", Uint32(1));
3667   INITIALIZER(createPkIndex);
3668   INITIALIZER(runLoadTable);
3669   STEPS(runMixedDML, 4);
3670   STEP(runRestarts);
3671   FINALIZER(createPkIndex_Drop);
3672 }
3673 TESTCASE("Bug56829",
3674          "Return empty ordered index nodes to index fragment "
3675          "so that empty fragment pages can be freed"){
3676   STEP(runBug56829);
3677 }
3678 TESTCASE("Bug12315582", "")
3679 {
3680   TC_PROPERTY("LoggedIndexes", Uint32(0));
3681   TC_PROPERTY("OrderedIndex", Uint32(0));
3682   INITIALIZER(createPkIndex);
3683   INITIALIZER(runLoadTable);
3684   INITIALIZER(runBug12315582);
3685   FINALIZER(createPkIndex_Drop);
3686 }
3687 TESTCASE("Bug60851", "")
3688 {
3689   TC_PROPERTY("LoggedIndexes", Uint32(0));
3690   TC_PROPERTY("OrderedIndex", Uint32(0));
3691   INITIALIZER(createPkIndex);
3692   INITIALIZER(runLoadTable);
3693   INITIALIZER(runBug60851);
3694   FINALIZER(createPkIndex_Drop);
3695 }
3696 TESTCASE("RefreshWithOrderedIndex",
3697          "Refresh tuples with ordered index(es)")
3698 {
3699   TC_PROPERTY("OrderedIndex", 1);
3700   TC_PROPERTY("LoggedIndexes", Uint32(0));
3701   INITIALIZER(createPkIndex);
3702   INITIALIZER(runRefreshTupleAbort);
3703   FINALIZER(createPkIndex_Drop);
3704   FINALIZER(runClearTable);
3705 }
3706 NDBT_TESTSUITE_END(testIndex);
3707 
main(int argc,const char ** argv)3708 int main(int argc, const char** argv){
3709   ndb_init();
3710   NDBT_TESTSUITE_INSTANCE(testIndex);
3711   return testIndex.execute(argc, argv);
3712 }
3713 
3714 template class Vector<Attrib*>;
3715