summaryrefslogtreecommitdiff
path: root/ndb/test/ndbapi/testRestartGci.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/test/ndbapi/testRestartGci.cpp')
-rw-r--r--ndb/test/ndbapi/testRestartGci.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/ndb/test/ndbapi/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci.cpp
new file mode 100644
index 00000000000..e3dd1f8e2ce
--- /dev/null
+++ b/ndb/test/ndbapi/testRestartGci.cpp
@@ -0,0 +1,218 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "NDBT_Test.hpp"
+#include "NDBT_ReturnCodes.h"
+#include "HugoTransactions.hpp"
+#include "UtilTransactions.hpp"
+#include "NdbRestarter.hpp"
+
+
+/**
+ * Global vector to keep track of
+ * records stored in db
+ */
+
+struct SavedRecord {
+ int m_gci;
+ BaseString m_str;
+ SavedRecord(int _gci, BaseString _str){
+ m_gci = _gci;
+ m_str.assign(_str);
+ }
+ SavedRecord(){
+ m_gci = 0;
+ m_str = "";
+ };
+};
+Vector<SavedRecord> savedRecords;
+
+
+#define CHECK(b) if (!(b)) { \
+ ndbout << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ break; }
+
+int runInsertRememberGci(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int records = ctx->getNumRecords();
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+ int i = 0;
+
+ while(ctx->isTestStopped() == false && i < records){
+ // Insert record and read it in same transaction
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0);
+ if (hugoOps.execute_NoCommit(pNdb) != 0){
+ ndbout << "Could not insert record " << i << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
+ if (hugoOps.execute_Commit(pNdb) != 0){
+ ndbout << "Did not find record in DB " << i << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ savedRecords.push_back(SavedRecord(hugoOps.getRecordGci(0),
+ hugoOps.getRecordStr(0)));
+
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+ i++;
+ };
+
+ return result;
+}
+
+int runRestartGciControl(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ Ndb* pNdb = GETNDB(step);
+ UtilTransactions utilTrans(*ctx->getTab());
+ NdbRestarter restarter;
+
+ // Wait until we have enough records in db
+ int count = 0;
+ while (count < records){
+ if (utilTrans.selectCount(pNdb, 64, &count) != 0){
+ ctx->stopTest();
+ return NDBT_FAILED;
+ }
+ }
+
+ // Restart cluster with abort
+ if (restarter.restartAll(false, false, true) != 0){
+ ctx->stopTest();
+ return NDBT_FAILED;
+ }
+
+ // Stop the other thread
+ ctx->stopTest();
+
+ if (restarter.waitClusterStarted(300) != 0){
+ return NDBT_FAILED;
+ }
+
+ if (pNdb->waitUntilReady() != 0){
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ Ndb* pNdb = GETNDB(step);
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoOperations hugoOps(*ctx->getTab());
+ NdbRestarter restarter;
+
+ int restartGCI = pNdb->NdbTamper(Ndb::ReadRestartGCI, 0);
+
+ ndbout << "restartGCI = " << restartGCI << endl;
+ int count = 0;
+ if (utilTrans.selectCount(pNdb, 64, &count) != 0){
+ return NDBT_FAILED;
+ }
+
+ // RULE1: The vector with saved records should have exactly as many
+ // records with lower or same gci as there are in DB
+ int recordsWithLowerOrSameGci = 0;
+ for (unsigned i = 0; i < savedRecords.size(); i++){
+ if (savedRecords[i].m_gci <= restartGCI)
+ recordsWithLowerOrSameGci++;
+ }
+ if (recordsWithLowerOrSameGci != count){
+ ndbout << "ERR: Wrong number of expected records" << endl;
+ result = NDBT_FAILED;
+ }
+
+
+ // RULE2: The records found in db should have same or lower
+ // gci as in the vector
+ for (unsigned i = 0; i < savedRecords.size(); i++){
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
+ if (hugoOps.execute_Commit(pNdb) != 0){
+ // Record was not found in db'
+
+ // Check record gci
+ if (savedRecords[i].m_gci <= restartGCI){
+ ndbout << "ERR: Record "<<i<<" should have existed" << endl;
+ result = NDBT_FAILED;
+ }
+ } else {
+ // Record was found in db
+ BaseString str = hugoOps.getRecordStr(0);
+ // Check record string
+ if (!(savedRecords[i].m_str == str)){
+ ndbout << "ERR: Record "<<i<<" str did not match "<< endl;
+ result = NDBT_FAILED;
+ }
+ // Check record gci
+ if (savedRecords[i].m_gci > restartGCI){
+ ndbout << "ERR: Record "<<i<<" should not have existed" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+ }
+
+
+ ndbout << "There are " << count << " records in db" << endl;
+ ndbout << "There are " << savedRecords.size()
+ << " records in vector" << endl;
+
+ ndbout << "There are " << recordsWithLowerOrSameGci
+ << " records with lower or same gci than " << restartGCI << endl;
+
+ return result;
+}
+
+int runClearGlobals(NDBT_Context* ctx, NDBT_Step* step){
+ savedRecords.clear();
+ return NDBT_OK;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(GETNDB(step), records, 240) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+NDBT_TESTSUITE(testRestartGci);
+TESTCASE("InsertRestartGci",
+ "Verify that only expected records are still in NDB\n"
+ "after a restart" ){
+ INITIALIZER(runClearTable);
+ INITIALIZER(runClearGlobals);
+ STEP(runInsertRememberGci);
+ STEP(runRestartGciControl);
+ VERIFIER(runVerifyInserts);
+ FINALIZER(runClearTable);
+}
+NDBT_TESTSUITE_END(testRestartGci);
+
+int main(int argc, const char** argv){
+ return testRestartGci.execute(argc, argv);
+}