18 #include "NDBT_Test.hpp"
19 #include "NDBT_ReturnCodes.h"
20 #include "HugoTransactions.hpp"
21 #include "UtilTransactions.hpp"
22 #include "NdbRestarter.hpp"
45 Uint64 highestExpectedGci;
47 #define CHECK(b) if (!(b)) { \
48 ndbout << "ERR: "<< step->getName() \
49 << " failed on line " << __LINE__ << endl; \
50 result = NDBT_FAILED; \
66 bool useExtendedBits = ((ndb_rand() % 5) != 0);
67 Uint32 numGciBits= ndb_rand() % 32;
68 Uint32 numAuthorBits = ndb_rand() % 32;
70 if (useExtendedBits && (numGciBits || numAuthorBits))
72 ndbout_c(
"Creating table %s with %u extra Gci and %u extra Author bits",
73 tab.
getName(), numGciBits, numAuthorBits);
79 ndbout_c(
"Table has no extra bits");
87 GETNDB(step)->getDictionary()->dropTable(ctx->getTab()->
getName());
94 runDropTable(ctx, step);
97 if (NDBT_Tables::createTable(GETNDB(step),
100 maybeExtraBits) == NDBT_OK)
102 ctx->setTab(GETNDB(step)->
104 getTable(ctx->getTab()->
getName()));
111 int result = NDBT_OK;
112 int records = ctx->getNumRecords();
115 Ndb* pNdb = GETNDB(step);
118 ndbout_c(
"Inserting %u records", records);
119 Uint64 minGci = ~Uint64(0);
121 Uint32 numAuthorBits = ctx->getTab()->getExtraRowAuthorBits();
122 Uint32 authorMask = (1 << numAuthorBits) -1;
123 ndbout_c(
"numAuthor bits is %u, mask is %x",
124 numAuthorBits, authorMask);
128 CHECK(hugoOps.startTransaction(pNdb) == 0);
129 CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0);
130 if (hugoOps.execute_NoCommit(pNdb) != 0){
131 ndbout <<
"Could not insert record " << i << endl;
132 result = NDBT_FAILED;
136 Uint32 authorVal = 0;
137 if (ctx->getTab()->getExtraRowAuthorBits() > 0)
139 authorVal = (ndb_rand() & authorMask);
141 char rowBuff[NDB_MAX_TUPLE_SIZE];
146 setValueSpec.column = NdbDictionary::Column::ROW_AUTHOR;
147 setValueSpec.value = &authorVal;
149 opts.optionsPresent= NdbOperation::OperationOptions::OO_SETVALUE;
150 opts.extraSetValues= &setValueSpec;
151 opts.numExtraSetValues = 1;
159 CHECK(update != NULL);
162 CHECK(hugoOps.pkReadRecord(pNdb, i) == 0);
163 if (hugoOps.execute_Commit(pNdb) != 0){
164 ndbout <<
"Did not find record in DB " << i << endl;
165 result = NDBT_FAILED;
169 CHECK(hugoOps.getTransaction()->getGCI(&gci) == 0);
178 hugoOps.getRecordStr(0)));
180 CHECK(hugoOps.closeTransaction(pNdb) == 0);
183 NdbSleep_MilliSleep(10);
186 ndbout_c(
" Inserted records from gci %x/%x to gci %x/%x",
187 (Uint32) (minGci >> 32), (Uint32) (minGci & 0xffffffff),
188 (Uint32) (maxGci >> 32), (Uint32) (maxGci & 0xffffffff));
190 highestExpectedGci = maxGci;
196 Ndb* pNdb = GETNDB(step);
199 ndbout_c(
"Restart of all nodes");
202 if (restarter.restartAll(
false,
false,
true) != 0){
207 if (restarter.waitClusterStarted(300) != 0){
219 Ndb* pNdb = GETNDB(step);
222 if (restarter.getNumDbNodes() < 2)
230 int node = restarter.getRandomNotMasterNodeId(rand());
231 ndbout_c(
"Restarting node %u initial", node);
233 if (restarter.restartOneDbNode(node,
243 if (restarter.waitClusterStarted(300) != 0){
255 int records = ctx->getNumRecords();
256 Ndb* pNdb = GETNDB(step);
261 while (count < records){
262 if (utilTrans.selectCount(pNdb, 64, &count) != 0){
266 NdbSleep_MilliSleep(10);
269 return runRestartAll(ctx,step);
274 Ndb* pNdb = GETNDB(step);
279 ndbout <<
"Failed to retrieve restart gci" << endl;
284 ndbout_c(
"Restart GCI is %u (0x%x)",
285 restartGci, restartGci);
287 ndbout_c(
"Highest expected GCI was %x/%x",
288 (Uint32) (highestExpectedGci >> 32),
289 (Uint32) (highestExpectedGci & 0xffffffff));
291 highestExpectedGci = ((Uint64) restartGci) << 32 | 0xffffffff;
292 ndbout_c(
"Resetting Highest expected GCI to align with restart Gci (%x/%x)",
293 (Uint32) (highestExpectedGci >> 32),
294 (Uint32) (highestExpectedGci & 0xffffffff));
299 ctx->incProperty(
"ExactGCI");
304 int result = NDBT_OK;
305 Ndb* pNdb = GETNDB(step);
309 Uint32 extraGciBits = ctx->getTab()->getExtraRowGciBits();
310 Uint32 firstSaturatedValue = (1 << extraGciBits) -1;
313 if (utilTrans.selectCount(pNdb, 64, &count) != 0){
319 int recordsWithLowerOrSameGci = 0;
321 for (i = 0; i < savedRecords.size(); i++){
322 if (savedRecords[i].m_gci <= highestExpectedGci)
323 recordsWithLowerOrSameGci++;
325 if (recordsWithLowerOrSameGci != count){
326 ndbout <<
"ERR: Wrong number of expected records" << endl;
327 result = NDBT_FAILED;
330 bool exactGCIonly = ctx->getProperty(
"ExactGCI", (
unsigned) 0);
334 int recordsWithIncorrectGci = 0;
335 int recordsWithRoundedGci = 0;
336 int recordsWithIncorrectAuthor = 0;
337 for (i = 0; i < savedRecords.size(); i++){
338 CHECK(hugoOps.startTransaction(pNdb) == 0);
340 CHECK(hugoOps.pkReadRecord(pNdb, i) == 0);
343 NdbOperation* readOp = trans->getNdbOperation(ctx->getTab());
344 CHECK(readOp != NULL);
346 CHECK(hugoOps.equalForRow(readOp, i) == 0);
349 CHECK(rowGci != NULL);
350 CHECK(rowAuthor != NULL);
351 if (hugoOps.execute_Commit(pNdb) != 0){
355 if (savedRecords[i].m_gci <= highestExpectedGci) {
356 ndbout <<
"ERR: Record "<<i<<
" should have existed" << endl;
357 result = NDBT_FAILED;
365 savedRecords[
i].m_gci = (Uint64(1) << 63) -1;
371 if (!(savedRecords[i].m_str == str)){
372 ndbout <<
"ERR: Record "<<i<<
" str did not match "<< endl;
373 result = NDBT_FAILED;
376 Uint64 expectedRecordGci = savedRecords[
i].m_gci;
377 if (expectedRecordGci > highestExpectedGci){
378 ndbout <<
"ERR: Record "<<i<<
" should not have existed" << endl;
379 result = NDBT_FAILED;
381 bool expectRounding = (expectedRecordGci & 0xffffffff) >= firstSaturatedValue;
382 Uint64 expectedRoundedGci = (expectedRecordGci | 0xffffffff);
383 Uint64 readGci = rowGci->u_64_value();
384 Uint64 expectedRead = (expectRounding)?expectedRoundedGci :
387 if (expectedRead != readGci){
388 if ((!exactGCIonly) &&
389 (expectedRoundedGci == readGci))
394 recordsWithRoundedGci++;
398 ndbout_c(
"ERR: Record %u should have GCI %x/%x, but has "
401 (Uint32) (expectedRead >> 32),
402 (Uint32) (expectedRead & 0xffffffff),
403 (Uint32) (readGci >> 32),
404 (Uint32) (readGci & 0xffffffff));
405 recordsWithIncorrectGci++;
406 result = NDBT_FAILED;
411 Uint32 expectedAuthor = savedRecords[
i].m_author;
413 if (rowAuthor->
u_32_value() != expectedAuthor)
415 ndbout_c(
"ERR: Record %u should have Author %d, but has %d.",
419 recordsWithIncorrectAuthor++;
420 result = NDBT_FAILED;
424 CHECK(hugoOps.closeTransaction(pNdb) == 0);
428 ndbout <<
"There are " << count <<
" records in db" << endl;
429 ndbout <<
"There are " << savedRecords.size()
430 <<
" records in vector" << endl;
432 ndbout_c(
"There are %u records with lower or same gci than %x/%x",
433 recordsWithLowerOrSameGci,
434 (Uint32)(highestExpectedGci >> 32),
435 (Uint32)(highestExpectedGci & 0xffffffff));
437 ndbout_c(
"There are %u records with rounded Gcis. Exact GCI flag is %u",
438 recordsWithRoundedGci, exactGCIonly);
440 ndbout <<
"There are " << recordsWithIncorrectGci
441 <<
" records with incorrect Gci on recovery." << endl;
443 ndbout <<
"There are " << recordsWithIncorrectAuthor
444 <<
" records with incorrect Author on recovery." << endl;
450 savedRecords.clear();
451 highestExpectedGci = 0;
456 int records = ctx->getNumRecords();
459 if (utilTrans.clearTable2(GETNDB(step), records, 240) != 0){
468 int records = ctx->getNumRecords();
470 if (hugoTrans.loadTable(GETNDB(step), records, 512,
false, 0,
true) != 0){
479 const Uint32 numRestarts = 4;
480 for (Uint32 nr = 0; nr < numRestarts; nr++)
482 if (ctx->isTestStopped())
486 int nodeId = restarter.getNode(NdbRestarter::NS_RANDOM);
487 ndbout_c(
"Restarting node %u", nodeId);
489 if (restarter.restartOneDbNode(nodeId, NdbRestarter::NRRF_INITIAL) != 0)
491 ndbout_c(
"Error restarting node");
496 if (restarter.waitClusterStarted(300) != 0)
502 if (GETNDB(step)->waitUntilReady() != 0)
518 Ndb* pNdb = GETNDB(step);
523 Uint64 loopCount = 0;
524 Uint64 distinctCount = 0;
525 Uint64 expectedGCI = 0;
526 Uint64 lastGoodReadGCI = 0;
527 Uint32 extraGciBits = ctx->getTab()->getExtraRowGciBits();
528 Uint32 firstSaturatedValue = (1 << extraGciBits) -1;
529 ndbout_c(
"Extra GCI bits : %u, firstSaturatedValue : %u",
531 firstSaturatedValue);
532 int result = NDBT_OK;
533 while (!ctx->isTestStopped())
535 CHECK(hugoOps.startTransaction(pNdb) == 0);
538 CHECK(hugoOps.pkReadRecord(pNdb,
541 NdbOperation* readOp = trans->getNdbOperation(ctx->getTab());
542 CHECK(readOp != NULL);
543 CHECK(readOp->readTuple() == 0);
544 CHECK(hugoOps.equalForRow(readOp, 0) == 0);
545 NdbRecAttr* rowGci = readOp->getValue(NdbDictionary::Column::ROW_GCI64);
546 CHECK(rowGci != NULL);
549 CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, loopCount+1) == 0);
551 if (hugoOps.execute_Commit(pNdb) != 0)
553 if (hugoOps.getNdbError().classification ==
556 hugoOps.closeTransaction(pNdb);
557 ndbout_c(
"Temporary error at loopCount %llu", loopCount);
561 ndbout <<
"Error executing : " << hugoOps.getNdbError() << endl;
566 CHECK(hugoCalc.verifyRowValues(&hugoOps.get_row(0)) == 0);
567 CHECK((Uint64)hugoCalc.getUpdatesValue(&hugoOps.get_row(0)) == loopCount);
571 CHECK(trans->getGCI(&committedGCI) == 0);
572 Uint32 gci_lo = Uint32(committedGCI & 0xffffffff);
574 Uint64 saturatedCommittedGCI = (gci_lo >= firstSaturatedValue) ?
575 committedGCI | 0xffffffff : committedGCI;
576 Uint64 rowGCI64 = rowGci->u_64_value();
589 if (rowGCI64 < lastGoodReadGCI)
591 ndbout_c(
"ERROR : Read row GCI value (%x/%x) lower than previous value (%x/%x)",
592 (Uint32) (rowGCI64 >> 32),
593 (Uint32) (rowGCI64 & 0xffffffff),
594 Uint32(lastGoodReadGCI >> 32),
595 Uint32(lastGoodReadGCI & 0xffffffff));
600 if (saturatedCommittedGCI < rowGCI64)
602 ndbout_c(
"ERROR : Saturated committed GCI (%x/%x) lower than actual read GCI (%x/%x)",
603 Uint32(saturatedCommittedGCI >>32),
604 Uint32(saturatedCommittedGCI & 0xffffffff),
605 (Uint32) (rowGCI64 >> 32),
606 (Uint32) (rowGCI64 & 0xffffffff));
611 if (saturatedCommittedGCI < lastGoodReadGCI)
613 ndbout_c(
"ERROR : Saturated committed GCI (%x/%x) lower than a previously"
615 Uint32(saturatedCommittedGCI >>32),
616 Uint32(saturatedCommittedGCI & 0xffffffff),
617 Uint32(lastGoodReadGCI >> 32),
618 Uint32(lastGoodReadGCI & 0xffffffff));
623 if (saturatedCommittedGCI < expectedGCI)
625 ndbout_c(
"ERROR : Saturated committed GCI (%x/%x) lower than expected GCI"
627 Uint32(saturatedCommittedGCI >>32),
628 Uint32(saturatedCommittedGCI & 0xffffffff),
629 Uint32(expectedGCI >> 32),
630 Uint32(expectedGCI & 0xffffffff));
635 if (rowGCI64 != expectedGCI)
637 ndbout_c(
"MISMATCH : Expected GCI of %x/%x, but found %x/%x",
638 (Uint32) (expectedGCI >> 32),
639 (Uint32) (expectedGCI & 0xffffffff),
640 (Uint32) (rowGCI64 >> 32),
641 (Uint32) (rowGCI64 & 0xffffffff));
642 ndbout_c(
"At loopcount %llu", loopCount);
643 ndbout_c(
"Last good read GCI %x/%x",
644 Uint32(lastGoodReadGCI >> 32),
645 Uint32(lastGoodReadGCI & 0xffffffff));
646 ndbout_c(
"Read committed GCI : %x/%x",
647 Uint32(saturatedCommittedGCI >>32),
648 Uint32(saturatedCommittedGCI & 0xffffffff));
649 ndbout_c(
"Transaction coordinator node : %u",
650 trans->getConnectedNodeId());
654 if (saturatedCommittedGCI != expectedGCI)
660 expectedGCI = saturatedCommittedGCI;
661 lastGoodReadGCI = rowGCI64;
663 hugoOps.closeTransaction(pNdb);
667 NdbSleep_MilliSleep(10);
670 ndbout_c(
"%llu updates with %llu distinct GCI values",
677 NDBT_TESTSUITE(testRestartGci);
678 TESTCASE(
"InsertRestartGci",
679 "Verify that only expected records are still in NDB\n"
681 INITIALIZER(runCreateTable);
682 INITIALIZER(runClearGlobals);
683 INITIALIZER(runInsertRememberGci);
684 INITIALIZER(runRestartGciControl);
685 INITIALIZER(runDetermineRestartGci);
686 TC_PROPERTY(
"ExactGCI", Uint32(0));
687 VERIFIER(runVerifyInserts);
691 VERIFIER(runRestartAll);
692 VERIFIER(runDetermineRestartGci);
693 VERIFIER(runVerifyInserts);
697 VERIFIER(runRestartOneInitial);
698 VERIFIER(runVerifyInserts);
699 VERIFIER(runClearTable);
704 VERIFIER(runClearGlobals);
705 VERIFIER(runInsertRememberGci);
706 VERIFIER(runRestartOneInitial);
708 VERIFIER(runRequireExact);
709 VERIFIER(runVerifyInserts);
713 VERIFIER(runRestartAll);
714 VERIFIER(runDetermineRestartGci);
715 VERIFIER(runVerifyInserts);
716 FINALIZER(runClearTable);
717 FINALIZER(runDropTable);
719 TESTCASE(
"InitialNodeRestartUpdate",
720 "Check that initial node restart (copyfrag) does "
721 "not affect GCI recording")
723 INITIALIZER(runCreateTable);
724 INITIALIZER(runLoadTable);
725 STEP(runNodeInitialRestarts);
726 STEP(runUpdateVerifyGCI);
727 FINALIZER(runClearTable);
728 FINALIZER(runDropTable);
730 NDBT_TESTSUITE_END(testRestartGci);
732 int main(
int argc,
const char** argv){
734 NDBT_TESTSUITE_INSTANCE(testRestartGci);
735 testRestartGci.setCreateTable(
false);
736 return testRestartGci.execute(argc, argv);