1 /*
2    Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <NDBT_Test.hpp>
26 #include <NDBT_ReturnCodes.h>
27 #include <HugoTransactions.hpp>
28 #include <UtilTransactions.hpp>
29 #include <NdbRestarter.hpp>
30 #include <signaldata/DictTabInfo.hpp>
31 #include <Bitmask.hpp>
32 #include <random.h>
33 #include <signaldata/DumpStateOrd.hpp>
34 
35 /**
36  * TODO
37  *  dirtyWrite, write, dirtyUpdate
38  *  delete should be visible to same transaction
39  *
40  */
runLoadTable2(NDBT_Context * ctx,NDBT_Step * step)41 int runLoadTable2(NDBT_Context* ctx, NDBT_Step* step)
42 {
43   int records = ctx->getNumRecords();
44   HugoTransactions hugoTrans(*ctx->getTab());
45   if (hugoTrans.loadTable(GETNDB(step), records, 512, false, 0, true) != 0){
46     return NDBT_FAILED;
47   }
48   return NDBT_OK;
49 }
50 
runLoadTable(NDBT_Context * ctx,NDBT_Step * step)51 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step)
52 {
53   int records = ctx->getNumRecords();
54   HugoTransactions hugoTrans(*ctx->getTab());
55   if (hugoTrans.loadTable(GETNDB(step), records) != 0){
56     return NDBT_FAILED;
57   }
58   return NDBT_OK;
59 }
60 
runInsert(NDBT_Context * ctx,NDBT_Step * step)61 int runInsert(NDBT_Context* ctx, NDBT_Step* step){
62 
63   int records = ctx->getNumRecords();
64   HugoTransactions hugoTrans(*ctx->getTab());
65   // Insert records, dont allow any
66   // errors(except temporary) while inserting
67   if (hugoTrans.loadTable(GETNDB(step), records, 1, false) != 0){
68     return NDBT_FAILED;
69   }
70   return NDBT_OK;
71 }
72 
runInsertTwice(NDBT_Context * ctx,NDBT_Step * step)73 int runInsertTwice(NDBT_Context* ctx, NDBT_Step* step){
74 
75   int records = ctx->getNumRecords();
76   HugoTransactions hugoTrans(*ctx->getTab());
77   // Insert records, expect primary key violation 630
78   if (hugoTrans.loadTable(GETNDB(step), records, 1, false) != 630){
79     return NDBT_FAILED;
80   }
81   return NDBT_OK;
82 }
83 
runVerifyInsert(NDBT_Context * ctx,NDBT_Step * step)84 int runVerifyInsert(NDBT_Context* ctx, NDBT_Step* step){
85   int records = ctx->getNumRecords();
86 
87   HugoTransactions hugoTrans(*ctx->getTab());
88   if (hugoTrans.pkDelRecords(GETNDB(step),  records, 1, false) != 0){
89     return NDBT_FAILED;
90   }
91   return NDBT_OK;
92 }
93 
runInsertUntilStopped(NDBT_Context * ctx,NDBT_Step * step)94 int runInsertUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
95   int records = ctx->getNumRecords();
96   int i = 0;
97   HugoTransactions hugoTrans(*ctx->getTab());
98   while (ctx->isTestStopped() == false) {
99     g_info << i << ": ";
100     if (hugoTrans.loadTable(GETNDB(step), records) != 0){
101       g_info << endl;
102       return NDBT_FAILED;
103     }
104     i++;
105   }
106   g_info << endl;
107   return NDBT_OK;
108 }
109 
runClearTable(NDBT_Context * ctx,NDBT_Step * step)110 int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
111   int records = ctx->getNumRecords();
112   int batchSize = ctx->getProperty("BatchSize", 1);
113 
114   HugoTransactions hugoTrans(*ctx->getTab());
115   if (hugoTrans.pkDelRecords(GETNDB(step),  records, batchSize) != 0){
116     return NDBT_FAILED;
117   }
118   return NDBT_OK;
119 }
120 
runPkDelete(NDBT_Context * ctx,NDBT_Step * step)121 int runPkDelete(NDBT_Context* ctx, NDBT_Step* step){
122   int loops = ctx->getNumLoops();
123   int records = ctx->getNumRecords();
124 
125   int i = 0;
126   HugoTransactions hugoTrans(*ctx->getTab());
127   while (i<loops) {
128     g_info << i << ": ";
129     if (hugoTrans.pkDelRecords(GETNDB(step),  records) != 0){
130       g_info << endl;
131       return NDBT_FAILED;
132     }
133     // Load table, don't allow any primary key violations
134     if (hugoTrans.loadTable(GETNDB(step), records, 512, false) != 0){
135       g_info << endl;
136       return NDBT_FAILED;
137     }
138     i++;
139   }
140   g_info << endl;
141   return NDBT_OK;
142 }
143 
144 
runPkRead(NDBT_Context * ctx,NDBT_Step * step)145 int runPkRead(NDBT_Context* ctx, NDBT_Step* step){
146   int loops = ctx->getNumLoops();
147   int records = ctx->getNumRecords();
148   int batchSize = ctx->getProperty("BatchSize", 1);
149   int lm = ctx->getProperty("LockMode", NdbOperation::LM_Read);
150   int i = 0;
151   HugoTransactions hugoTrans(*ctx->getTab());
152   while (i<loops) {
153     g_info << i << ": ";
154     if (hugoTrans.pkReadRecords(GETNDB(step), records, batchSize,
155                                 (NdbOperation::LockMode)lm) != NDBT_OK){
156       g_info << endl;
157       return NDBT_FAILED;
158     }
159     i++;
160   }
161   g_info << endl;
162   return NDBT_OK;
163 }
164 
runPkReadUntilStopped(NDBT_Context * ctx,NDBT_Step * step)165 int runPkReadUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
166   int records = ctx->getNumRecords();
167   int batchSize = ctx->getProperty("BatchSize", 1);
168   int i = 0;
169   HugoTransactions hugoTrans(*ctx->getTab());
170   while (ctx->isTestStopped() == false) {
171     g_info << i << ": ";
172     if (hugoTrans.pkReadRecords(GETNDB(step), records, batchSize) != 0){
173       g_info << endl;
174       return NDBT_FAILED;
175     }
176     i++;
177   }
178   g_info << endl;
179   return NDBT_OK;
180 }
181 
runPkUpdate(NDBT_Context * ctx,NDBT_Step * step)182 int runPkUpdate(NDBT_Context* ctx, NDBT_Step* step){
183   int loops = ctx->getNumLoops();
184   int records = ctx->getNumRecords();
185   int batchSize = ctx->getProperty("BatchSize", 1);
186   int i = 0;
187   HugoTransactions hugoTrans(*ctx->getTab());
188   while (i<loops) {
189     g_info << "|- " << i << ": ";
190     if (hugoTrans.pkUpdateRecords(GETNDB(step), records, batchSize) != 0){
191       g_info << endl;
192       return NDBT_FAILED;
193     }
194     i++;
195   }
196   g_info << endl;
197   return NDBT_OK;
198 }
199 
runPkUpdateUntilStopped(NDBT_Context * ctx,NDBT_Step * step)200 int runPkUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
201   int records = ctx->getNumRecords();
202   int batchSize = ctx->getProperty("BatchSize", 1);
203   int i = 0;
204   HugoTransactions hugoTrans(*ctx->getTab());
205   while (ctx->isTestStopped()) {
206     g_info << i << ": ";
207     if (hugoTrans.pkUpdateRecords(GETNDB(step), records, batchSize) != 0){
208       g_info << endl;
209       return NDBT_FAILED;
210     }
211     i++;
212   }
213   g_info << endl;
214   return NDBT_OK;
215 }
216 
runLocker(NDBT_Context * ctx,NDBT_Step * step)217 int runLocker(NDBT_Context* ctx, NDBT_Step* step){
218   int result = NDBT_OK;
219   int records = ctx->getNumRecords();
220   HugoTransactions hugoTrans(*ctx->getTab());
221 
222   if (hugoTrans.lockRecords(GETNDB(step), records, 10, 500) != 0){
223     result = NDBT_FAILED;
224   }
225   ctx->stopTest();
226 
227   return result;
228 }
229 
230 int
runInsertOne(NDBT_Context * ctx,NDBT_Step * step)231 runInsertOne(NDBT_Context* ctx, NDBT_Step* step){
232 
233   if(ctx->getProperty("InsertCommitted", (Uint32)0) != 0){
234     abort();
235   }
236 
237   while(ctx->getProperty("Read1Performed", (Uint32)0) == 0){
238     NdbSleep_MilliSleep(20);
239   }
240 
241   HugoTransactions hugoTrans(*ctx->getTab());
242 
243   if (hugoTrans.loadTable(GETNDB(step), 1, 1) != 0){
244     return NDBT_FAILED;
245   }
246 
247   ctx->setProperty("InsertCommitted", 1);
248 
249   NdbSleep_SecSleep(2);
250 
251   return NDBT_OK;
252 }
253 
254 static
255 int
readOneNoCommit(Ndb * pNdb,NdbConnection * pTrans,const NdbDictionary::Table * tab,NDBT_ResultRow * row)256 readOneNoCommit(Ndb* pNdb, NdbConnection* pTrans,
257 		const NdbDictionary::Table* tab,NDBT_ResultRow * row){
258   int a;
259   NdbOperation * pOp = pTrans->getNdbOperation(tab->getName());
260   if (pOp == NULL){
261     ERR(pTrans->getNdbError());
262     return NDBT_FAILED;
263   }
264 
265   HugoTransactions tmp(*tab);
266 
267   int check = pOp->readTuple();
268   if( check == -1 ) {
269     ERR(pTrans->getNdbError());
270     return NDBT_FAILED;
271   }
272 
273   // Define primary keys
274   for(a = 0; a<tab->getNoOfColumns(); a++){
275     if (tab->getColumn(a)->getPrimaryKey() == true){
276       if(tmp.equalForAttr(pOp, a, 0) != 0){
277 	ERR(pTrans->getNdbError());
278 	return NDBT_FAILED;
279       }
280     }
281   }
282 
283   // Define attributes to read
284   for(a = 0; a<tab->getNoOfColumns(); a++){
285     if((row->attributeStore(a) =
286 	pOp->getValue(tab->getColumn(a)->getName())) == 0) {
287       ERR(pTrans->getNdbError());
288       return NDBT_FAILED;
289     }
290   }
291 
292   check = pTrans->execute(NoCommit);
293   if( check == -1 ) {
294     const NdbError err = pTrans->getNdbError();
295     ERR(err);
296     return err.code;
297   }
298   return NDBT_OK;
299 }
300 
301 int
runReadOne(NDBT_Context * ctx,NDBT_Step * step)302 runReadOne(NDBT_Context* ctx, NDBT_Step* step){
303 
304   Ndb* pNdb = GETNDB(step);
305   const NdbDictionary::Table* tab = ctx->getTab();
306   NDBT_ResultRow row1(*tab);
307   NDBT_ResultRow row2(*tab);
308 
309   if(ctx->getProperty("Read1Performed", (Uint32)0) != 0){
310     abort();
311   }
312 
313   if(ctx->getProperty("InsertCommitted", (Uint32)0) != 0){
314     abort();
315   }
316 
317   NdbConnection * pTrans = pNdb->startTransaction();
318   if (pTrans == NULL) {
319     abort();
320   }
321 
322   // Read a record with NoCommit
323   // Since the record isn't inserted yet it wil return 626
324   const int res1 = readOneNoCommit(pNdb, pTrans, tab, &row1);
325   g_info << "|- res1 = " << res1 << endl;
326 
327   ctx->setProperty("Read1Performed", 1);
328 
329   while(ctx->getProperty("InsertCommitted", (Uint32)0) == 0 &&
330 	!ctx->isTestStopped()){
331     g_info << "|- Waiting for insert" << endl;
332     NdbSleep_MilliSleep(20);
333   }
334 
335   if(ctx->isTestStopped()){
336     abort();
337   }
338 
339   // Now the record should have been inserted
340   // Read it once again in the same transaction
341   // Should also reutrn 626 if reads are consistent
342 
343   // NOTE! Currently it's not possible to start a new operation
344   // on a transaction that has returned an error code
345   // This is wat fail in this test
346   // MASV 20030624
347   const int res2 = readOneNoCommit(pNdb, pTrans, tab, &row2);
348 
349   pTrans->execute(Commit);
350   pNdb->closeTransaction(pTrans);
351   g_info << "|- res2 = " << res2 << endl;
352 
353   if (res2 == 626 && res1 == res2)
354     return NDBT_OK;
355   else
356     return NDBT_FAILED;
357 }
358 
runFillTable(NDBT_Context * ctx,NDBT_Step * step)359 int runFillTable(NDBT_Context* ctx, NDBT_Step* step){
360   int batch = 512; //4096;
361   HugoTransactions hugoTrans(*ctx->getTab());
362   if (hugoTrans.fillTable(GETNDB(step), batch ) != 0){
363     return NDBT_FAILED;
364   }
365   return NDBT_OK;
366 }
367 
runClearTable2(NDBT_Context * ctx,NDBT_Step * step)368 int runClearTable2(NDBT_Context* ctx, NDBT_Step* step){
369   int records = ctx->getNumRecords();
370 
371   UtilTransactions utilTrans(*ctx->getTab());
372   if (utilTrans.clearTable2(GETNDB(step), records, 240) != 0){
373     return NDBT_FAILED;
374   }
375   return NDBT_OK;
376 }
377 
378 #define CHECK(b) if (!(b)) { \
379   ndbout << "ERR: "<< step->getName() \
380          << " failed on line " << __LINE__ << endl; \
381   result = NDBT_FAILED; \
382   break; }
383 
runNoCommitSleep(NDBT_Context * ctx,NDBT_Step * step)384 int runNoCommitSleep(NDBT_Context* ctx, NDBT_Step* step){
385   int result = NDBT_OK;
386   HugoOperations hugoOps(*ctx->getTab());
387   Ndb* pNdb = GETNDB(step);
388   int sleepTime = 100; // ms
389   for (int i = 2; i < 8; i++){
390 
391     CHECK(hugoOps.startTransaction(pNdb) == 0);
392     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
393     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
394 
395     ndbout << i <<": Sleeping for " << sleepTime << " ms" << endl;
396     NdbSleep_MilliSleep(sleepTime);
397 
398     // Dont care about result of these ops
399     hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive);
400     hugoOps.closeTransaction(pNdb);
401 
402     sleepTime = sleepTime *i;
403   }
404 
405   hugoOps.closeTransaction(pNdb);
406 
407   return result;
408 }
409 
runCommit626(NDBT_Context * ctx,NDBT_Step * step)410 int runCommit626(NDBT_Context* ctx, NDBT_Step* step){
411   int result = NDBT_OK;
412   HugoOperations hugoOps(*ctx->getTab());
413   Ndb* pNdb = GETNDB(step);
414 
415   do{
416     // Commit transaction
417     CHECK(hugoOps.startTransaction(pNdb) == 0);
418     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
419     CHECK(hugoOps.execute_Commit(pNdb) == 626);
420     CHECK(hugoOps.closeTransaction(pNdb) == 0);
421 
422     // Commit transaction
423     // Multiple operations
424     CHECK(hugoOps.startTransaction(pNdb) == 0);
425     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
426     CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
427     CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
428     CHECK(hugoOps.execute_Commit(pNdb) == 626);
429   }while(false);
430 
431   hugoOps.closeTransaction(pNdb);
432 
433   return result;
434 }
435 
runCommit630(NDBT_Context * ctx,NDBT_Step * step)436 int runCommit630(NDBT_Context* ctx, NDBT_Step* step){
437   int result = NDBT_OK;
438   HugoOperations hugoOps(*ctx->getTab());
439   Ndb* pNdb = GETNDB(step);
440 
441   do{
442     // Commit transaction
443     CHECK(hugoOps.startTransaction(pNdb) == 0);
444     CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
445     CHECK(hugoOps.execute_Commit(pNdb) == 630);
446   }while(false);
447 
448   hugoOps.closeTransaction(pNdb);
449 
450   return result;
451 }
452 
runCommit_TryCommit626(NDBT_Context * ctx,NDBT_Step * step)453 int runCommit_TryCommit626(NDBT_Context* ctx, NDBT_Step* step){
454   int result = NDBT_OK;
455   HugoOperations hugoOps(*ctx->getTab());
456   Ndb* pNdb = GETNDB(step);
457 
458   do{
459     // Commit transaction, TryCommit
460     CHECK(hugoOps.startTransaction(pNdb) == 0);
461     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
462     CHECK(hugoOps.execute_Commit(pNdb, TryCommit) == 626);
463     CHECK(hugoOps.closeTransaction(pNdb) == 0);
464 
465     // Commit transaction, TryCommit
466     // Several operations in one transaction
467     // The insert is OK
468     CHECK(hugoOps.startTransaction(pNdb) == 0);
469     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
470     CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
471     CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
472     CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
473     CHECK(hugoOps.pkReadRecord(pNdb, 4, 1, NdbOperation::LM_Exclusive) == 0);
474     CHECK(hugoOps.execute_Commit(pNdb, TryCommit) == 626);
475   }while(false);
476 
477   hugoOps.closeTransaction(pNdb);
478 
479   return result;
480 }
481 
runCommit_TryCommit630(NDBT_Context * ctx,NDBT_Step * step)482 int runCommit_TryCommit630(NDBT_Context* ctx, NDBT_Step* step){
483   int result = NDBT_OK;
484   HugoOperations hugoOps(*ctx->getTab());
485   Ndb* pNdb = GETNDB(step);
486 
487   do{
488     // Commit transaction, TryCommit
489     CHECK(hugoOps.startTransaction(pNdb) == 0);
490     CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
491     CHECK(hugoOps.execute_Commit(pNdb, TryCommit) == 630);
492   }while(false);
493 
494   hugoOps.closeTransaction(pNdb);
495 
496   return result;
497 }
498 
runCommit_CommitAsMuchAsPossible626(NDBT_Context * ctx,NDBT_Step * step)499 int runCommit_CommitAsMuchAsPossible626(NDBT_Context* ctx, NDBT_Step* step){
500   int result = NDBT_OK;
501   HugoOperations hugoOps(*ctx->getTab());
502   Ndb* pNdb = GETNDB(step);
503 
504   do{
505     // Commit transaction, CommitAsMuchAsPossible
506     CHECK(hugoOps.startTransaction(pNdb) == 0);
507     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
508     CHECK(hugoOps.execute_Commit(pNdb, CommitAsMuchAsPossible) == 626);
509     CHECK(hugoOps.closeTransaction(pNdb) == 0);
510 
511     // Commit transaction, CommitAsMuchAsPossible
512     CHECK(hugoOps.startTransaction(pNdb) == 0);
513     CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
514     CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
515     CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
516     CHECK(hugoOps.execute_Commit(pNdb, CommitAsMuchAsPossible) == 626);
517     CHECK(hugoOps.closeTransaction(pNdb) == 0);
518 
519     CHECK(hugoOps.startTransaction(pNdb) == 0);
520     CHECK(hugoOps.pkReadRecord(pNdb, 1) == 0);
521     CHECK(hugoOps.execute_Commit(pNdb) == 0);
522     CHECK(hugoOps.closeTransaction(pNdb) == 0);
523   } while(false);
524 
525   hugoOps.closeTransaction(pNdb);
526 
527   return result;
528 }
529 
runCommit_CommitAsMuchAsPossible630(NDBT_Context * ctx,NDBT_Step * step)530 int runCommit_CommitAsMuchAsPossible630(NDBT_Context* ctx, NDBT_Step* step){
531   int result = NDBT_OK;
532   HugoOperations hugoOps(*ctx->getTab());
533   Ndb* pNdb = GETNDB(step);
534 
535   do{
536     // Commit transaction, CommitAsMuchAsPossible
537     CHECK(hugoOps.startTransaction(pNdb) == 0);
538     CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
539     CHECK(hugoOps.pkDeleteRecord(pNdb, 2) == 0);
540     CHECK(hugoOps.execute_Commit(pNdb, CommitAsMuchAsPossible) == 630);
541     CHECK(hugoOps.closeTransaction(pNdb) == 0);
542 
543     CHECK(hugoOps.startTransaction(pNdb) == 0);
544     CHECK(hugoOps.pkReadRecord(pNdb, 2) == 0);
545     CHECK(hugoOps.execute_Commit(pNdb) == 626);
546   } while(false);
547 
548   hugoOps.closeTransaction(pNdb);
549 
550   return result;
551 }
552 
runNoCommit626(NDBT_Context * ctx,NDBT_Step * step)553 int runNoCommit626(NDBT_Context* ctx, NDBT_Step* step){
554   int result = NDBT_OK;
555   HugoOperations hugoOps(*ctx->getTab());
556   Ndb* pNdb = GETNDB(step);
557 
558   do{
559     // No commit transaction, readTuple
560     CHECK(hugoOps.startTransaction(pNdb) == 0);
561     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
562     CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
563     CHECK(hugoOps.closeTransaction(pNdb) == 0);
564 
565     // No commit transaction, readTupleExcluive
566     CHECK(hugoOps.startTransaction(pNdb) == 0);
567     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
568     CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
569   }while(false);
570 
571   hugoOps.closeTransaction(pNdb);
572 
573   return result;
574 }
575 
runNoCommit630(NDBT_Context * ctx,NDBT_Step * step)576 int runNoCommit630(NDBT_Context* ctx, NDBT_Step* step){
577   int result = NDBT_OK;
578   HugoOperations hugoOps(*ctx->getTab());
579   Ndb* pNdb = GETNDB(step);
580 
581   do{
582     // No commit transaction
583     CHECK(hugoOps.startTransaction(pNdb) == 0);
584     CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
585     CHECK(hugoOps.execute_NoCommit(pNdb) == 630);
586   }while(false);
587 
588   hugoOps.closeTransaction(pNdb);
589 
590   return result;
591 }
592 
runNoCommitRollback626(NDBT_Context * ctx,NDBT_Step * step)593 int runNoCommitRollback626(NDBT_Context* ctx, NDBT_Step* step){
594   int result = NDBT_OK;
595   HugoOperations hugoOps(*ctx->getTab());
596   Ndb* pNdb = GETNDB(step);
597 
598   do{
599     // No commit transaction, rollback
600     CHECK(hugoOps.startTransaction(pNdb) == 0);
601     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
602     CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
603     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
604     CHECK(hugoOps.closeTransaction(pNdb) == 0);
605 
606     // No commit transaction, rollback
607     // Multiple operations
608     CHECK(hugoOps.startTransaction(pNdb) == 0);
609     CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
610     CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
611     CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
612     CHECK(hugoOps.pkReadRecord(pNdb, 4, 1, NdbOperation::LM_Exclusive) == 0);
613     CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
614     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
615   }while(false);
616 
617   hugoOps.closeTransaction(pNdb);
618 
619   return result;
620 }
621 
runNoCommitRollback630(NDBT_Context * ctx,NDBT_Step * step)622 int runNoCommitRollback630(NDBT_Context* ctx, NDBT_Step* step){
623   int result = NDBT_OK;
624   HugoOperations hugoOps(*ctx->getTab());
625   Ndb* pNdb = GETNDB(step);
626 
627   do{
628     // No commit transaction, rollback
629     CHECK(hugoOps.startTransaction(pNdb) == 0);
630     CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
631     CHECK(hugoOps.execute_NoCommit(pNdb) == 630);
632     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
633   }while(false);
634 
635   hugoOps.closeTransaction(pNdb);
636 
637   return result;
638 }
639 
640 
runNoCommitAndClose(NDBT_Context * ctx,NDBT_Step * step)641 int runNoCommitAndClose(NDBT_Context* ctx, NDBT_Step* step){
642   int i, result = NDBT_OK;
643   HugoOperations hugoOps(*ctx->getTab());
644   Ndb* pNdb = GETNDB(step);
645 
646   do{
647     // Read
648     CHECK(hugoOps.startTransaction(pNdb) == 0);
649     for (i = 0; i < 10; i++)
650       CHECK(hugoOps.pkReadRecord(pNdb, i, 1, NdbOperation::LM_Exclusive) == 0);
651     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
652     CHECK(hugoOps.closeTransaction(pNdb) == 0);
653 
654     // Update
655     CHECK(hugoOps.startTransaction(pNdb) == 0);
656     for (i = 0; i < 10; i++)
657       CHECK(hugoOps.pkUpdateRecord(pNdb, i) == 0);
658     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
659     CHECK(hugoOps.closeTransaction(pNdb) == 0);
660 
661     // Delete
662     CHECK(hugoOps.startTransaction(pNdb) == 0);
663     for (i = 0; i < 10; i++)
664       CHECK(hugoOps.pkDeleteRecord(pNdb, i) == 0);
665     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
666     CHECK(hugoOps.closeTransaction(pNdb) == 0);
667 
668     // Try to insert, record should already exist
669     CHECK(hugoOps.startTransaction(pNdb) == 0);
670     for (i = 0; i < 10; i++)
671       CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0);
672     CHECK(hugoOps.execute_Commit(pNdb) == 630);
673     CHECK(hugoOps.closeTransaction(pNdb) == 0);
674 
675   }while(false);
676 
677   hugoOps.closeTransaction(pNdb);
678 
679   return result;
680 }
681 
682 
683 
runCheckRollbackDelete(NDBT_Context * ctx,NDBT_Step * step)684 int runCheckRollbackDelete(NDBT_Context* ctx, NDBT_Step* step){
685   int result = NDBT_OK;
686   HugoOperations hugoOps(*ctx->getTab());
687   Ndb* pNdb = GETNDB(step);
688 
689   do{
690 
691     // Read value and save it for later
692     CHECK(hugoOps.startTransaction(pNdb) == 0);
693     CHECK(hugoOps.pkReadRecord(pNdb, 5) == 0);
694     CHECK(hugoOps.execute_Commit(pNdb) == 0);
695     CHECK(hugoOps.saveCopyOfRecord() == NDBT_OK);
696     CHECK(hugoOps.closeTransaction(pNdb) == 0);
697 
698     // Delete record 5
699     CHECK(hugoOps.startTransaction(pNdb) == 0);
700     CHECK(hugoOps.pkDeleteRecord(pNdb, 5) == 0);
701     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
702 
703     // Check record is deleted
704     CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
705     CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
706     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
707 
708     CHECK(hugoOps.closeTransaction(pNdb) == 0);
709 
710     // Check record is not deleted
711     CHECK(hugoOps.startTransaction(pNdb) == 0);
712     CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
713     CHECK(hugoOps.execute_Commit(pNdb) == 0);
714     CHECK(hugoOps.closeTransaction(pNdb) == 0);
715 
716     // Check record is back to original value
717     CHECK(hugoOps.startTransaction(pNdb) == 0);
718     CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
719     CHECK(hugoOps.execute_Commit(pNdb) == 0);
720     CHECK(hugoOps.compareRecordToCopy() == NDBT_OK);
721 
722 
723   }while(false);
724 
725   hugoOps.closeTransaction(pNdb);
726 
727   return result;
728 }
729 
runCheckRollbackUpdate(NDBT_Context * ctx,NDBT_Step * step)730 int runCheckRollbackUpdate(NDBT_Context* ctx, NDBT_Step* step){
731   int result = NDBT_OK;
732   HugoOperations hugoOps(*ctx->getTab());
733   Ndb* pNdb = GETNDB(step);
734   int numRecords = 5;
735   do{
736 
737     // Read value and save it for later
738     CHECK(hugoOps.startTransaction(pNdb) == 0);
739     CHECK(hugoOps.pkReadRecord(pNdb, 1, numRecords) == 0);
740     CHECK(hugoOps.execute_Commit(pNdb) == 0);
741     CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK); // Update value 0
742     CHECK(hugoOps.closeTransaction(pNdb) == 0);
743 
744     // Update  record 5
745     CHECK(hugoOps.startTransaction(pNdb) == 0);
746     CHECK(hugoOps.pkUpdateRecord(pNdb, 1, numRecords, 5) == 0);// Updates value 5
747     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
748 
749     // Check record is updated
750     CHECK(hugoOps.pkReadRecord(pNdb, 1, numRecords, NdbOperation::LM_Exclusive) == 0);
751     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
752     CHECK(hugoOps.verifyUpdatesValue(5) == NDBT_OK); // Updates value 5
753     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
754 
755     CHECK(hugoOps.closeTransaction(pNdb) == 0);
756 
757     // Check record is back to original value
758     CHECK(hugoOps.startTransaction(pNdb) == 0);
759     CHECK(hugoOps.pkReadRecord(pNdb, 1, numRecords, NdbOperation::LM_Exclusive) == 0);
760     CHECK(hugoOps.execute_Commit(pNdb) == 0);
761     CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK); // Updates value 0
762 
763   }while(false);
764 
765   hugoOps.closeTransaction(pNdb);
766 
767   return result;
768 }
769 
runCheckRollbackDeleteMultiple(NDBT_Context * ctx,NDBT_Step * step)770 int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
771   int result = NDBT_OK;
772   HugoOperations hugoOps(*ctx->getTab());
773   Ndb* pNdb = GETNDB(step);
774 
775   do{
776     // Read value and save it for later
777     CHECK(hugoOps.startTransaction(pNdb) == 0);
778     CHECK(hugoOps.pkReadRecord(pNdb, 5, 10) == 0);
779     CHECK(hugoOps.execute_Commit(pNdb) == 0);
780     CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK);
781     CHECK(hugoOps.closeTransaction(pNdb) == 0);
782 
783     Uint32 updatesValue = 0;
784     Uint32 j;
785     for(Uint32 i = 0; i<1; i++){
786       // Read  record 5 - 10
787       CHECK(hugoOps.startTransaction(pNdb) == 0);
788       CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
789       CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
790 
791       for(j = 0; j<10; j++){
792 	// Update  record 5 - 10
793 	updatesValue++;
794 	CHECK(hugoOps.pkUpdateRecord(pNdb, 5, 10, updatesValue) == 0);
795 	CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
796 
797 	CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
798 	CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
799 	CHECK(hugoOps.verifyUpdatesValue(updatesValue) == 0);
800       }
801 
802       for(j = 0; j<10; j++){
803 	// Delete record 5 - 10 times
804 	CHECK(hugoOps.pkDeleteRecord(pNdb, 5, 10) == 0);
805 	CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
806 
807 #if 0
808 	// Check records are deleted
809 	CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
810 	CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
811 #endif
812 
813 	updatesValue++;
814 	CHECK(hugoOps.pkInsertRecord(pNdb, 5, 10, updatesValue) == 0);
815 	CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
816 
817 	CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
818 	CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
819 	CHECK(hugoOps.verifyUpdatesValue(updatesValue) == 0);
820       }
821 
822       CHECK(hugoOps.pkDeleteRecord(pNdb, 5, 10) == 0);
823       CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
824 
825       // Check records are deleted
826       CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
827       CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
828       CHECK(hugoOps.execute_Rollback(pNdb) == 0);
829 
830       CHECK(hugoOps.closeTransaction(pNdb) == 0);
831     }
832 
833     // Check records are not deleted
834     // after rollback
835     CHECK(hugoOps.startTransaction(pNdb) == 0);
836     CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
837     CHECK(hugoOps.execute_Commit(pNdb) == 0);
838     CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK);
839 
840   }while(false);
841 
842   hugoOps.closeTransaction(pNdb);
843 
844   return result;
845 }
846 
847 
runCheckImplicitRollbackDelete(NDBT_Context * ctx,NDBT_Step * step)848 int runCheckImplicitRollbackDelete(NDBT_Context* ctx, NDBT_Step* step){
849   int result = NDBT_OK;
850   HugoOperations hugoOps(*ctx->getTab());
851   Ndb* pNdb = GETNDB(step);
852 
853   do{
854     // Read  record 5
855     CHECK(hugoOps.startTransaction(pNdb) == 0);
856     CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
857     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
858     CHECK(hugoOps.closeTransaction(pNdb) == 0);
859 
860     // Update  record 5
861     CHECK(hugoOps.startTransaction(pNdb) == 0);
862     CHECK(hugoOps.pkUpdateRecord(pNdb, 5) == 0);
863     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
864     CHECK(hugoOps.closeTransaction(pNdb) == 0);
865 
866     // Delete record 5
867     CHECK(hugoOps.startTransaction(pNdb) == 0);
868     CHECK(hugoOps.pkDeleteRecord(pNdb, 5) == 0);
869     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
870     CHECK(hugoOps.closeTransaction(pNdb) == 0);
871 
872     // Check record is not deleted
873     // Close transaction should have rollbacked
874     CHECK(hugoOps.startTransaction(pNdb) == 0);
875     CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
876     CHECK(hugoOps.execute_Commit(pNdb) == 0);
877   }while(false);
878 
879   hugoOps.closeTransaction(pNdb);
880 
881   return result;
882 }
883 
runCheckCommitDelete(NDBT_Context * ctx,NDBT_Step * step)884 int runCheckCommitDelete(NDBT_Context* ctx, NDBT_Step* step){
885   int result = NDBT_OK;
886   HugoOperations hugoOps(*ctx->getTab());
887   Ndb* pNdb = GETNDB(step);
888 
889   do{
890     // Read  10 records
891     CHECK(hugoOps.startTransaction(pNdb) == 0);
892     CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
893     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
894 
895     // Update 10 records
896     CHECK(hugoOps.pkUpdateRecord(pNdb, 5, 10) == 0);
897     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
898 
899     // Delete 10 records
900     CHECK(hugoOps.pkDeleteRecord(pNdb, 5, 10) == 0);
901     CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
902 
903     CHECK(hugoOps.execute_Commit(pNdb) == 0);
904     CHECK(hugoOps.closeTransaction(pNdb) == 0);
905 
906     // Check record's are deleted
907     CHECK(hugoOps.startTransaction(pNdb) == 0);
908     CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
909     CHECK(hugoOps.execute_Commit(pNdb) == 626);
910 
911   }while(false);
912 
913   hugoOps.closeTransaction(pNdb);
914 
915   return result;
916 }
917 
runRollbackNothing(NDBT_Context * ctx,NDBT_Step * step)918 int runRollbackNothing(NDBT_Context* ctx, NDBT_Step* step){
919   int result = NDBT_OK;
920   HugoOperations hugoOps(*ctx->getTab());
921   Ndb* pNdb = GETNDB(step);
922 
923   do{
924     // Delete record 5 - 15
925     CHECK(hugoOps.startTransaction(pNdb) == 0);
926     CHECK(hugoOps.pkDeleteRecord(pNdb, 5, 10) == 0);
927     // Rollback
928     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
929     CHECK(hugoOps.closeTransaction(pNdb) == 0);
930 
931     // Check records are not deleted
932     CHECK(hugoOps.startTransaction(pNdb) == 0);
933     CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
934     CHECK(hugoOps.execute_Commit(pNdb) == 0);
935     CHECK(hugoOps.closeTransaction(pNdb) == 0);
936 
937     CHECK(hugoOps.startTransaction(pNdb) == 0);
938     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
939 
940   }while(false);
941 
942   hugoOps.closeTransaction(pNdb);
943 
944   return result;
945 }
946 
runMassiveRollback(NDBT_Context * ctx,NDBT_Step * step)947 int runMassiveRollback(NDBT_Context* ctx, NDBT_Step* step){
948 
949   NdbRestarter restarter;
950   const int records = 4 * restarter.getNumDbNodes();
951 
952   HugoTransactions hugoTrans(*ctx->getTab());
953   if (hugoTrans.loadTable(GETNDB(step), records) != 0){
954     return NDBT_FAILED;
955   }
956 
957   int result = NDBT_OK;
958   HugoOperations hugoOps(*ctx->getTab());
959   Ndb* pNdb = GETNDB(step);
960 
961   const Uint32 OPS_PER_TRANS = 256;
962   const Uint32 OPS_TOTAL = 4096;
963 
964   for(int row = 0; row < records; row++){
965     int res;
966     CHECK(hugoOps.startTransaction(pNdb) == 0);
967     for(Uint32 i = 0; i<OPS_TOTAL; i += OPS_PER_TRANS){
968       for(Uint32 j = 0; j<OPS_PER_TRANS; j++){
969 	CHECK(hugoOps.pkUpdateRecord(pNdb, row, 1, i) == 0);
970       }
971       g_info << "Performed " << (i+OPS_PER_TRANS) << " updates on row: " << row
972 	     << endl;
973       if(result != NDBT_OK){
974 	break;
975       }
976       res = hugoOps.execute_NoCommit(pNdb);
977       if(res != 0){
978 	NdbError err = pNdb->getNdbError(res);
979 	CHECK(err.classification == NdbError::TimeoutExpired);
980 	break;
981       }
982     }
983     if(result != NDBT_OK){
984       break;
985     }
986     g_info << "executeRollback" << endl;
987     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
988     CHECK(hugoOps.closeTransaction(pNdb) == 0);
989   }
990 
991   hugoOps.closeTransaction(pNdb);
992   return result;
993 }
994 
995 int
runMassiveRollback2(NDBT_Context * ctx,NDBT_Step * step)996 runMassiveRollback2(NDBT_Context* ctx, NDBT_Step* step){
997 
998   HugoTransactions hugoTrans(*ctx->getTab());
999   if (hugoTrans.loadTable(GETNDB(step), 1) != 0){
1000     return NDBT_FAILED;
1001   }
1002 
1003   int result = NDBT_OK;
1004   HugoOperations hugoOps(*ctx->getTab());
1005   Ndb* pNdb = GETNDB(step);
1006 
1007   const Uint32 OPS_TOTAL = 4096;
1008   const Uint32 LOOPS = 10;
1009 
1010   for(Uint32 loop = 0; loop<LOOPS; loop++){
1011     CHECK(hugoOps.startTransaction(pNdb) == 0);
1012     for(Uint32 i = 0; i<OPS_TOTAL-1; i ++){
1013       if((i & 1) == 0){
1014 	CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, loop) == 0);
1015       } else {
1016 	CHECK(hugoOps.pkUpdateRecord(pNdb, 1, 1, loop) == 0);
1017       }
1018     }
1019     CHECK(hugoOps.execute_Commit(pNdb) == 626);
1020     CHECK(hugoOps.execute_Rollback(pNdb) == 0);
1021     CHECK(hugoOps.closeTransaction(pNdb) == 0);
1022   }
1023 
1024   hugoOps.closeTransaction(pNdb);
1025   return result;
1026 }
1027 
1028 int
runMassiveRollback3(NDBT_Context * ctx,NDBT_Step * step)1029 runMassiveRollback3(NDBT_Context* ctx, NDBT_Step* step){
1030 
1031   int result = NDBT_OK;
1032   HugoOperations hugoOps(*ctx->getTab());
1033   Ndb* pNdb = GETNDB(step);
1034 
1035   const Uint32 BATCH = 10;
1036   const Uint32 OPS_TOTAL = 50;
1037   const Uint32 LOOPS = 100;
1038 
1039   for(Uint32 loop = 0; loop<LOOPS; loop++)
1040   {
1041     CHECK(hugoOps.startTransaction(pNdb) == 0);
1042     bool ok = true;
1043     for (Uint32 i = 0; i<OPS_TOTAL; i+= BATCH)
1044     {
1045       CHECK(hugoOps.pkInsertRecord(pNdb, i, BATCH, 0) == 0);
1046       if (hugoOps.execute_NoCommit(pNdb) != 0)
1047       {
1048 	ok = false;
1049 	break;
1050       }
1051     }
1052     hugoOps.execute_Rollback(pNdb);
1053     CHECK(hugoOps.closeTransaction(pNdb) == 0);
1054   }
1055 
1056   hugoOps.closeTransaction(pNdb);
1057   return result;
1058 }
1059 
1060 int
runMassiveRollback4(NDBT_Context * ctx,NDBT_Step * step)1061 runMassiveRollback4(NDBT_Context* ctx, NDBT_Step* step){
1062 
1063   int result = NDBT_OK;
1064   HugoOperations hugoOps(*ctx->getTab());
1065   Ndb* pNdb = GETNDB(step);
1066 
1067   const Uint32 BATCH = 10;
1068   const Uint32 OPS_TOTAL = 20;
1069   const Uint32 LOOPS = 100;
1070 
1071   for(Uint32 loop = 0; loop<LOOPS; loop++)
1072   {
1073     CHECK(hugoOps.startTransaction(pNdb) == 0);
1074     bool ok = true;
1075     for (Uint32 i = 0; i<OPS_TOTAL; i+= BATCH)
1076     {
1077       CHECK(hugoOps.pkInsertRecord(pNdb, i, BATCH, 0) == 0);
1078       CHECK(hugoOps.pkDeleteRecord(pNdb, i, BATCH) == 0);
1079       if (hugoOps.execute_NoCommit(pNdb) != 0)
1080       {
1081 	ok = false;
1082 	break;
1083       }
1084     }
1085     hugoOps.execute_Rollback(pNdb);
1086     CHECK(hugoOps.closeTransaction(pNdb) == 0);
1087   }
1088 
1089   hugoOps.closeTransaction(pNdb);
1090   return result;
1091 }
1092 
1093 /**
1094  * TUP errors
1095  */
1096 struct TupError
1097 {
1098   enum Bits {
1099     TE_VARSIZE  = 0x1,
1100     TE_MULTI_OP = 0x2,
1101     TE_DISK     = 0x4,
1102     TE_REPLICA  = 0x8,
1103     TE_OI       = 0x10, // Ordered index
1104     TE_UI       = 0x20  // Unique hash index
1105   };
1106   int op;
1107   int error;
1108   int bits;
1109 };
1110 
1111 static
1112 TupError
1113 f_tup_errors[] =
1114 {
1115   { NdbOperation::InsertRequest, 4014, 0 },       // Out of undo buffer
1116   { NdbOperation::InsertRequest, 4015, TupError::TE_DISK }, // Out of log space
1117   { NdbOperation::InsertRequest, 4016, 0 },       // AI Inconsistency
1118   { NdbOperation::InsertRequest, 4017, 0 },       // Out of memory
1119   { NdbOperation::InsertRequest, 4018, 0 },       // Null check error
1120   { NdbOperation::InsertRequest, 4019, TupError::TE_REPLICA }, //Alloc rowid error
1121   { NdbOperation::InsertRequest, 4020, TupError::TE_MULTI_OP }, // Size change error
1122   { NdbOperation::InsertRequest, 4021, TupError::TE_DISK },    // Out of disk space
1123   { NdbOperation::InsertRequest, 4022, TupError::TE_OI },
1124   { NdbOperation::InsertRequest, 4023, TupError::TE_OI },
1125   { NdbOperation::UpdateRequest, 4030, TupError::TE_UI },
1126   { -1, 0, 0 }
1127 };
1128 
1129 int
runTupErrors(NDBT_Context * ctx,NDBT_Step * step)1130 runTupErrors(NDBT_Context* ctx, NDBT_Step* step){
1131 
1132   NdbRestarter restarter;
1133   HugoTransactions hugoTrans(*ctx->getTab());
1134   HugoOperations hugoOps(*ctx->getTab());
1135   Ndb* pNdb = GETNDB(step);
1136 
1137   const NdbDictionary::Table * tab = ctx->getTab();
1138   int i;
1139   int bits = TupError::TE_MULTI_OP;
1140   for(i = 0; i<tab->getNoOfColumns(); i++)
1141   {
1142     if (tab->getColumn(i)->getArrayType() != NdbDictionary::Column::ArrayTypeFixed)
1143       bits |= TupError::TE_VARSIZE;
1144     if (tab->getColumn(i)->getStorageType()!= NdbDictionary::Column::StorageTypeMemory)
1145       bits |= TupError::TE_DISK;
1146   }
1147 
1148   if (restarter.getNumDbNodes() >= 2)
1149   {
1150     bits |= TupError::TE_REPLICA;
1151   }
1152 
1153   NdbDictionary::Dictionary::List l;
1154   pNdb->getDictionary()->listIndexes(l, tab->getName());
1155   for (i = 0; i<(int)l.count; i++)
1156   {
1157     if (DictTabInfo::isOrderedIndex(l.elements[i].type))
1158       bits |= TupError::TE_OI;
1159     if (DictTabInfo::isUniqueIndex(l.elements[i].type))
1160       bits |= TupError::TE_UI;
1161   }
1162 
1163   /**
1164    * Insert
1165    */
1166   for(i = 0; f_tup_errors[i].op != -1; i++)
1167   {
1168     if (f_tup_errors[i].op != NdbOperation::InsertRequest)
1169     {
1170       continue;
1171     }
1172 
1173     if ((f_tup_errors[i].bits & bits) != f_tup_errors[i].bits)
1174     {
1175       g_err << "Skipping " << f_tup_errors[i].error
1176             << " - req bits: " << hex << f_tup_errors[i].bits
1177             << " bits: " << hex << bits << endl;
1178       continue;
1179     }
1180 
1181     g_err << "Testing error insert: " << f_tup_errors[i].error << endl;
1182     restarter.insertErrorInAllNodes(f_tup_errors[i].error);
1183     if (f_tup_errors[i].bits & TupError::TE_MULTI_OP)
1184     {
1185 
1186     }
1187     else
1188     {
1189       hugoTrans.loadTable(pNdb, 5);
1190     }
1191     restarter.insertErrorInAllNodes(0);
1192     if (hugoTrans.clearTable(pNdb, 5) != 0)
1193     {
1194       return NDBT_FAILED;
1195     }
1196   }
1197 
1198   /**
1199    * update
1200    */
1201   hugoTrans.loadTable(pNdb, 5);
1202   for(i = 0; f_tup_errors[i].op != -1; i++)
1203   {
1204     if (f_tup_errors[i].op != NdbOperation::UpdateRequest)
1205     {
1206       continue;
1207     }
1208 
1209     if ((f_tup_errors[i].bits & bits) != f_tup_errors[i].bits)
1210     {
1211       g_err << "Skipping " << f_tup_errors[i].error
1212             << " - req bits: " << hex << f_tup_errors[i].bits
1213             << " bits: " << hex << bits << endl;
1214       continue;
1215     }
1216 
1217     g_err << "Testing error insert: " << f_tup_errors[i].error << endl;
1218     restarter.insertErrorInAllNodes(f_tup_errors[i].error);
1219     if (f_tup_errors[i].bits & TupError::TE_MULTI_OP)
1220     {
1221 
1222     }
1223     else
1224     {
1225       hugoTrans.scanUpdateRecords(pNdb, 5);
1226     }
1227     restarter.insertErrorInAllNodes(0);
1228     if (hugoTrans.scanUpdateRecords(pNdb, 5) != 0)
1229     {
1230       return NDBT_FAILED;
1231     }
1232   }
1233 
1234   return NDBT_OK;
1235 }
1236 
1237 int
runInsertError(NDBT_Context * ctx,NDBT_Step * step)1238 runInsertError(NDBT_Context* ctx, NDBT_Step* step){
1239 
1240   int result = NDBT_OK;
1241   HugoOperations hugoOp1(*ctx->getTab());
1242   HugoOperations hugoOp2(*ctx->getTab());
1243   Ndb* pNdb = GETNDB(step);
1244 
1245   NdbRestarter restarter;
1246   restarter.insertErrorInAllNodes(4017);
1247   const Uint32 LOOPS = 10;
1248   for (Uint32 i = 0; i<LOOPS; i++)
1249   {
1250     CHECK(hugoOp1.startTransaction(pNdb) == 0);
1251     CHECK(hugoOp1.pkInsertRecord(pNdb, 1) == 0);
1252 
1253     CHECK(hugoOp2.startTransaction(pNdb) == 0);
1254     CHECK(hugoOp2.pkReadRecord(pNdb, 1, 1) == 0);
1255 
1256     CHECK(hugoOp1.execute_async_prepare(pNdb, NdbTransaction::Commit) == 0);
1257     CHECK(hugoOp2.execute_async_prepare(pNdb, NdbTransaction::Commit) == 0);
1258     hugoOp1.wait_async(pNdb);
1259     hugoOp2.wait_async(pNdb);
1260     CHECK(hugoOp1.closeTransaction(pNdb) == 0);
1261     CHECK(hugoOp2.closeTransaction(pNdb) == 0);
1262   }
1263 
1264   restarter.insertErrorInAllNodes(0);
1265 
1266   return result;
1267 }
1268 
1269 int
runInsertError2(NDBT_Context * ctx,NDBT_Step * step)1270 runInsertError2(NDBT_Context* ctx, NDBT_Step* step){
1271   int result = NDBT_OK;
1272   HugoOperations hugoOp1(*ctx->getTab());
1273   Ndb* pNdb = GETNDB(step);
1274 
1275   NdbRestarter restarter;
1276   restarter.insertErrorInAllNodes(4017);
1277 
1278   const Uint32 LOOPS = 1;
1279   for (Uint32 i = 0; i<LOOPS; i++)
1280   {
1281     CHECK(hugoOp1.startTransaction(pNdb) == 0);
1282     CHECK(hugoOp1.pkInsertRecord(pNdb, 1) == 0);
1283     CHECK(hugoOp1.pkDeleteRecord(pNdb, 1) == 0);
1284 
1285     hugoOp1.execute_NoCommit(pNdb);
1286     CHECK(hugoOp1.closeTransaction(pNdb) == 0);
1287   }
1288 
1289   restarter.insertErrorInAllNodes(0);
1290   return NDBT_OK;
1291 }
1292 
1293 int
runBug25090(NDBT_Context * ctx,NDBT_Step * step)1294 runBug25090(NDBT_Context* ctx, NDBT_Step* step){
1295 
1296   Ndb* pNdb = GETNDB(step);
1297   //NdbDictionary::Dictionary * dict = pNdb->getDictionary();
1298 
1299   HugoOperations ops(*ctx->getTab());
1300 
1301   int loops = ctx->getNumLoops();
1302   //const int rows = ctx->getNumRecords();
1303 
1304   while (loops--)
1305   {
1306     ops.startTransaction(pNdb);
1307     ops.pkReadRecord(pNdb, 1, 1);
1308     ops.execute_Commit(pNdb, AO_IgnoreError);
1309     sleep(10);
1310     ops.closeTransaction(pNdb);
1311   }
1312 
1313   return NDBT_OK;
1314 }
1315 
1316 int
runDeleteRead(NDBT_Context * ctx,NDBT_Step * step)1317 runDeleteRead(NDBT_Context* ctx, NDBT_Step* step){
1318 
1319   Ndb* pNdb = GETNDB(step);
1320 
1321   const NdbDictionary::Table* tab = ctx->getTab();
1322   NDBT_ResultRow row(*ctx->getTab());
1323   HugoTransactions tmp(*ctx->getTab());
1324 
1325   int a;
1326   int loops = ctx->getNumLoops();
1327   //const int rows = ctx->getNumRecords();
1328 
1329   while (loops--)
1330   {
1331     NdbTransaction* pTrans = pNdb->startTransaction();
1332     NdbOperation* pOp = pTrans->getNdbOperation(tab->getName());
1333     pOp->deleteTuple();
1334     tmp.equalForRow(pOp, loops);
1335 
1336     // Define attributes to read
1337     for(a = 0; a<tab->getNoOfColumns(); a++)
1338     {
1339       if((row.attributeStore(a) = pOp->getValue(tab->getColumn(a)->getName())) == 0) {
1340 	ERR(pTrans->getNdbError());
1341 	return NDBT_FAILED;
1342       }
1343     }
1344 
1345     pTrans->execute(Commit);
1346     pTrans->close();
1347 
1348     pTrans = pNdb->startTransaction();
1349     pOp = pTrans->getNdbOperation(tab->getName());
1350     pOp->insertTuple();
1351     tmp.setValues(pOp, loops, 0);
1352 
1353     pOp = pTrans->getNdbOperation(tab->getName());
1354     pOp->deleteTuple();
1355     tmp.equalForRow(pOp, loops);
1356     for(a = 0; a<tab->getNoOfColumns(); a++)
1357     {
1358       if((row.attributeStore(a) = pOp->getValue(tab->getColumn(a)->getName())) == 0)
1359       {
1360 	ERR(pTrans->getNdbError());
1361 	return NDBT_FAILED;
1362       }
1363     }
1364     if (pTrans->execute(Commit) != 0)
1365     {
1366       ERR(pTrans->getNdbError());
1367       return NDBT_FAILED;
1368     }
1369 
1370     pTrans->close();
1371   }
1372 
1373   return NDBT_OK;
1374 }
1375 
1376 int
runBug27756(NDBT_Context * ctx,NDBT_Step * step)1377 runBug27756(NDBT_Context* ctx, NDBT_Step* step)
1378 {
1379 
1380   Ndb* pNdb = GETNDB(step);
1381   //NdbDictionary::Dictionary * dict = pNdb->getDictionary();
1382 
1383   HugoOperations ops(*ctx->getTab());
1384 
1385   int loops = ctx->getNumLoops();
1386   //const int rows = ctx->getNumRecords();
1387 
1388   Vector<Uint64> copies;
1389   while (loops--)
1390   {
1391     ops.startTransaction(pNdb);
1392     ops.pkInsertRecord(pNdb, 1, 1);
1393     ops.execute_NoCommit(pNdb);
1394 
1395     NdbTransaction* pTrans = ops.getTransaction();
1396     NdbOperation* op = pTrans->getNdbOperation(ctx->getTab()->getName());
1397     op->interpretedUpdateTuple();
1398     ops.equalForRow(op, 1);
1399     NdbRecAttr* attr = op->getValue(NdbDictionary::Column::COPY_ROWID);
1400     ops.execute_NoCommit(pNdb);
1401 
1402     copies.push_back(attr->u_64_value());
1403     ndbout_c("copy at: %llx", copies.back());
1404     ops.execute_NoCommit(pNdb);
1405 
1406     ops.pkDeleteRecord(pNdb, 1, 1);
1407     ops.execute_NoCommit(pNdb);
1408 
1409     if (loops & 1)
1410     {
1411       ops.execute_Rollback(pNdb);
1412       ops.closeTransaction(pNdb);
1413     }
1414     else
1415     {
1416       ops.execute_Commit(pNdb);
1417       ops.closeTransaction(pNdb);
1418       ops.clearTable(pNdb, 100);
1419     }
1420   }
1421 
1422   for (Uint32 i = 0; i<copies.size(); i++)
1423     if (copies[i] != copies.back())
1424     {
1425       ndbout_c("Memleak detected");
1426       return NDBT_FAILED;
1427     }
1428 
1429   return NDBT_OK;
1430 }
1431 
1432 int
runBug28073(NDBT_Context * ctx,NDBT_Step * step)1433 runBug28073(NDBT_Context *ctx, NDBT_Step* step)
1434 {
1435   int result = NDBT_OK;
1436   const NdbDictionary::Table *table= ctx->getTab();
1437   HugoOperations hugoOp1(*table);
1438   HugoOperations hugoOp2(*table);
1439   Ndb* pNdb = GETNDB(step);
1440   int loops = ctx->getNumLoops();
1441   bool inserted= false;
1442 
1443   while (loops--)
1444   {
1445     if (!inserted)
1446     {
1447       CHECK(hugoOp1.startTransaction(pNdb) == 0);
1448       CHECK(hugoOp1.pkInsertRecord(pNdb, 1, 1) == 0);
1449       CHECK(hugoOp1.execute_Commit(pNdb) == 0);
1450       CHECK(hugoOp1.closeTransaction(pNdb) == 0);
1451       inserted= 1;
1452     }
1453 
1454     // Use TC hint to hit the same node in both transactions.
1455     Uint32 key_val= 0;
1456     const char *key= (const char *)(&key_val);
1457     CHECK(hugoOp1.startTransaction(pNdb, table, key, 4) == 0);
1458     CHECK(hugoOp2.startTransaction(pNdb, table, key, 4) == 0);
1459 
1460     // First take 2*read lock on the tuple in transaction 1.
1461     for (Uint32 i= 0; i < 2; i++)
1462     {
1463       CHECK(hugoOp1.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
1464       CHECK(hugoOp1.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
1465     }
1466     CHECK(hugoOp1.execute_NoCommit(pNdb) == 0);
1467 
1468     // Now send ops in two transactions, one batch.
1469     // First 2*read in transaction 2.
1470     for (Uint32 i= 0; i < 2; i++)
1471     {
1472       CHECK(hugoOp2.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
1473       CHECK(hugoOp2.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
1474     }
1475     CHECK(hugoOp2.execute_async_prepare(pNdb, NdbTransaction::NoCommit) == 0);
1476 
1477     // Second op an update in transaction 1.
1478     CHECK(hugoOp1.pkUpdateRecord(pNdb, 1, 1) == 0);
1479     CHECK(hugoOp1.execute_async_prepare(pNdb, NdbTransaction::Commit) == 0);
1480 
1481     // Transaction 1 will now hang waiting on transaction 2 to commit before it
1482     // can upgrade its read lock to a write lock.
1483     // With the bug, we get a node failure due to watchdog timeout here.
1484     CHECK(hugoOp2.wait_async(pNdb) == 0);
1485 
1486     // Now commit transaction 2, we should see transaction 1 finish with the
1487     // update.
1488     CHECK(hugoOp2.execute_async_prepare(pNdb, NdbTransaction::Commit) == 0);
1489     CHECK(hugoOp2.wait_async(pNdb) == 0);
1490     // No error check, as transaction 1 may have terminated already.
1491     hugoOp1.wait_async(pNdb);
1492 
1493     CHECK(hugoOp1.closeTransaction(pNdb) == 0);
1494     CHECK(hugoOp2.closeTransaction(pNdb) == 0);
1495   }
1496 
1497   return result;
1498 }
1499 
1500 int
runBug20535(NDBT_Context * ctx,NDBT_Step * step)1501 runBug20535(NDBT_Context* ctx, NDBT_Step* step)
1502 {
1503   Ndb* pNdb = GETNDB(step);
1504   const NdbDictionary::Table * tab = ctx->getTab();
1505 
1506   bool hasDefault = false;
1507   for (Uint32 i = 0; i<(Uint32)tab->getNoOfColumns(); i++)
1508   {
1509     if (tab->getColumn(i)->getNullable() ||
1510         tab->getColumn(i)->getDefaultValue())
1511     {
1512       hasDefault = true;
1513       break;
1514     }
1515   }
1516 
1517   if (!hasDefault)
1518     return NDBT_OK;
1519 
1520   HugoTransactions hugoTrans(* tab);
1521   hugoTrans.loadTable(pNdb, 1);
1522 
1523   NdbTransaction* pTrans = pNdb->startTransaction();
1524   NdbOperation* pOp = pTrans->getNdbOperation(tab->getName());
1525   pOp->deleteTuple();
1526   hugoTrans.equalForRow(pOp, 0);
1527   if (pTrans->execute(NoCommit) != 0)
1528     return NDBT_FAILED;
1529 
1530   pOp = pTrans->getNdbOperation(tab->getName());
1531   pOp->insertTuple();
1532   hugoTrans.equalForRow(pOp, 0);
1533   for (Uint32 i = 0; i<(Uint32)tab->getNoOfColumns(); i++)
1534   {
1535     if (!tab->getColumn(i)->getPrimaryKey() &&
1536         !tab->getColumn(i)->getNullable() &&
1537         !tab->getColumn(i)->getDefaultValue())
1538     {
1539       hugoTrans.setValueForAttr(pOp, i, 0, 1);
1540     }
1541   }
1542 
1543   if (pTrans->execute(Commit) != 0)
1544     return NDBT_FAILED;
1545 
1546   pTrans->close();
1547 
1548   pTrans = pNdb->startTransaction();
1549   pOp = pTrans->getNdbOperation(tab->getName());
1550   pOp->readTuple();
1551   hugoTrans.equalForRow(pOp, 0);
1552   Vector<NdbRecAttr*> values;
1553   for (Uint32 i = 0; i<(Uint32)tab->getNoOfColumns(); i++)
1554   {
1555     if (!tab->getColumn(i)->getPrimaryKey() &&
1556         (tab->getColumn(i)->getNullable() ||
1557          tab->getColumn(i)->getDefaultValue()))
1558     {
1559       values.push_back(pOp->getValue(i));
1560     }
1561   }
1562 
1563   if (pTrans->execute(Commit) != 0)
1564     return NDBT_FAILED;
1565 
1566   bool defaultOk = true;
1567   for (unsigned int i = 0; i<values.size(); i++)
1568   {
1569     const NdbRecAttr* recAttr = values[i];
1570     const NdbDictionary::Column* col = recAttr->getColumn();
1571     unsigned int defaultLen = 0;
1572     const char* def = (const char*) col->getDefaultValue(&defaultLen);
1573 
1574     if (def)
1575     {
1576       /* Column has a native default, check that it was set */
1577 
1578       if (!recAttr->isNULL())
1579       {
1580         if (memcmp(def, recAttr->aRef(), defaultLen) != 0)
1581         {
1582           defaultOk = false;
1583           ndbout_c("column %s does not have correct default value",
1584                    recAttr->getColumn()->getName());
1585         }
1586       }
1587       else
1588       {
1589         defaultOk = false;
1590         ndbout_c("column %s is null, should have default value",
1591                  recAttr->getColumn()->getName());
1592       }
1593     }
1594     else
1595     {
1596       /* Column has Null as its default */
1597       if (!recAttr->isNULL())
1598       {
1599         defaultOk = false;
1600         ndbout_c("column %s is not NULL", recAttr->getColumn()->getName());
1601       }
1602     }
1603   }
1604 
1605   pTrans->close();
1606 
1607   if (defaultOk)
1608     return NDBT_OK;
1609   else
1610     return NDBT_FAILED;
1611 }
1612 
1613 
1614 int
runDDInsertFailUpdateBatch(NDBT_Context * ctx,NDBT_Step * step)1615 runDDInsertFailUpdateBatch(NDBT_Context* ctx, NDBT_Step* step)
1616 {
1617   Ndb* pNdb = GETNDB(step);
1618   NdbRestarter restarter;
1619 
1620   const NdbDictionary::Table * tab = ctx->getTab();
1621 
1622   int errCode = 0;
1623   int expectedError = 0;
1624   {
1625     bool tabHasDD = false;
1626     for(int i = 0; i<tab->getNoOfColumns(); i++)
1627     {
1628       tabHasDD |= (tab->getColumn(i)->getStorageType() ==
1629                    NdbDictionary::Column::StorageTypeDisk);
1630     }
1631 
1632     if (tabHasDD)
1633     {
1634       errCode = 4021;
1635       expectedError = 1601;
1636     }
1637     else
1638     {
1639       NdbDictionary::Dictionary::List l;
1640       pNdb->getDictionary()->listIndexes(l, tab->getName());
1641       for (Uint32 i = 0; i<l.count; i++)
1642       {
1643         if (DictTabInfo::isOrderedIndex(l.elements[i].type))
1644         {
1645           errCode = 4023;
1646           expectedError = 9999;
1647           break;
1648         }
1649       }
1650     }
1651 
1652     if (errCode == 0)
1653     {
1654       ndbout_c("Table %s has no disk attributes or ordered indexes, skipping",
1655                tab->getName());
1656       return NDBT_OK;
1657     }
1658   }
1659 
1660   HugoOperations hugoOps(*ctx->getTab());
1661 
1662   int result = NDBT_OK;
1663 
1664   for (Uint32 loop = 0; loop < 100; loop ++)
1665   {
1666     restarter.insertErrorInAllNodes(errCode);
1667     CHECK(hugoOps.startTransaction(pNdb) == 0);
1668 
1669     /* Create batch with insert op (which will fail due to disk allocation issue)
1670      * followed by update op on same pk
1671      * Transaction will abort due to insert failure, and reason should be
1672      * disk space exhaustion, not any issue with the update.
1673      */
1674     CHECK(hugoOps.pkInsertRecord(pNdb, loop, 1, 0) == 0);
1675 
1676     /* Add up to 16 updates after the insert */
1677     Uint32 numUpdates = 1 + (loop % 15);
1678     for (Uint32 updateCnt = 0; updateCnt < numUpdates; updateCnt++)
1679       CHECK(hugoOps.pkUpdateRecord(pNdb, loop, 1, 1+updateCnt) == 0);
1680 
1681     CHECK(hugoOps.execute_Commit(pNdb) != 0); /* Expect failure */
1682 
1683     NdbError err= hugoOps.getTransaction()->getNdbError();
1684 
1685     CHECK(err.code == expectedError);
1686 
1687     hugoOps.closeTransaction(pNdb);
1688   }
1689 
1690   restarter.insertErrorInAllNodes(0);
1691 
1692   return result;
1693 }
1694 
1695 // Bug34348
1696 
1697 #define chk1(b) \
1698   if (!(b)) { g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ << endl; result = NDBT_FAILED; continue; }
1699 #define chk2(b, e) \
1700   if (!(b)) { g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ << ": " << e << endl; result = NDBT_FAILED; continue; }
1701 
1702 const char* tabname_bug34348 = "TBug34348";
1703 
1704 int
runBug34348insert(NDBT_Context * ctx,NDBT_Step * step,HugoOperations & ops,int i,bool * rangeFull)1705 runBug34348insert(NDBT_Context* ctx, NDBT_Step* step,
1706                   HugoOperations& ops, int i, bool* rangeFull)
1707 {
1708   const int rangeFullError = 633;
1709   Ndb* pNdb = GETNDB(step);
1710   int result = NDBT_OK;
1711   while (result == NDBT_OK)
1712   {
1713     int code = 0;
1714     chk2(ops.startTransaction(pNdb) == 0, ops.getNdbError());
1715     chk2(ops.pkInsertRecord(pNdb, i, 1) == 0, ops.getNdbError());
1716     chk2(ops.execute_Commit(pNdb) == 0 || (code = ops.getNdbError().code) == rangeFullError, ops.getNdbError());
1717     ops.closeTransaction(pNdb);
1718     *rangeFull = (code == rangeFullError);
1719     break;
1720   }
1721   return result;
1722 }
1723 
1724 int
runBug34348delete(NDBT_Context * ctx,NDBT_Step * step,HugoOperations & ops,int i)1725 runBug34348delete(NDBT_Context* ctx, NDBT_Step* step,
1726                   HugoOperations& ops, int i)
1727 {
1728   Ndb* pNdb = GETNDB(step);
1729   int result = NDBT_OK;
1730   while (result == NDBT_OK)
1731   {
1732     chk2(ops.startTransaction(pNdb) == 0, ops.getNdbError());
1733     chk2(ops.pkDeleteRecord(pNdb, i, 1) == 0, ops.getNdbError());
1734     chk2(ops.execute_Commit(pNdb) == 0, ops.getNdbError());
1735     ops.closeTransaction(pNdb);
1736     break;
1737   }
1738   return result;
1739 }
1740 
1741 int
runBug34348(NDBT_Context * ctx,NDBT_Step * step)1742 runBug34348(NDBT_Context* ctx, NDBT_Step* step)
1743 {
1744   myRandom48Init((long)NdbTick_CurrentMillisecond());
1745   Ndb* pNdb = GETNDB(step);
1746   NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
1747   NdbRestarter restarter;
1748   int result = NDBT_OK;
1749   const int loops = ctx->getNumLoops();
1750   const int errInsDBACC = 3002;
1751   const int errInsCLEAR = 0;
1752   Uint32* rowmask = 0;
1753 
1754   while (result == NDBT_OK)
1755   {
1756     chk1(restarter.insertErrorInAllNodes(errInsDBACC) == 0);
1757     ndbout << "error insert " << errInsDBACC << " done" << endl;
1758 
1759     const NdbDictionary::Table* pTab = 0;
1760     while (result == NDBT_OK)
1761     {
1762       (void)pDict->dropTable(tabname_bug34348);
1763       NdbDictionary::Table tab(tabname_bug34348);
1764       {
1765         NdbDictionary::Column col("a");
1766         col.setType(NdbDictionary::Column::Unsigned);
1767         col.setPrimaryKey(true);
1768         tab.addColumn(col);
1769       }
1770       {
1771         NdbDictionary::Column col("b");
1772         col.setType(NdbDictionary::Column::Unsigned);
1773         col.setNullable(false);
1774         tab.addColumn(col);
1775       }
1776       chk2(pDict->createTable(tab) == 0, pDict->getNdbError());
1777       chk2((pTab = pDict->getTable(tabname_bug34348)) != 0, pDict->getNdbError());
1778       break;
1779     }
1780 
1781     HugoOperations ops(*pTab);
1782     ops.setQuiet();
1783 
1784     int rowmaxprev = 0;
1785     int loop = 0;
1786     while (result == NDBT_OK && loop < loops)
1787     {
1788       ndbout << "loop:" << loop << endl;
1789       int rowcnt = 0;
1790 
1791       // fill up
1792       while (result == NDBT_OK)
1793       {
1794         bool rangeFull;
1795         chk1(runBug34348insert(ctx, step, ops, rowcnt, &rangeFull) == NDBT_OK);
1796         if (rangeFull)
1797         {
1798           // 360449 (1 fragment)
1799           ndbout << "dir range full at " << rowcnt << endl;
1800           break;
1801         }
1802         rowcnt++;
1803       }
1804       chk1(result == NDBT_OK);
1805       const int rowmax = rowcnt;
1806 
1807       if (loop == 0)
1808         rowmaxprev = rowmax;
1809       else
1810         chk2(rowmaxprev == rowmax, "rowmaxprev:" << rowmaxprev << " rowmax:" << rowmax);
1811 
1812       const int sz = (rowmax + 31) / 32;
1813       delete [] rowmask;
1814       rowmask = new Uint32 [sz];
1815       BitmaskImpl::clear(sz, rowmask);
1816       {
1817         int i;
1818         for (i = 0; i < rowmax; i++)
1819           BitmaskImpl::set(sz, rowmask, i);
1820       }
1821 
1822       // random delete until insert succeeds
1823       while (result == NDBT_OK)
1824       {
1825         int i = myRandom48(rowmax);
1826         if (!BitmaskImpl::get(sz, rowmask, i))
1827           continue;
1828         chk1(runBug34348delete(ctx, step, ops, i) == NDBT_OK);
1829         BitmaskImpl::clear(sz, rowmask, i);
1830         rowcnt--;
1831         bool rangeFull;
1832         chk1(runBug34348insert(ctx, step, ops, rowmax, &rangeFull) == NDBT_OK);
1833         if (!rangeFull)
1834         {
1835           chk1(runBug34348delete(ctx, step, ops, rowmax) == NDBT_OK);
1836           // 344063 (1 fragment)
1837           ndbout << "dir range released at " << rowcnt << endl;
1838           break;
1839         }
1840       }
1841       chk1(result == NDBT_OK);
1842       assert(BitmaskImpl::count(sz, rowmask)== (Uint32)rowcnt);
1843 
1844       // delete about 1/2 remaining
1845       while (result == NDBT_OK)
1846       {
1847         int i;
1848         for (i = 0; result == NDBT_OK && i < rowmax; i++)
1849         {
1850           if (!BitmaskImpl::get(sz, rowmask, i))
1851             continue;
1852           if (myRandom48(100) < 50)
1853             continue;
1854           chk1(runBug34348delete(ctx, step, ops, i) == NDBT_OK);
1855           BitmaskImpl::clear(sz, rowmask, i);
1856           rowcnt--;
1857         }
1858         ndbout << "deleted down to " << rowcnt << endl;
1859         break;
1860       }
1861       chk1(result == NDBT_OK);
1862       assert(BitmaskImpl::count(sz, rowmask)== (Uint32)rowcnt);
1863 
1864       // insert until full again
1865       while (result == NDBT_OK)
1866       {
1867         int i;
1868         for (i = 0; result == NDBT_OK && i < rowmax; i++)
1869         {
1870           if (BitmaskImpl::get(sz, rowmask, i))
1871             continue;
1872           bool rangeFull;
1873           chk1(runBug34348insert(ctx, step, ops, i, &rangeFull) == NDBT_OK);
1874           // assume all can be inserted back
1875           chk2(!rangeFull, "dir range full too early at " << rowcnt);
1876           BitmaskImpl::set(sz, rowmask, i);
1877           rowcnt++;
1878         }
1879         chk1(result == NDBT_OK);
1880         ndbout << "inserted all back to " << rowcnt << endl;
1881         break;
1882       }
1883       chk1(result == NDBT_OK);
1884       assert(BitmaskImpl::count(sz, rowmask)== (Uint32)rowcnt);
1885 
1886       // delete all
1887       while (result == NDBT_OK)
1888       {
1889         int i;
1890         for (i = 0; result == NDBT_OK && i < rowmax; i++)
1891         {
1892           if (!BitmaskImpl::get(sz, rowmask, i))
1893             continue;
1894           chk1(runBug34348delete(ctx, step, ops, i) == NDBT_OK);
1895           BitmaskImpl::clear(sz, rowmask, i);
1896           rowcnt--;
1897         }
1898         ndbout << "deleted all" << endl;
1899         break;
1900       }
1901       chk1(result == NDBT_OK);
1902       assert(BitmaskImpl::count(sz, rowmask)== (Uint32)rowcnt);
1903       assert(rowcnt == 0);
1904 
1905       loop++;
1906     }
1907 
1908     chk2(pDict->dropTable(tabname_bug34348) == 0, pDict->getNdbError());
1909 
1910     chk1(restarter.insertErrorInAllNodes(errInsCLEAR) == 0);
1911     ndbout << "error insert clear done" << endl;
1912     break;
1913   }
1914 
1915   if (result != NDBT_OK && restarter.insertErrorInAllNodes(errInsCLEAR) != 0)
1916     g_err << "error insert clear failed" << endl;
1917 
1918   delete [] rowmask;
1919   rowmask = 0;
1920   return result;
1921 }
1922 
1923 #define check(b, e) \
1924   if (!(b)) { g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ << ": " << e.getNdbError() << endl; return NDBT_FAILED; }
1925 
runUnlocker(NDBT_Context * ctx,NDBT_Step * step)1926 int runUnlocker(NDBT_Context* ctx, NDBT_Step* step){
1927   int loops = ctx->getNumLoops();
1928   int records = ctx->getNumRecords();
1929   int batchSize = ctx->getProperty("Batchsize", 1);
1930   int doubleUnlock = ctx->getProperty("DoubleUnlock", (Uint32)0);
1931   int lm = ctx->getProperty("LockMode", NdbOperation::LM_Read);
1932   int i = 0;
1933   HugoOperations hugoOps(*ctx->getTab());
1934   Ndb* ndb = GETNDB(step);
1935 
1936   g_err << "Unlocker : ";
1937   g_err << "Loops = " << loops << " Records = " << records << " Batchsize = "
1938         << batchSize << endl;
1939 
1940   while(i++ < loops)
1941   {
1942     g_err << i << " ";
1943 
1944     check(hugoOps.startTransaction(ndb) == 0, (*ndb));
1945 
1946     const int maxRetries = 10;
1947     int retryAttempt = 0;
1948     int r = records;
1949     Vector<const NdbLockHandle*> lockHandles;
1950 
1951     while(r > 0)
1952     {
1953       int batchContents = MIN(r, batchSize);
1954 
1955       check(hugoOps.pkReadRecordLockHandle(ndb,
1956                                            lockHandles,
1957                                            records - r,
1958                                            batchContents,
1959                                            (NdbOperation::LockMode)lm) == 0,
1960             hugoOps);
1961 
1962       r-= batchContents;
1963 
1964       if (hugoOps.execute_NoCommit(ndb) != 0)
1965       {
1966         NdbError err = hugoOps.getNdbError();
1967         if ((err.status == NdbError::TemporaryError) &&
1968             retryAttempt < maxRetries){
1969           ERR(err);
1970           NdbSleep_MilliSleep(50);
1971           retryAttempt++;
1972           lockHandles.clear();
1973           check(hugoOps.closeTransaction(ndb) == 0,
1974                 hugoOps);
1975           check(hugoOps.startTransaction(ndb) == 0, (*ndb));
1976           continue;
1977         }
1978         ERR(err);
1979         return NDBT_FAILED;
1980       }
1981 
1982       check(hugoOps.pkUnlockRecord(ndb,
1983                                   lockHandles) == 0,
1984             hugoOps);
1985 
1986       check(hugoOps.execute_NoCommit(ndb) == 0,
1987             hugoOps);
1988 
1989       if (doubleUnlock)
1990       {
1991         NdbOperation::AbortOption ao;
1992         switch(rand() % 2)
1993         {
1994         case 0:
1995           ao = NdbOperation::AbortOnError;
1996           break;
1997         case 1:
1998         default:
1999           ao = NdbOperation::AO_IgnoreError;
2000           break;
2001         }
2002 
2003         g_err << "Double unlock, abort option is "
2004               << ao << endl;
2005 
2006         /* Failure scenario */
2007         check(hugoOps.pkUnlockRecord(ndb,
2008                                      lockHandles,
2009                                      0,    // offset
2010                                      ~(0), // NumRecords
2011                                      ao) == 0,
2012               hugoOps);
2013 
2014         check(hugoOps.execute_NoCommit(ndb,
2015                                        DefaultAbortOption) != 0,
2016               hugoOps);
2017 
2018         /* 417 = Bad operation reference */
2019         check(hugoOps.getNdbError().code == 417,
2020               hugoOps);
2021 
2022 
2023         if (ao == NdbOperation::AbortOnError)
2024         {
2025           /* Restart transaction and continue with next loop iteration */
2026           r = 0;
2027           lockHandles.clear();
2028           check(hugoOps.closeTransaction(ndb) == 0,
2029                 hugoOps);
2030           check(hugoOps.startTransaction(ndb) == 0, (*ndb));
2031 
2032           continue;
2033         }
2034         /* Otherwise, IgnoreError, so let's attempt to
2035          * continue
2036          */
2037       }
2038 
2039       check(hugoOps.releaseLockHandles(ndb,
2040                                        lockHandles) == 0,
2041             hugoOps);
2042 
2043       lockHandles.clear();
2044     }
2045 
2046     switch(rand() % 3)
2047     {
2048     case 0:
2049       check(hugoOps.execute_Commit(ndb) == 0,
2050             hugoOps);
2051       break;
2052     case 1:
2053       check(hugoOps.execute_Rollback(ndb) == 0,
2054             hugoOps);
2055       break;
2056     default:
2057       /* Do nothing, just close */
2058       break;
2059     }
2060 
2061     check(hugoOps.closeTransaction(ndb) == 0,
2062           hugoOps);
2063 
2064   }
2065 
2066   g_err << endl;
2067 
2068   return NDBT_OK;
2069 }
2070 
2071 template class Vector<NdbRecAttr*>;
2072 
2073 int
runBug54986(NDBT_Context * ctx,NDBT_Step * step)2074 runBug54986(NDBT_Context* ctx, NDBT_Step* step)
2075 {
2076   NdbRestarter restarter;
2077   Ndb* pNdb = GETNDB(step);
2078   NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
2079   const NdbDictionary::Table * pTab = ctx->getTab();
2080   NdbDictionary::Table copy = *pTab;
2081 
2082   BaseString name;
2083   name.assfmt("%s_COPY", copy.getName());
2084   copy.setName(name.c_str());
2085   pDict->createTable(copy);
2086   const NdbDictionary::Table * copyTab = pDict->getTable(copy.getName());
2087 
2088   HugoTransactions hugoTrans(*pTab);
2089   hugoTrans.loadTable(pNdb, 20);
2090   hugoTrans.clearTable(pNdb);
2091 
2092   const Uint32 rows = 5000;
2093 
2094   HugoTransactions hugoTransCopy(*copyTab);
2095   hugoTransCopy.loadTable(pNdb, rows);
2096 
2097   {
2098     restarter.getNumDbNodes(); // connect
2099     int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_CHECKPOINT, 0 };
2100     NdbLogEventHandle handle =
2101       ndb_mgm_create_logevent_handle(restarter.handle, filter);
2102     for (Uint32 i = 0; i<3; i++)
2103     {
2104       int dump[] = { DumpStateOrd::DihStartLcpImmediately };
2105 
2106       struct ndb_logevent event;
2107 
2108       restarter.dumpStateAllNodes(dump, 1);
2109       while(ndb_logevent_get_next(handle, &event, 0) >= 0 &&
2110             event.type != NDB_LE_LocalCheckpointStarted);
2111       while(ndb_logevent_get_next(handle, &event, 0) >= 0 &&
2112             event.type != NDB_LE_LocalCheckpointCompleted);
2113     }
2114     ndb_mgm_destroy_logevent_handle(&handle);
2115   }
2116 
2117   for (int i = 0; i<5; i++)
2118   {
2119     int val1 = DumpStateOrd::DihMaxTimeBetweenLCP;
2120     int val2 = 7099; // Force start
2121 
2122     restarter.dumpStateAllNodes(&val1, 1);
2123     int val[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
2124     restarter.dumpStateAllNodes(val, 2);
2125 
2126     restarter.insertErrorInAllNodes(932); // prevent arbit shutdown
2127 
2128     HugoTransactions hugoTrans(*pTab);
2129     hugoTrans.loadTable(pNdb, 20);
2130 
2131     restarter.dumpStateAllNodes(&val2, 1);
2132 
2133     NdbSleep_SecSleep(15);
2134     hugoTrans.clearTable(pNdb);
2135 
2136     hugoTransCopy.pkReadRecords(pNdb, rows);
2137 
2138     HugoOperations hugoOps(*pTab);
2139     hugoOps.startTransaction(pNdb);
2140     hugoOps.pkInsertRecord(pNdb, 1);
2141     hugoOps.execute_NoCommit(pNdb);
2142 
2143     restarter.insertErrorInAllNodes(5056);
2144     restarter.dumpStateAllNodes(&val2, 1);
2145     restarter.waitClusterNoStart();
2146     int vall = 11009;
2147     restarter.dumpStateAllNodes(&vall, 1);
2148     restarter.startAll();
2149     restarter.waitClusterStarted();
2150   }
2151 
2152   pDict->dropTable(copy.getName());
2153 
2154   // remove 25-page pgman
2155   restarter.restartAll(false, true, true);
2156   restarter.waitClusterNoStart();
2157   restarter.startAll();
2158   restarter.waitClusterStarted();
2159   return NDBT_OK;
2160 }
2161 
2162 int
runBug54944(NDBT_Context * ctx,NDBT_Step * step)2163 runBug54944(NDBT_Context* ctx, NDBT_Step* step)
2164 {
2165   Ndb* pNdb = GETNDB(step);
2166   const NdbDictionary::Table * pTab = ctx->getTab();
2167   NdbRestarter res;
2168 
2169   for (Uint32 i = 0; i<5; i++)
2170   {
2171     Uint32 rows = 5000 + i * 2000;
2172     HugoOperations hugoOps(*pTab);
2173     hugoOps.startTransaction(pNdb);
2174 
2175     for (Uint32 r = 0; r < rows; r++)
2176     {
2177       for (Uint32 b = 0; b<100; b++, r++)
2178       {
2179         hugoOps.pkInsertRecord(pNdb, r);
2180       }
2181       hugoOps.execute_NoCommit(pNdb);
2182     }
2183 
2184     res.insertErrorInAllNodes(8087);
2185 
2186     HugoTransactions hugoTrans(*pTab);
2187     hugoTrans.loadTableStartFrom(pNdb, 50000, 100);
2188 
2189     hugoOps.execute_Rollback(pNdb);
2190     hugoTrans.clearTable(pNdb);
2191 
2192     res.insertErrorInAllNodes(0);
2193   }
2194   return NDBT_OK;
2195 }
2196 
2197 int
runBug59496_scan(NDBT_Context * ctx,NDBT_Step * step)2198 runBug59496_scan(NDBT_Context* ctx, NDBT_Step* step)
2199 {
2200   Ndb* pNdb = GETNDB(step);
2201   const NdbDictionary::Table * pTab = ctx->getTab();
2202   NdbRestarter res;
2203   int rowcount = ctx->getProperty("CHECK_ROWCOUNT", Uint32(0));
2204   int records = ctx->getNumRecords();
2205   if (rowcount == 0)
2206     records = 0;
2207 
2208   HugoTransactions hugoTrans(*pTab);
2209   while (!ctx->isTestStopped())
2210   {
2211     if (hugoTrans.scanReadRecords(pNdb,
2212                                   records, 0, 0,
2213                                   NdbOperation::LM_CommittedRead,
2214                                   (int)NdbScanOperation::SF_TupScan) != NDBT_OK)
2215       return NDBT_FAILED;
2216   }
2217   return NDBT_OK;
2218 }
2219 
2220 int
runBug59496_case1(NDBT_Context * ctx,NDBT_Step * step)2221 runBug59496_case1(NDBT_Context* ctx, NDBT_Step* step)
2222 {
2223   Ndb* pNdb = GETNDB(step);
2224   NdbRestarter res;
2225 
2226   int loops = ctx->getNumLoops();
2227   int records = ctx->getNumRecords();
2228 
2229   HugoOperations hugoOps(*ctx->getTab());
2230   for (int i = 0; i < loops; i++)
2231   {
2232     hugoOps.startTransaction(pNdb);
2233     hugoOps.pkInsertRecord(pNdb, 0, records, 0);
2234     hugoOps.execute_NoCommit(pNdb);
2235     hugoOps.pkUpdateRecord(pNdb, 0, records, rand());
2236     hugoOps.execute_NoCommit(pNdb);
2237     hugoOps.pkUpdateRecord(pNdb, 0, records, rand());
2238     hugoOps.execute_NoCommit(pNdb);
2239     res.insertErrorInAllNodes(8089);
2240     hugoOps.execute_Commit(pNdb);
2241     res.insertErrorInAllNodes(0);
2242     hugoOps.closeTransaction(pNdb);
2243     hugoOps.clearTable(pNdb);
2244   }
2245   ctx->stopTest();
2246   return NDBT_OK;
2247 }
2248 
2249 int
runBug59496_case2(NDBT_Context * ctx,NDBT_Step * step)2250 runBug59496_case2(NDBT_Context* ctx, NDBT_Step* step)
2251 {
2252   Ndb* pNdb = GETNDB(step);
2253   NdbRestarter res;
2254 
2255   int loops = ctx->getNumLoops();
2256   int records = ctx->getNumRecords();
2257 
2258   HugoOperations hugoOps(*ctx->getTab());
2259   for (int i = 0; i < loops; i++)
2260   {
2261     hugoOps.startTransaction(pNdb);
2262     hugoOps.pkDeleteRecord(pNdb, 0, records);
2263     hugoOps.execute_NoCommit(pNdb);
2264     hugoOps.pkInsertRecord(pNdb, 0, records, 0);
2265     hugoOps.execute_NoCommit(pNdb);
2266 
2267     res.insertErrorInAllNodes(8089);
2268     hugoOps.execute_Rollback(pNdb);
2269     res.insertErrorInAllNodes(0);
2270 
2271     hugoOps.closeTransaction(pNdb);
2272   }
2273   ctx->stopTest();
2274   return NDBT_OK;
2275 }
2276 
2277 #define CHK_RET_FAILED(x) if (!(x)) { ndbout_c("Failed on line: %u", __LINE__); return NDBT_FAILED; }
2278 
2279 int
runTest899(NDBT_Context * ctx,NDBT_Step * step)2280 runTest899(NDBT_Context* ctx, NDBT_Step* step)
2281 {
2282   Ndb* pNdb = GETNDB(step);
2283   const NdbDictionary::Table* pTab = ctx->getTab();
2284 
2285   const int rows = ctx->getNumRecords();
2286   const int loops = ctx->getNumLoops();
2287   const int batch = ctx->getProperty("Batch", Uint32(50));
2288   const int until_stopped = ctx->getProperty("UntilStopped");
2289 
2290   const NdbRecord * pRowRecord = pTab->getDefaultRecord();
2291   CHK_RET_FAILED(pRowRecord != 0);
2292 
2293   const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
2294   Uint8 * pRow = new Uint8[len];
2295 
2296   int count_ok = 0;
2297   int count_failed = 0;
2298   int count_899 = 0;
2299   for (int i = 0; i < loops || (until_stopped && !ctx->isTestStopped()); i++)
2300   {
2301     ndbout_c("loop: %d",i);
2302     int result = 0;
2303     for (int rowNo = 0; rowNo < rows;)
2304     {
2305       NdbTransaction* pTrans = pNdb->startTransaction();
2306       CHK_RET_FAILED(pTrans != 0);
2307 
2308       for (int b = 0; rowNo < rows && b < batch; rowNo++, b++)
2309       {
2310         bzero(pRow, len);
2311 
2312         HugoCalculator calc(* pTab);
2313 
2314         NdbOperation::OperationOptions opts;
2315         bzero(&opts, sizeof(opts));
2316 
2317         const NdbOperation* pOp = 0;
2318         switch(i % 2){
2319         case 0:
2320           calc.setValues(pRow, pRowRecord, rowNo, rand());
2321           pOp = pTrans->writeTuple(pRowRecord, (char*)pRow,
2322                                    pRowRecord, (char*)pRow,
2323                                    0,
2324                                    &opts,
2325                                    sizeof(opts));
2326           result = pTrans->execute(NoCommit);
2327           break;
2328         case 1:
2329           calc.setValues(pRow, pRowRecord, rowNo, rand());
2330           pOp = pTrans->deleteTuple(pRowRecord, (char*)pRow,
2331                                     pRowRecord, (char*)pRow,
2332                                     0,
2333                                     &opts,
2334                                     sizeof(opts));
2335           result = pTrans->execute(NoCommit, AO_IgnoreError);
2336           break;
2337         }
2338 
2339         CHK_RET_FAILED(pOp != 0);
2340 
2341         if (result != 0)
2342         {
2343           goto found_error;
2344         }
2345       }
2346       result = pTrans->execute(Commit);
2347 
2348       if (result != 0)
2349       {
2350     found_error:
2351         count_failed++;
2352         NdbError err = pTrans->getNdbError();
2353         if (! (err.status == NdbError::TemporaryError ||
2354                err.classification == NdbError::NoDataFound ||
2355                err.classification == NdbError::ConstraintViolation))
2356         {
2357           ndbout << err << endl;
2358         }
2359         CHK_RET_FAILED(err.status == NdbError::TemporaryError ||
2360                        err.classification == NdbError::NoDataFound ||
2361                        err.classification == NdbError::ConstraintViolation);
2362         if (err.code == 899)
2363         {
2364           count_899++;
2365           ndbout << err << endl;
2366         }
2367       }
2368       else
2369       {
2370         count_ok++;
2371       }
2372       pTrans->close();
2373     }
2374   }
2375 
2376   ndbout_c("count_ok: %d count_failed: %d (899: %d)",
2377            count_ok, count_failed, count_899);
2378   delete [] pRow;
2379 
2380   return count_899 == 0 ? NDBT_OK : NDBT_FAILED;
2381 }
2382 
2383 int
runInit899(NDBT_Context * ctx,NDBT_Step * step)2384 runInit899(NDBT_Context* ctx, NDBT_Step* step)
2385 {
2386   NdbRestarter restarter;
2387   int val = DumpStateOrd::DihMinTimeBetweenLCP;
2388   restarter.dumpStateAllNodes(&val, 1);
2389 
2390   Ndb* pNdb = GETNDB(step);
2391   const NdbDictionary::Table* pTab = ctx->getTab();
2392   const NdbDictionary::Table * pTab2 = pNdb->getDictionary()->
2393     getTable(pTab->getName());
2394 
2395   int tableId = pTab2->getObjectId();
2396   int val2[] = { DumpStateOrd::BackupErrorInsert, 10042, tableId };
2397 
2398   for (int i = 0; i < restarter.getNumDbNodes(); i++)
2399   {
2400     if (i & 1)
2401     {
2402       int nodeId = restarter.getDbNodeId(i);
2403       ndbout_c("Setting slow LCP of table %d on node %d",
2404                tableId, nodeId);
2405       restarter.dumpStateOneNode(nodeId, val2, 3);
2406     }
2407   }
2408 
2409   return NDBT_OK;
2410 }
2411 
2412 int
runEnd899(NDBT_Context * ctx,NDBT_Step * step)2413 runEnd899(NDBT_Context* ctx, NDBT_Step* step)
2414 {
2415   // reset LCP speed
2416   NdbRestarter restarter;
2417   int val[] = { DumpStateOrd::DihMinTimeBetweenLCP, 0 };
2418   restarter.dumpStateAllNodes(val, 2);
2419 
2420   restarter.insertErrorInAllNodes(0);
2421   return NDBT_OK;
2422 }
2423 
2424 
initSubscription(NDBT_Context * ctx,NDBT_Step * step)2425 int initSubscription(NDBT_Context* ctx, NDBT_Step* step){
2426   /* Subscribe to events on the table, and put access
2427    * to the subscription somewhere handy
2428    */
2429   Ndb* pNdb = GETNDB(step);
2430   const NdbDictionary::Table& tab = *ctx->getTab();
2431   bool merge_events = false;
2432   bool report = false;
2433 
2434   char eventName[1024];
2435   sprintf(eventName,"%s_EVENT",tab.getName());
2436 
2437   NdbDictionary::Dictionary *myDict = pNdb->getDictionary();
2438 
2439   if (!myDict) {
2440     g_err << "Dictionary not found "
2441 	  << pNdb->getNdbError().code << " "
2442 	  << pNdb->getNdbError().message << endl;
2443     return NDBT_FAILED;
2444   }
2445 
2446   myDict->dropEvent(eventName);
2447 
2448   NdbDictionary::Event myEvent(eventName);
2449   myEvent.setTable(tab.getName());
2450   myEvent.addTableEvent(NdbDictionary::Event::TE_ALL);
2451   for(int a = 0; a < tab.getNoOfColumns(); a++){
2452     myEvent.addEventColumn(a);
2453   }
2454   myEvent.mergeEvents(merge_events);
2455 
2456   if (report)
2457     myEvent.setReport(NdbDictionary::Event::ER_SUBSCRIBE);
2458 
2459   int res = myDict->createEvent(myEvent); // Add event to database
2460 
2461   if (res == 0)
2462     myEvent.print();
2463   else if (myDict->getNdbError().classification ==
2464 	   NdbError::SchemaObjectExists)
2465   {
2466     g_info << "Event creation failed event exists\n";
2467     res = myDict->dropEvent(eventName);
2468     if (res) {
2469       g_err << "Failed to drop event: "
2470 	    << myDict->getNdbError().code << " : "
2471 	    << myDict->getNdbError().message << endl;
2472       return NDBT_FAILED;
2473     }
2474     // try again
2475     res = myDict->createEvent(myEvent); // Add event to database
2476     if (res) {
2477       g_err << "Failed to create event (1): "
2478 	    << myDict->getNdbError().code << " : "
2479 	    << myDict->getNdbError().message << endl;
2480       return NDBT_FAILED;
2481     }
2482   }
2483   else
2484   {
2485     g_err << "Failed to create event (2): "
2486 	  << myDict->getNdbError().code << " : "
2487 	  << myDict->getNdbError().message << endl;
2488     return NDBT_FAILED;
2489   }
2490 
2491   return NDBT_OK;
2492 }
2493 
removeSubscription(NDBT_Context * ctx,NDBT_Step * step)2494 int removeSubscription(NDBT_Context* ctx, NDBT_Step* step){
2495   /* Remove subscription created above */
2496   Ndb* pNdb = GETNDB(step);
2497   const NdbDictionary::Table& tab = *ctx->getTab();
2498 
2499   char eventName[1024];
2500   sprintf(eventName,"%s_EVENT",tab.getName());
2501 
2502   NdbDictionary::Dictionary *myDict = pNdb->getDictionary();
2503 
2504   if (!myDict) {
2505     g_err << "Dictionary not found "
2506 	  << pNdb->getNdbError().code << " "
2507 	  << pNdb->getNdbError().message << endl;
2508     return NDBT_FAILED;
2509   }
2510 
2511   myDict->dropEvent(eventName);
2512 
2513   return NDBT_OK;
2514 }
2515 
runVerifyRowCount(NDBT_Context * ctx,NDBT_Step * step)2516 int runVerifyRowCount(NDBT_Context* ctx, NDBT_Step* step)
2517 {
2518   Ndb* ndb = GETNDB(step);
2519 
2520   /* Check that number of results returned by a normal scan
2521    * and per-fragment rowcount sum are equal
2522    */
2523   Uint32 rowCountSum = 0;
2524   Uint32 rowScanCount = 0;
2525 
2526   int result = NDBT_OK;
2527   do
2528   {
2529     NdbTransaction* trans = ndb->startTransaction();
2530     CHECK(trans != NULL);
2531 
2532     NdbScanOperation* scan = trans->getNdbScanOperation(ctx->getTab());
2533     CHECK(scan != NULL);
2534 
2535     CHECK(scan->readTuples(NdbScanOperation::LM_CommittedRead) == 0);
2536 
2537     NdbInterpretedCode code;
2538 
2539     CHECK(code.interpret_exit_last_row() == 0);
2540     CHECK(code.finalise() == 0);
2541 
2542     NdbRecAttr* rowCountRA = scan->getValue(NdbDictionary::Column::ROW_COUNT);
2543     CHECK(rowCountRA != NULL);
2544     CHECK(scan->setInterpretedCode(&code) == 0);
2545 
2546     CHECK(trans->execute(NoCommit) == 0);
2547 
2548     while (scan->nextResult() == 0)
2549       rowCountSum+= rowCountRA->u_32_value();
2550 
2551     trans->close();
2552 
2553     trans = ndb->startTransaction();
2554     CHECK(trans != NULL);
2555 
2556     scan = trans->getNdbScanOperation(ctx->getTab());
2557     CHECK(scan != NULL);
2558 
2559     CHECK(scan->readTuples(NdbScanOperation::LM_CommittedRead) == 0);
2560 
2561     rowCountRA = scan->getValue(NdbDictionary::Column::ROW_COUNT);
2562     CHECK(rowCountRA != NULL);
2563 
2564     CHECK(trans->execute(NoCommit) == 0);
2565 
2566     while (scan->nextResult() == 0)
2567       rowScanCount++;
2568 
2569     trans->close();
2570   }
2571   while(0);
2572 
2573   if (result == NDBT_OK)
2574   {
2575     ndbout_c("Sum of fragment row counts : %u  Number rows scanned : %u",
2576              rowCountSum,
2577              rowScanCount);
2578 
2579     if (rowCountSum != rowScanCount)
2580     {
2581       ndbout_c("MISMATCH");
2582       result = NDBT_FAILED;
2583     }
2584   }
2585 
2586   return result;
2587 }
2588 
2589 enum ApiEventType { Insert, Update, Delete };
2590 
2591 template class Vector<ApiEventType>;
2592 
2593 struct EventInfo
2594 {
2595   ApiEventType type;
2596   int id;
2597   Uint64 gci;
2598 };
2599 template class Vector<EventInfo>;
2600 
collectEvents(Ndb * ndb,HugoCalculator & calc,const NdbDictionary::Table & tab,Vector<EventInfo> & receivedEvents,int idCol,int updateCol,Vector<NdbRecAttr * > * beforeAttrs,Vector<NdbRecAttr * > * afterAttrs)2601 int collectEvents(Ndb* ndb,
2602                   HugoCalculator& calc,
2603                   const NdbDictionary::Table& tab,
2604                   Vector<EventInfo>& receivedEvents,
2605                   int idCol,
2606                   int updateCol,
2607                   Vector<NdbRecAttr*>* beforeAttrs,
2608                   Vector<NdbRecAttr*>* afterAttrs)
2609 {
2610   int MaxTimeouts = 5;
2611   while (true)
2612   {
2613     int res = ndb->pollEvents(1000);
2614 
2615     if (res > 0)
2616     {
2617       NdbEventOperation* pOp;
2618       while ((pOp = ndb->nextEvent()))
2619       {
2620         bool isDelete = (pOp->getEventType() == NdbDictionary::Event::TE_DELETE);
2621         Vector<NdbRecAttr*>* whichVersion =
2622           isDelete?
2623           beforeAttrs :
2624           afterAttrs;
2625         int id = (*whichVersion)[idCol]->u_32_value();
2626         Uint64 gci = pOp->getGCI();
2627         Uint32 anyValue = pOp->getAnyValue();
2628         Uint32 scenario = ((anyValue >> 24) & 0xff) -1;
2629         Uint32 optype = ((anyValue >> 16) & 0xff);
2630         Uint32 recNum = (anyValue & 0xffff);
2631 
2632         g_err << "# " << receivedEvents.size()
2633               << " GCI : " << (gci >> 32)
2634               << "/"
2635               << (gci & 0xffffffff)
2636               << " id : "
2637               << id
2638               << " scenario : " << scenario
2639               << " optype : " << optype
2640               << " record : " << recNum
2641               << "  ";
2642 
2643         /* Check event has self-consistent data */
2644         int updatesValue = (*whichVersion)[updateCol]->u_32_value();
2645 
2646         if ((*whichVersion)[updateCol]->isNULL() ||
2647             (*whichVersion)[idCol]->isNULL())
2648         {
2649           g_err << "Null update/id cols : REFRESH of !EXISTS  ";
2650         }
2651 
2652         g_err << "(Updates val = " << updatesValue << ")";
2653 
2654         for (int i=0; i < (int) whichVersion->size(); i++)
2655         {
2656           /* Check PK columns and also other columns for non-delete */
2657           if (!isDelete ||
2658               tab.getColumn(i)->getPrimaryKey())
2659           {
2660             NdbRecAttr* ra = (*whichVersion)[i];
2661             if (calc.verifyRecAttr(recNum, updatesValue, ra) != 0)
2662             {
2663               g_err << "Verify failed on recNum : " << recNum << " with updates value "
2664                     << updatesValue << " for column " << ra->getColumn()->getAttrId()
2665                     << endl;
2666               return NDBT_FAILED;
2667             }
2668           }
2669         }
2670 
2671         EventInfo ei;
2672 
2673         switch (pOp->getEventType())
2674         {
2675         case NdbDictionary::Event::TE_INSERT:
2676           g_err << " Insert event" << endl;
2677           ei.type = Insert;
2678           break;
2679         case NdbDictionary::Event::TE_DELETE:
2680           ei.type = Delete;
2681           g_err << " Delete event" << endl;
2682           break;
2683         case NdbDictionary::Event::TE_UPDATE:
2684           ei.type = Update;
2685           g_err << " Update event" << endl;
2686           break;
2687         default:
2688           g_err << " Event type : " << pOp->getEventType() << endl;
2689           abort();
2690           break;
2691         }
2692 
2693         ei.id = recNum;
2694         ei.gci = gci;
2695 
2696         receivedEvents.push_back(ei);
2697       }
2698     }
2699     else
2700     {
2701       if (--MaxTimeouts == 0)
2702       {
2703         break;
2704       }
2705     }
2706   }
2707 
2708   return NDBT_OK;
2709 }
2710 
verifyEvents(const Vector<EventInfo> & receivedEvents,const Vector<ApiEventType> & expectedEvents,int records)2711 int verifyEvents(const Vector<EventInfo>& receivedEvents,
2712                  const Vector<ApiEventType>& expectedEvents,
2713                  int records)
2714 {
2715   /* Now verify received events against expected
2716    * This is messy as events occurring in the same epoch are unordered
2717    * except via id, so we use id-duplicates to determine which event
2718    * sequence we're looking at.
2719    */
2720   g_err << "Received total of " << receivedEvents.size() << " events" << endl;
2721   Vector<Uint32> keys;
2722   Vector<Uint64> gcis;
2723   Uint32 z = 0;
2724   Uint64 z2 = 0;
2725   keys.fill(records, z);
2726   gcis.fill(records, z2);
2727   Uint64 currGci = 0;
2728 
2729   for (Uint32 e=0; e < receivedEvents.size(); e++)
2730   {
2731     EventInfo ei = receivedEvents[e];
2732 
2733     if (ei.gci != currGci)
2734     {
2735       if (ei.gci < currGci)
2736         abort();
2737 
2738       /* Epoch boundary */
2739       /* At this point, all id counts must be equal */
2740       for (int i=0; i < records; i++)
2741       {
2742         if (keys[i] != keys[0])
2743         {
2744           g_err << "Count for id " << i
2745                 << " is " << keys[i]
2746                 << " but should be " << keys[0] << endl;
2747           return NDBT_OK;
2748         }
2749       }
2750 
2751       currGci = ei.gci;
2752     }
2753 
2754     Uint32 eventIndex = keys[ei.id];
2755     keys[ei.id]++;
2756 
2757     ApiEventType et = expectedEvents[eventIndex];
2758 
2759     if (ei.type != et)
2760     {
2761       g_err << "Expected event of type " << et
2762             << " but found " << ei.type
2763             << " at expectedEvent " << eventIndex
2764             << " and event num " << e << endl;
2765       return NDBT_FAILED;
2766     }
2767   }
2768 
2769   return NDBT_OK;
2770 }
2771 
runRefreshTuple(NDBT_Context * ctx,NDBT_Step * step)2772 int runRefreshTuple(NDBT_Context* ctx, NDBT_Step* step){
2773   int records = ctx->getNumRecords();
2774   Ndb* ndb = GETNDB(step);
2775 
2776   /* Now attempt to create EventOperation */
2777   NdbEventOperation* pOp;
2778   const NdbDictionary::Table& tab = *ctx->getTab();
2779 
2780   char eventName[1024];
2781   sprintf(eventName,"%s_EVENT",tab.getName());
2782 
2783   pOp = ndb->createEventOperation(eventName);
2784   if (pOp == NULL)
2785   {
2786     g_err << "Failed to create event operation\n";
2787     return NDBT_FAILED;
2788   }
2789 
2790   HugoCalculator calc(tab);
2791   Vector<NdbRecAttr*> eventAfterRecAttr;
2792   Vector<NdbRecAttr*> eventBeforeRecAttr;
2793   int updateCol = -1;
2794   int idCol = -1;
2795 
2796   /* Now request all attributes */
2797   for (int a = 0; a < tab.getNoOfColumns(); a++)
2798   {
2799     eventAfterRecAttr.push_back(pOp->getValue(tab.getColumn(a)->getName()));
2800     eventBeforeRecAttr.push_back(pOp->getPreValue(tab.getColumn(a)->getName()));
2801     if (calc.isIdCol(a))
2802       idCol = a;
2803     if (calc.isUpdateCol(a))
2804       updateCol = a;
2805   }
2806 
2807   /* Now execute the event */
2808   if (pOp->execute())
2809   {
2810     g_err << "Event operation execution failed : " << pOp->getNdbError() << endl;
2811     return NDBT_FAILED;
2812   }
2813 
2814   HugoOperations hugoOps(*ctx->getTab());
2815   int scenario = 0;
2816 
2817   Vector<ApiEventType> expectedEvents;
2818 
2819   for (scenario = 0; scenario < 2; scenario++)
2820   {
2821     g_err << "Scenario = " << scenario
2822           << " ( Refresh "
2823           << ((scenario == 0)? "before":"after")
2824           << " operations )" << endl;
2825     int optype = 0;
2826     bool done = false;
2827     int expectedError = 0;
2828     do
2829     {
2830       check(hugoOps.startTransaction(ndb) == 0, hugoOps);
2831 
2832       if (scenario == 0)
2833       {
2834         g_err << "Refresh before operations" << endl;
2835         int anyValue =
2836           ((1) << 8) |
2837           optype;
2838         check(hugoOps.pkRefreshRecord(ndb, 0, records, anyValue) == 0, hugoOps);
2839       }
2840 
2841       switch(optype)
2842       {
2843       case 0:
2844       {
2845         /* Refresh with no data present */
2846         g_err << "  Do nothing" << endl;
2847         expectedError = 0; /* Single refresh should always be fine */
2848         expectedEvents.push_back(Delete);
2849         break;
2850       }
2851       case 1:
2852       {
2853         /* [Refresh] Insert [Refresh] */
2854         g_err << "  Insert" << endl;
2855         check(hugoOps.pkInsertRecord(ndb, 0, records, 1) == 0, hugoOps);
2856         if (scenario == 0)
2857         {
2858           /* Tuple already existed error when we insert after refresh */
2859           expectedError = 630;
2860           expectedEvents.push_back(Delete);
2861         }
2862         else
2863         {
2864           expectedError = 0;
2865           expectedEvents.push_back(Insert);
2866         }
2867         /* Tuple already existed error when we insert after refresh */
2868         break;
2869       }
2870       case 2:
2871       {
2872         /* Refresh */
2873         g_err << "  Refresh" << endl;
2874         if (scenario == 0)
2875         {
2876           expectedEvents.push_back(Delete);
2877         }
2878         else
2879         {
2880           expectedEvents.push_back(Insert);
2881         }
2882         expectedError = 0;
2883         break;
2884       }
2885       case 3:
2886       {
2887         /* [Refresh] Update [Refresh] */
2888         g_err << "  Update" << endl;
2889         check(hugoOps.pkUpdateRecord(ndb, 0, records, 3) == 0, hugoOps);
2890         if (scenario == 0)
2891         {
2892           expectedError = 920;
2893           expectedEvents.push_back(Delete);
2894         }
2895         else
2896         {
2897           expectedError = 0;
2898           expectedEvents.push_back(Insert);
2899         }
2900         break;
2901       }
2902       case 4:
2903       {
2904         /* [Refresh] Delete [Refresh] */
2905         g_err << "  [Refresh] Delete [Refresh]" << endl;
2906         if (scenario == 0)
2907         {
2908           expectedError = 920;
2909           expectedEvents.push_back(Delete);
2910         }
2911         else
2912         {
2913           expectedError = 0;
2914           expectedEvents.push_back(Delete);
2915         }
2916         check(hugoOps.pkDeleteRecord(ndb, 0, records) == 0, hugoOps);
2917         break;
2918       }
2919       case 5:
2920       {
2921         g_err << "  Refresh" << endl;
2922         expectedError = 0;
2923         expectedEvents.push_back(Delete);
2924         /* Refresh with no data present */
2925         break;
2926       }
2927       case 6:
2928       {
2929         g_err << "  Double refresh" << endl;
2930         int anyValue =
2931           ((2) << 8) |
2932           optype;
2933         check(hugoOps.pkRefreshRecord(ndb, 0, records, anyValue) == 0, hugoOps);
2934         expectedError = 920; /* Row operation defined after refreshTuple() */
2935         expectedEvents.push_back(Delete);
2936       }
2937       default:
2938         done = true;
2939         break;
2940       }
2941 
2942       if (scenario == 1)
2943       {
2944         g_err << "Refresh after operations" << endl;
2945         int anyValue =
2946           ((4) << 8) |
2947           optype;
2948         check(hugoOps.pkRefreshRecord(ndb, 0, records, anyValue) == 0, hugoOps);
2949       }
2950 
2951       int rc = hugoOps.execute_Commit(ndb, AO_IgnoreError);
2952       check(rc == expectedError, hugoOps);
2953 
2954       check(hugoOps.closeTransaction(ndb) == 0, hugoOps);
2955 
2956       optype++;
2957 
2958 
2959       /* Now check fragment counts vs findable row counts */
2960       if (runVerifyRowCount(ctx, step) != NDBT_OK)
2961         return NDBT_FAILED;
2962 
2963     } while (!done);
2964   } // for scenario...
2965 
2966   /* Now check fragment counts vs findable row counts */
2967   if (runVerifyRowCount(ctx, step) != NDBT_OK)
2968     return NDBT_FAILED;
2969 
2970   /* Now let's dump and check the events */
2971   g_err << "Expecting the following sequence..." << endl;
2972   for (Uint32 i=0; i < expectedEvents.size(); i++)
2973   {
2974     g_err << i << ".  ";
2975     switch(expectedEvents[i])
2976     {
2977     case Insert:
2978       g_err << "Insert" << endl;
2979       break;
2980     case Update:
2981       g_err << "Update" << endl;
2982       break;
2983     case Delete:
2984       g_err << "Delete" << endl;
2985       break;
2986     default:
2987       abort();
2988     }
2989   }
2990 
2991   Vector<EventInfo> receivedEvents;
2992 
2993   int rc = collectEvents(ndb, calc, tab, receivedEvents, idCol, updateCol,
2994                          &eventBeforeRecAttr,
2995                          &eventAfterRecAttr);
2996   if (rc == NDBT_OK)
2997   {
2998     rc = verifyEvents(receivedEvents,
2999                       expectedEvents,
3000                       records);
3001   }
3002 
3003   if (ndb->dropEventOperation(pOp) != 0)
3004   {
3005     g_err << "Drop Event Operation failed : " << ndb->getNdbError() << endl;
3006     return NDBT_FAILED;
3007   }
3008 
3009   return rc;
3010 };
3011 
3012 enum PreRefreshOps
3013 {
3014   PR_NONE,
3015   PR_INSERT,
3016   PR_INSERTDELETE,
3017   PR_DELETE
3018 };
3019 
3020 struct RefreshScenario
3021 {
3022   const char*   name;
3023   bool          preExist;
3024   PreRefreshOps preRefreshOps;
3025 };
3026 
3027 static RefreshScenario refreshTests[] = {
3028   { "No row, No pre-ops",        false, PR_NONE         },
3029   { "No row, Insert pre-op",     false, PR_INSERT       },
3030   { "No row, Insert-Del pre-op", false, PR_INSERTDELETE },
3031   { "Row exists, No pre-ops",    true,  PR_NONE         },
3032   { "Row exists, Delete pre-op", true,  PR_DELETE       }
3033 };
3034 
3035 enum OpTypes
3036 {
3037   OP_READ_C,
3038   OP_READ_S,
3039   OP_READ_E,
3040   OP_INSERT,
3041   OP_UPDATE,
3042   OP_WRITE,
3043   OP_DELETE,
3044   OP_LAST
3045 };
3046 
3047 const char* opTypeNames[] =
3048 {
3049   "READ_C",
3050   "READ_S",
3051   "READ_E",
3052   "INSERT",
3053   "UPDATE",
3054   "WRITE",
3055   "DELETE"
3056 };
3057 
3058 
3059 int
runRefreshLocking(NDBT_Context * ctx,NDBT_Step * step)3060 runRefreshLocking(NDBT_Context* ctx, NDBT_Step* step)
3061 {
3062   /* Check that refresh in various situations has the
3063    * locks we expect it to
3064    * Scenario combinations :
3065    *   Now row pre-existing | Row pre-existing
3066    *   Trans1 : Refresh | Insert-Refresh | Insert-Delete-Refresh
3067    *            Delete-Refresh
3068    *   Trans2 : Read [Committed|Shared|Exclusive] | Insert | Update
3069    *            Write | Delete
3070    *
3071    * Expectations : Read committed  always non-blocking
3072    *                Read committed sees pre-existing row
3073    *                All other trans2 operations deadlock
3074    */
3075 
3076   Ndb* ndb = GETNDB(step);
3077   Uint32 numScenarios = sizeof(refreshTests) / sizeof(refreshTests[0]);
3078   HugoTransactions hugoTrans(*ctx->getTab());
3079 
3080   for (Uint32 s = 0; s < numScenarios; s++)
3081   {
3082     RefreshScenario& scenario = refreshTests[s];
3083 
3084     if (scenario.preExist)
3085     {
3086       /* Create pre-existing tuple */
3087       if (hugoTrans.loadTable(ndb, 1) != 0)
3088       {
3089         g_err << "Pre-exist failed : " << hugoTrans.getNdbError() << endl;
3090         return NDBT_FAILED;
3091       }
3092     }
3093 
3094     if (hugoTrans.startTransaction(ndb) != 0)
3095     {
3096       g_err << "Start trans failed : " << hugoTrans.getNdbError() << endl;
3097       return NDBT_FAILED;
3098     }
3099 
3100     g_err << "Scenario : " << scenario.name << endl;
3101 
3102     /* Do pre-refresh ops */
3103     switch (scenario.preRefreshOps)
3104     {
3105     case PR_NONE:
3106       break;
3107     case PR_INSERT:
3108     case PR_INSERTDELETE:
3109       if (hugoTrans.pkInsertRecord(ndb, 0) != 0)
3110       {
3111         g_err << "Pre insert failed : " << hugoTrans.getNdbError() << endl;
3112         return NDBT_FAILED;
3113       }
3114 
3115       if (scenario.preRefreshOps == PR_INSERT)
3116         break;
3117     case PR_DELETE:
3118       if (hugoTrans.pkDeleteRecord(ndb, 0) != 0)
3119       {
3120         g_err << "Pre delete failed : " << hugoTrans.getNdbError() << endl;
3121         return NDBT_FAILED;
3122       }
3123       break;
3124     }
3125 
3126     /* Then refresh */
3127     if (hugoTrans.pkRefreshRecord(ndb, 0) != 0)
3128     {
3129       g_err << "Refresh failed : " << hugoTrans.getNdbError() << endl;
3130       return NDBT_FAILED;
3131     }
3132 
3133     /* Now execute */
3134     if (hugoTrans.execute_NoCommit(ndb) != 0)
3135     {
3136       g_err << "Execute failed : " << hugoTrans.getNdbError() << endl;
3137       return NDBT_FAILED;
3138     }
3139 
3140     {
3141       /* Now try ops from another transaction */
3142       HugoOperations hugoOps(*ctx->getTab());
3143       Uint32 ot = OP_READ_C;
3144 
3145       while (ot < OP_LAST)
3146       {
3147         if (hugoOps.startTransaction(ndb) != 0)
3148         {
3149           g_err << "Start trans2 failed : " << hugoOps.getNdbError() << endl;
3150           return NDBT_FAILED;
3151         }
3152 
3153         g_err << "Operation type : " << opTypeNames[ot] << endl;
3154         int res = 0;
3155         switch (ot)
3156         {
3157         case OP_READ_C:
3158           res = hugoOps.pkReadRecord(ndb,0,1,NdbOperation::LM_CommittedRead);
3159           break;
3160         case OP_READ_S:
3161           res = hugoOps.pkReadRecord(ndb,0,1,NdbOperation::LM_Read);
3162           break;
3163         case OP_READ_E:
3164           res = hugoOps.pkReadRecord(ndb,0,1,NdbOperation::LM_Exclusive);
3165           break;
3166         case OP_INSERT:
3167           res = hugoOps.pkInsertRecord(ndb, 0);
3168           break;
3169         case OP_UPDATE:
3170           res = hugoOps.pkUpdateRecord(ndb, 0);
3171           break;
3172         case OP_WRITE:
3173           res = hugoOps.pkWriteRecord(ndb, 0);
3174           break;
3175         case OP_DELETE:
3176           res = hugoOps.pkDeleteRecord(ndb, 0);
3177           break;
3178         case OP_LAST:
3179           abort();
3180         }
3181 
3182         hugoOps.execute_Commit(ndb);
3183 
3184         if ((ot == OP_READ_C) && (scenario.preExist))
3185         {
3186           if (hugoOps.getNdbError().code == 0)
3187           {
3188             g_err << "Read committed succeeded" << endl;
3189           }
3190           else
3191           {
3192             g_err << "UNEXPECTED : Read committed failed. " << hugoOps.getNdbError() << endl;
3193             return NDBT_FAILED;
3194           }
3195         }
3196         else
3197         {
3198           if (hugoOps.getNdbError().code == 0)
3199           {
3200             g_err << opTypeNames[ot] << " succeeded, should not have" << endl;
3201             return NDBT_FAILED;
3202           }
3203         }
3204 
3205         hugoOps.closeTransaction(ndb);
3206 
3207         ot = ot + 1;
3208       }
3209 
3210     }
3211 
3212     /* Close refresh transaction */
3213     hugoTrans.closeTransaction(ndb);
3214 
3215     if (scenario.preExist)
3216     {
3217       /* Cleanup pre-existing before next iteration */
3218       if (hugoTrans.pkDelRecords(ndb, 0) != 0)
3219       {
3220         g_err << "Delete pre existing failed : " << hugoTrans.getNdbError() << endl;
3221         return NDBT_FAILED;
3222       }
3223     }
3224   }
3225 
3226   return NDBT_OK;
3227 }
3228 
3229 
3230 NDBT_TESTSUITE(testBasic);
3231 TESTCASE("PkInsert",
3232 	 "Verify that we can insert and delete from this table using PK"
3233 	 "NOTE! No errors are allowed!" ){
3234   INITIALIZER(runInsert);
3235   VERIFIER(runVerifyInsert);
3236 }
3237 TESTCASE("PkRead",
3238 	   "Verify that we can insert, read and delete from this table using PK"){
3239   TC_PROPERTY("LockMode", NdbOperation::LM_Read);
3240   INITIALIZER(runLoadTable);
3241   STEP(runPkRead);
3242   FINALIZER(runClearTable);
3243 }
3244 TESTCASE("PkDirtyRead",
3245 	 "Verify that we can insert, dirty read and delete from this table using PK"){
3246   TC_PROPERTY("LockMode", NdbOperation::LM_Dirty);
3247   INITIALIZER(runLoadTable);
3248   STEP(runPkRead);
3249   FINALIZER(runClearTable);
3250 }
3251 TESTCASE("PkSimpleRead",
3252 	 "Verify that we can insert, simple read and delete from this table using PK"){
3253   TC_PROPERTY("LockMode", NdbOperation::LM_SimpleRead);
3254   INITIALIZER(runLoadTable);
3255   STEP(runPkRead);
3256   FINALIZER(runClearTable);
3257 }
3258 TESTCASE("PkUpdate",
3259 	   "Verify that we can insert, update and delete from this table using PK"){
3260   INITIALIZER(runLoadTable);
3261   STEP(runPkUpdate);
3262   FINALIZER(runClearTable);
3263 }
3264 TESTCASE("PkDelete",
3265 	 "Verify that we can delete from this table using PK"){
3266   INITIALIZER(runLoadTable);
3267   STEP(runPkDelete);
3268   FINALIZER(runClearTable);
3269 }
3270 TESTCASE("UpdateAndRead",
3271 	 "Verify that we can read and update at the same time"){
3272   INITIALIZER(runLoadTable);
3273   STEP(runPkRead);
3274   STEP(runPkRead);
3275   STEP(runPkRead);
3276   STEP(runPkUpdate);
3277   STEP(runPkUpdate);
3278   STEP(runPkUpdate);
3279   FINALIZER(runClearTable);
3280 }
3281 TESTCASE("PkReadAndLocker",
3282 	 "Verify that we can read although there are "\
3283 	 " a number of 1 second locks in the table"){
3284   INITIALIZER(runLoadTable);
3285   STEP(runPkReadUntilStopped);
3286   STEP(runLocker);
3287   FINALIZER(runClearTable);
3288 }
3289 TESTCASE("PkReadAndLocker2",
3290 	 "Verify that we can read and update although there are "\
3291 	 " a number of 1 second locks in the table"){
3292   INITIALIZER(runLoadTable);
3293   STEP(runPkReadUntilStopped);
3294   STEP(runPkReadUntilStopped);
3295   STEP(runPkReadUntilStopped);
3296   STEP(runPkReadUntilStopped);
3297   STEP(runPkReadUntilStopped);
3298   STEP(runPkReadUntilStopped);
3299   STEP(runLocker);
3300   FINALIZER(runClearTable);
3301 }
3302 TESTCASE("PkReadUpdateAndLocker",
3303 	 "Verify that we can read and update although there are "\
3304 	 " a number of 1 second locks in the table"){
3305   INITIALIZER(runLoadTable);
3306   STEP(runPkReadUntilStopped);
3307   STEP(runPkReadUntilStopped);
3308   STEP(runPkUpdateUntilStopped);
3309   STEP(runPkUpdateUntilStopped);
3310   STEP(runLocker);
3311   FINALIZER(runClearTable);
3312 }
3313 TESTCASE("ReadWithLocksAndInserts",
3314 	 "TR457: This test is added to verify that an insert of a records "\
3315 	 "that is already in the database does not delete the record"){
3316   INITIALIZER(runLoadTable);
3317   STEP(runPkReadUntilStopped);
3318   STEP(runPkReadUntilStopped);
3319   STEP(runLocker);
3320   STEP(runInsertUntilStopped);
3321   FINALIZER(runClearTable);
3322 }
3323 TESTCASE("PkInsertTwice",
3324 	 "Verify that we can't insert an already inserted record."
3325 	 "Error should be returned" ){
3326   INITIALIZER(runLoadTable);
3327   STEP(runInsertTwice);
3328   FINALIZER(runClearTable);
3329 }
3330 TESTCASE("NoCommitSleep",
3331 	 "Verify what happens when a NoCommit transaction is aborted by "
3332 	 "NDB because the application is sleeping" ){
3333   INITIALIZER(runLoadTable);
3334   INITIALIZER(runNoCommitSleep);
3335   FINALIZER(runClearTable2);
3336 }
3337 TESTCASE("Commit626",
3338 	 "Verify what happens when a Commit transaction is aborted by "
3339 	 "NDB because the record does no exist" ){
3340   INITIALIZER(runClearTable2);
3341   INITIALIZER(runCommit626);
3342   FINALIZER(runClearTable2);
3343 }
3344 TESTCASE("CommitTry626",
3345 	 "Verify what happens when a Commit(TryCommit) \n"
3346 	 "transaction is aborted by "
3347 	 "NDB because the record does no exist" ){
3348   INITIALIZER(runClearTable2);
3349   INITIALIZER(runCommit_TryCommit626);
3350   FINALIZER(runClearTable2);
3351 }
3352 TESTCASE("CommitAsMuch626",
3353 	 "Verify what happens when a Commit(CommitAsMuchAsPossible) \n"
3354 	 "transaction is aborted by\n"
3355 	 "NDB because the record does no exist" ){
3356   INITIALIZER(runClearTable2);
3357   INITIALIZER(runCommit_CommitAsMuchAsPossible626);
3358   FINALIZER(runClearTable2);
3359 }
3360 TESTCASE("NoCommit626",
3361 	 "Verify what happens when a NoCommit transaction is aborted by "
3362 	 "NDB because the record does no exist" ){
3363   INITIALIZER(runClearTable2);
3364   INITIALIZER(runNoCommit626);
3365   FINALIZER(runClearTable2);
3366 }
3367 TESTCASE("NoCommitRollback626",
3368 	 "Verify what happens when a NoCommit transaction is aborted by "
3369 	 "NDB because the record does no exist and then we try to rollback\n"
3370 	 "the transaction" ){
3371   INITIALIZER(runClearTable2);
3372   INITIALIZER(runNoCommitRollback626);
3373   FINALIZER(runClearTable2);
3374 }
3375 TESTCASE("Commit630",
3376 	 "Verify what happens when a Commit transaction is aborted by "
3377 	 "NDB because the record already exist" ){
3378   INITIALIZER(runLoadTable);
3379   INITIALIZER(runCommit630);
3380   FINALIZER(runClearTable2);
3381 }
3382 TESTCASE("CommitTry630",
3383 	 "Verify what happens when a Commit(TryCommit) \n"
3384 	 "transaction is aborted by "
3385 	 "NDB because the record already exist" ){
3386   INITIALIZER(runLoadTable);
3387   INITIALIZER(runCommit_TryCommit630);
3388   FINALIZER(runClearTable2);
3389 }
3390 TESTCASE("CommitAsMuch630",
3391 	 "Verify what happens when a Commit(CommitAsMuchAsPossible) \n"
3392 	 "transaction is aborted by\n"
3393 	 "NDB because the record already exist" ){
3394   INITIALIZER(runLoadTable);
3395   INITIALIZER(runCommit_CommitAsMuchAsPossible630);
3396   FINALIZER(runClearTable2);
3397 }
3398 TESTCASE("NoCommit630",
3399 	 "Verify what happens when a NoCommit transaction is aborted by "
3400 	 "NDB because the record already exist" ){
3401   INITIALIZER(runLoadTable);
3402   INITIALIZER(runNoCommit630);
3403   FINALIZER(runClearTable2);
3404 }
3405 TESTCASE("NoCommitRollback630",
3406 	 "Verify what happens when a NoCommit transaction is aborted by "
3407 	 "NDB because the record already exist and then we try to rollback\n"
3408 	 "the transaction" ){
3409   INITIALIZER(runLoadTable);
3410   INITIALIZER(runNoCommitRollback630);
3411   FINALIZER(runClearTable2);
3412 }
3413 TESTCASE("NoCommitAndClose",
3414 	 "Verify what happens when a NoCommit transaction is closed "
3415 	 "without rolling back the transaction " ){
3416   INITIALIZER(runLoadTable);
3417   INITIALIZER(runNoCommitAndClose);
3418   FINALIZER(runClearTable2);
3419 }
3420 TESTCASE("RollbackDelete",
3421 	 "Test rollback of a no committed delete"){
3422   INITIALIZER(runLoadTable);
3423   INITIALIZER(runCheckRollbackDelete);
3424   FINALIZER(runClearTable2);
3425 }
3426 TESTCASE("RollbackUpdate",
3427 	 "Test rollback of a no committed update"){
3428   INITIALIZER(runLoadTable);
3429   INITIALIZER(runCheckRollbackUpdate);
3430   FINALIZER(runClearTable2);
3431 }
3432 TESTCASE("RollbackDeleteMultiple",
3433 	 "Test rollback of 10 non committed delete"){
3434   INITIALIZER(runLoadTable);
3435   INITIALIZER(runCheckRollbackDeleteMultiple);
3436   FINALIZER(runClearTable2);
3437 }
3438 TESTCASE("ImplicitRollbackDelete",
3439 	 "Test close transaction after a no commited delete\n"
3440 	 "this would give an implicit rollback of the delete\n"){
3441   INITIALIZER(runLoadTable);
3442   INITIALIZER(runCheckImplicitRollbackDelete);
3443   FINALIZER(runClearTable2);
3444 }
3445 TESTCASE("CommitDelete",
3446 	 "Test close transaction after a no commited delete\n"
3447 	 "this would give an implicit rollback of the delete\n"){
3448   INITIALIZER(runLoadTable);
3449   INITIALIZER(runCheckCommitDelete);
3450   FINALIZER(runClearTable2);
3451 }
3452 TESTCASE("RollbackNothing",
3453 	 "Test rollback of nothing"){
3454   INITIALIZER(runLoadTable);
3455   INITIALIZER(runRollbackNothing);
3456   FINALIZER(runClearTable2);
3457 }
3458 TESTCASE("MassiveRollback",
3459 	 "Test rollback of 4096 operations"){
3460   INITIALIZER(runClearTable2);
3461   INITIALIZER(runMassiveRollback);
3462   FINALIZER(runClearTable2);
3463 }
3464 TESTCASE("MassiveRollback2",
3465 	 "Test rollback of 4096 operations"){
3466   INITIALIZER(runClearTable2);
3467   INITIALIZER(runMassiveRollback2);
3468   FINALIZER(runClearTable2);
3469 }
3470 TESTCASE("MassiveRollback3",
3471 	 "Test rollback of 4096 operations"){
3472   INITIALIZER(runClearTable2);
3473   STEP(runMassiveRollback3);
3474   STEP(runMassiveRollback3);
3475   FINALIZER(runClearTable2);
3476 }
3477 TESTCASE("MassiveRollback4",
3478 	 "Test rollback of 4096 operations"){
3479   INITIALIZER(runClearTable2);
3480   STEP(runMassiveRollback4);
3481   STEP(runMassiveRollback4);
3482   FINALIZER(runClearTable2);
3483 }
3484 TESTCASE("MassiveTransaction",
3485          "Test very large insert transaction"){
3486   INITIALIZER(runLoadTable2);
3487   FINALIZER(runClearTable2);
3488 }
3489 TESTCASE("TupError",
3490 	 "Verify what happens when we fill the db" ){
3491   INITIALIZER(runTupErrors);
3492 }
3493 TESTCASE("InsertError", "" ){
3494   INITIALIZER(runInsertError);
3495 }
3496 TESTCASE("InsertError2", "" ){
3497   INITIALIZER(runInsertError2);
3498 }
3499 TESTCASE("Fill",
3500 	 "Verify what happens when we fill the db" ){
3501   STEP(runFillTable);
3502 }
3503 TESTCASE("Bug25090",
3504 	 "Verify what happens when we fill the db" ){
3505   STEP(runBug25090);
3506 }
3507 TESTCASE("DeleteRead",
3508 	 "Verify Delete+Read" ){
3509   INITIALIZER(runLoadTable);
3510   INITIALIZER(runDeleteRead);
3511   FINALIZER(runClearTable2);
3512 }
3513 TESTCASE("Bug27756",
3514 	 "Verify what happens when we fill the db" ){
3515   STEP(runBug27756);
3516 }
3517 TESTCASE("Bug28073",
3518 	 "Infinite loop in lock queue" ){
3519   STEP(runBug28073);
3520 }
3521 TESTCASE("Bug20535",
3522 	 "Verify what happens when we fill the db" ){
3523   STEP(runBug20535);
3524 }
3525 TESTCASE("DDInsertFailUpdateBatch",
3526          "Verify DD insert failure effect on other ops in batch on same PK"){
3527   STEP(runDDInsertFailUpdateBatch);
3528 }
3529 
3530 TESTCASE("Bug34348",
3531          "Test fragment directory range full in ACC.\n"
3532          "NOTE: If interrupted, must clear error insert 3002 manually"){
3533   STEP(runBug34348);
3534 }
3535 TESTCASE("UnlockBatch",
3536          "Test that batched unlock operations work ok"){
3537   TC_PROPERTY("Batchsize", 33);
3538   INITIALIZER(runLoadTable);
3539   STEP(runUnlocker);
3540   FINALIZER(runClearTable);
3541 }
3542 TESTCASE("DoubleUnlock",
3543          "Test that batched unlock operations work ok"){
3544   TC_PROPERTY("DoubleUnlock", 1);
3545   INITIALIZER(runLoadTable);
3546   STEP(runUnlocker);
3547   FINALIZER(runClearTable);
3548 }
3549 TESTCASE("UnlockUpdateBatch",
3550          "Test Unlock mixed with Update"){
3551   TC_PROPERTY("Batchsize", 32);
3552   INITIALIZER(runLoadTable);
3553   STEP(runUnlocker);
3554   STEP(runUnlocker);
3555   STEP(runLocker);
3556   STEP(runPkUpdate);
3557   STEP(runPkUpdate);
3558   STEP(runPkRead);
3559   FINALIZER(runClearTable);
3560 }
3561 TESTCASE("RefreshTuple",
3562          "Test refreshTuple() operation properties"){
3563   INITIALIZER(initSubscription);
3564   INITIALIZER(runRefreshTuple);
3565   FINALIZER(removeSubscription);
3566 }
3567 TESTCASE("Bug54986", "")
3568 {
3569   INITIALIZER(runBug54986);
3570 }
3571 TESTCASE("Bug54944", "")
3572 {
3573   INITIALIZER(runBug54944);
3574 }
3575 TESTCASE("Bug59496_case1", "")
3576 {
3577   STEP(runBug59496_case1);
3578   STEPS(runBug59496_scan, 10);
3579 }
3580 TESTCASE("Bug59496_case2", "")
3581 {
3582   TC_PROPERTY("CHECK_ROWCOUNT", 1);
3583   INITIALIZER(runLoadTable);
3584   STEP(runBug59496_case2);
3585   STEPS(runBug59496_scan, 10);
3586 }
3587 TESTCASE("899", "")
3588 {
3589   INITIALIZER(runLoadTable);
3590   INITIALIZER(runInit899);
3591   STEP(runTest899);
3592   FINALIZER(runEnd899);
3593 }
3594 TESTCASE("RefreshLocking",
3595          "Test Refresh locking properties")
3596 {
3597   INITIALIZER(runRefreshLocking);
3598 }
3599 NDBT_TESTSUITE_END(testBasic);
3600 
3601 #if 0
3602 TESTCASE("ReadConsistency",
3603 	 "Check that a read within a transaction returns the " \
3604 	 "same result no matter"){
3605   STEP(runInsertOne);
3606   STEP(runReadOne);
3607   FINALIZER(runClearTable2);
3608 }
3609 TESTCASE("Fill",
3610 	 "Verify what happens when we fill the db" ){
3611   INITIALIZER(runFillTable);
3612   INITIALIZER(runPkRead);
3613   FINALIZER(runClearTable2);
3614 }
3615 #endif
3616 
main(int argc,const char ** argv)3617 int main(int argc, const char** argv){
3618   ndb_init();
3619   NDBT_TESTSUITE_INSTANCE(testBasic);
3620   return testBasic.execute(argc, argv);
3621 }
3622 
3623 
3624 
3625