/* 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 #include #include #include #include #include #include #include #include #include //#define TRACE #define DEBUG //#define RELEASE #define NODE_REC // epaulsa: introduces pointer checks to help 'acid' keep core // during node recovery #ifdef TRACE #define VerifyMethodInt(c, m) (ReportMethodInt(c->m, c, #c, #m, __FILE__, __LINE__)) #define VerifyMethodPtr(v, c, m) (v=ReportMethodPtr(c->m, c, #v, #c, #m, __FILE__, __LINE__)) #define VerifyMethodVoid(c, m) (c->m, ReportMethodVoid(c, #c, #m, __FILE__, __LINE__)) int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szClass << "->" << szMethod << " return " << iRes << " : "; ndbout << pNdbConnection->getNdbError(); NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation(); if(pNdbOperation) { ndbout << " : " << pNdbOperation->getNdbError(); } ndbout << " : " << pNdbConnection->getNdbErrorLine(); ndbout << endl; return iRes; } template int ReportMethodInt(int iRes, C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szClass << "->" << szMethod << " return " << iRes << " : "; ndbout << pC->getNdbError(); ndbout << endl; return iRes; } template R* ReportMethodPtr(R* pR, C* pC, const char* szVariable, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szVariable << " = " << szClass << "->" << szMethod << " return " << (long)(void*)pR << " : "; ndbout << pC->getNdbError(); ndbout << endl; return pR; } template void ReportMethodVoid(C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szClass << "->" << szMethod << " : "; ndbout << pC->getNdbError(); ndbout << endl; } #endif /* TRACE */ #ifdef DEBUG #define VerifyMethodInt(c, m) (ReportMethodInt(c->m, c, #c, #m, __FILE__, __LINE__)) #define VerifyMethodPtr(v, c, m) (v=ReportMethodPtr(c->m, c, #v, #c, #m, __FILE__, __LINE__)) #define VerifyMethodVoid(c, m) (c->m, ReportMethodVoid(c, #c, #m, __FILE__, __LINE__)) int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { if(iRes<0) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szClass << "->" << szMethod << " return " << iRes << " : "; ndbout << pNdbConnection->getNdbError(); NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation(); if(pNdbOperation) { ndbout << " : " << pNdbOperation->getNdbError(); } ndbout << " : " << pNdbConnection->getNdbErrorLine(); ndbout << " : "; ndbout << endl; } return iRes; } template int ReportMethodInt(int iRes, C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { if(iRes<0) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szClass << "->" << szMethod << " return " << iRes << " : "; ndbout << pC->getNdbError(); ndbout << endl; } return iRes; } template R* ReportMethodPtr(R* pR, C* pC, const char* szVariable, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { if(!pR) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szVariable << " = " << szClass << "->" << szMethod << " return " << " : "; ndbout << pC->getNdbError(); ndbout << endl; } return pR; } template void ReportMethodVoid(C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { if(pC->getNdbError().code) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szClass << "->" << szMethod << " : "; ndbout << pC->getNdbError(); ndbout << endl; } } #endif /* DEBUG */ #ifdef RELEASE #define VerifyMethodInt(c, m) (c->m) #define VerifyMethodPtr(v, c, m) (v=(c->m)) #define VerifyMethodVoid(c, m) (c->m) int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine) { if(iRes<0) { ndbout << szFile << "(" << iLine << ") : "; ndbout << szClass << "->" << szMethod << " return " << iRes << " : "; ndbout << pNdbConnection->getNdbError(); NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation(); if(pNdbOperation) { ndbout << " : " << pNdbOperation->getNdbError(); } ndbout << " : " << pNdbConnection->getNdbErrorLine(); ndbout << endl; } return iRes; } #endif /* RELEASE */ // epaulsa => #ifndef NODE_REC #define CHK_TR(p) #else #define CHK_TR(p) if(!p){ \ ndbout <<"startTransaction failed, returning now." << endl ; \ delete pNdb ; \ pNdb = NULL ; \ return 0 ; \ } #endif // NODE_REC // <= epaulsa const char* c_szWarehouse = "WAREHOUSE"; const char* c_szWarehouseNumber = "W_ID"; const char* c_szWarehouseSum = "W_SUM"; const char* c_szWarehouseCount = "W_CNT"; const char* c_szDistrict = "DISTRICT"; const char* c_szDistrictWarehouseNumber = "D_W_ID"; const char* c_szDistrictNumber = "D_ID"; const char* c_szDistrictSum = "D_SUM"; const char* c_szDistrictCount = "D_CNT"; Uint32 g_nWarehouseCount = 10; Uint32 g_nDistrictPerWarehouse = 10; Uint32 g_nThreadCount = 1; NdbMutex* g_pNdbMutex = 0; extern "C" void* NdbThreadFuncInsert(void* pArg) { myRandom48Init((long int)NdbTick_CurrentMillisecond()); unsigned nSucc = 0; unsigned nFail = 0; Ndb* pNdb = NULL ; pNdb = new Ndb("TEST_DB"); VerifyMethodInt(pNdb, init()); VerifyMethodInt(pNdb, waitUntilReady()); while(NdbMutex_Trylock(g_pNdbMutex)) { Uint32 nWarehouse = myRandom48(g_nWarehouseCount); NdbConnection* pNdbConnection = NULL ; VerifyMethodPtr(pNdbConnection, pNdb, startTransaction()); CHK_TR(pNdbConnection); NdbOperation* pNdbOperationW = NULL ; VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse)); VerifyMethodInt(pNdbOperationW, insertTuple()); VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse)); VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseCount, Uint32(1))); Uint32 nWarehouseSum = 0; for(Uint32 nDistrict=0; nDistrictexecute(Commit); int iError = pNdbConnection->getNdbError().code; if(iExec<0 && iError!=0 && iError!=266 && iError!=630) { ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__); } if(iExec==0) { ++nSucc; } else { ++nFail; } VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection)); } ndbout << "insert: " << nSucc << " succeeded, " << nFail << " failed " << endl; NdbMutex_Unlock(g_pNdbMutex); delete pNdb; pNdb = NULL ; return NULL; } extern "C" void* NdbThreadFuncUpdate(void* pArg) { myRandom48Init((long int)NdbTick_CurrentMillisecond()); unsigned nSucc = 0; unsigned nFail = 0; Ndb* pNdb = NULL ; pNdb = new Ndb("TEST_DB"); VerifyMethodInt(pNdb, init()); VerifyMethodInt(pNdb, waitUntilReady()); while(NdbMutex_Trylock(g_pNdbMutex)) { Uint32 nWarehouse = myRandom48(g_nWarehouseCount); NdbConnection* pNdbConnection = NULL ; VerifyMethodPtr(pNdbConnection, pNdb, startTransaction()); CHK_TR(pNdbConnection) ; // epaulsa NdbOperation* pNdbOperationW = NULL ; VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse)); VerifyMethodInt(pNdbOperationW, interpretedUpdateTuple()); VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse)); VerifyMethodInt(pNdbOperationW, incValue(c_szWarehouseCount, Uint32(1))); Uint32 nWarehouseSum = 0; for(Uint32 nDistrict=0; nDistrictexecute(Commit); int iError = pNdbConnection->getNdbError().code; if(iExec<0 && iError!=0 && iError!=266 && iError!=626) { ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__); } if(iExec==0) { ++nSucc; } else { ++nFail; } VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection)); } ndbout << "update: " << nSucc << " succeeded, " << nFail << " failed " << endl; NdbMutex_Unlock(g_pNdbMutex); delete pNdb; pNdb = NULL ; return NULL; } extern "C" void* NdbThreadFuncDelete(void* pArg) { myRandom48Init((long int)NdbTick_CurrentMillisecond()); unsigned nSucc = 0; unsigned nFail = 0; Ndb* pNdb = NULL ; pNdb = new Ndb("TEST_DB"); VerifyMethodInt(pNdb, init()); VerifyMethodInt(pNdb, waitUntilReady()); while(NdbMutex_Trylock(g_pNdbMutex)) { Uint32 nWarehouse = myRandom48(g_nWarehouseCount); NdbConnection* pNdbConnection = NULL ; VerifyMethodPtr(pNdbConnection, pNdb, startTransaction()); CHK_TR(pNdbConnection) ; // epaulsa NdbOperation* pNdbOperationW = NULL ; VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse)); VerifyMethodInt(pNdbOperationW, deleteTuple()); VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse)); for(Uint32 nDistrict=0; nDistrictexecute(Commit); int iError = pNdbConnection->getNdbError().code; if(iExec<0 && iError!=0 && iError!=266 && iError!=626) { ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__); } if(iExec==0) { ++nSucc; } else { ++nFail; } VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection)); } ndbout << "delete: " << nSucc << " succeeded, " << nFail << " failed " << endl; NdbMutex_Unlock(g_pNdbMutex); delete pNdb; pNdb = NULL ; return NULL; } extern "C" void* NdbThreadFuncRead(void* pArg) { myRandom48Init((long int)NdbTick_CurrentMillisecond()); unsigned nSucc = 0; unsigned nFail = 0; NdbRecAttr** ppNdbRecAttrDSum = new NdbRecAttr*[g_nDistrictPerWarehouse]; NdbRecAttr** ppNdbRecAttrDCnt = new NdbRecAttr*[g_nDistrictPerWarehouse]; Ndb* pNdb = NULL ; pNdb = new Ndb("TEST_DB"); VerifyMethodInt(pNdb, init()); VerifyMethodInt(pNdb, waitUntilReady()); while(NdbMutex_Trylock(g_pNdbMutex)) { Uint32 nWarehouse = myRandom48(g_nWarehouseCount); NdbConnection* pNdbConnection = NULL ; VerifyMethodPtr(pNdbConnection, pNdb, startTransaction()); CHK_TR(pNdbConnection) ; // epaulsa NdbOperation* pNdbOperationW = NULL ; VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse)); VerifyMethodInt(pNdbOperationW, readTuple()); VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse)); NdbRecAttr* pNdbRecAttrWSum; VerifyMethodPtr(pNdbRecAttrWSum, pNdbOperationW, getValue(c_szWarehouseSum, 0)); NdbRecAttr* pNdbRecAttrWCnt; VerifyMethodPtr(pNdbRecAttrWCnt, pNdbOperationW, getValue(c_szWarehouseCount, 0)); for(Uint32 nDistrict=0; nDistrictexecute(Commit); int iError = pNdbConnection->getNdbError().code; if(iExec<0 && iError!=0 && iError!=266 && iError!=626) { ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__); } if(iExec==0) { Uint32 nSum = 0; Uint32 nCnt = 0; for(Uint32 nDistrict=0; nDistrictu_32_value(); nCnt += ppNdbRecAttrDCnt[nDistrict]->u_32_value(); } if(nSum!=pNdbRecAttrWSum->u_32_value() || nCnt!=g_nDistrictPerWarehouse*pNdbRecAttrWCnt->u_32_value()) { ndbout << "INCONSISTENT!" << endl; ndbout << "iExec==" << iExec << endl; ndbout << "iError==" << iError << endl; ndbout << endl; ndbout << c_szWarehouseSum << "==" << pNdbRecAttrWSum->u_32_value() << ", "; ndbout << c_szWarehouseCount << "==" << pNdbRecAttrWCnt->u_32_value() << endl; ndbout << "nSum==" << nSum << ", nCnt=" << nCnt << endl; for(Uint32 nDistrict=0; nDistrictu_32_value() << ", "; ndbout << c_szDistrictCount << "[" << nDistrict << "]==" << ppNdbRecAttrDCnt[nDistrict]->u_32_value() << endl; } VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection)); delete pNdb; pNdb = NULL ; delete[] ppNdbRecAttrDSum; ppNdbRecAttrDSum = NULL ; delete[] ppNdbRecAttrDCnt; ppNdbRecAttrDCnt = NULL ; NDBT_ProgramExit(NDBT_FAILED); } ++nSucc; } else { ++nFail; } VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection)); } ndbout << "read: " << nSucc << " succeeded, " << nFail << " failed " << endl; NdbMutex_Unlock(g_pNdbMutex); delete pNdb; pNdb = NULL ; delete[] ppNdbRecAttrDSum; ppNdbRecAttrDSum = NULL ; delete[] ppNdbRecAttrDCnt; ppNdbRecAttrDCnt = NULL ; return NULL; } NDB_COMMAND(acid, "acid", "acid", "acid", 65535) { ndb_init(); long nSeconds = 60; int rc = NDBT_OK; for(int i=1; i