/* Copyright (c) 2003-2005 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; version 2 of the License. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include #include const char* const c_szDatabaseName = "TEST_DB"; const char* const c_szTableNameStored = "CCStored"; const char* const c_szTableNameTemp = "CCTemp"; const char* const c_szContextId = "ContextId"; const char* const c_szVersion = "Version"; const char* const c_szLockFlag = "LockFlag"; const char* const c_szLockTime = "LockTime"; const char* const c_szLockTimeUSec = "LockTimeUSec"; const char* const c_szContextData = "ContextData"; const char* g_szTableName = c_szTableNameStored; #ifdef NDB_WIN32 HANDLE hShutdownEvent = 0; #else #include bool bShutdownEvent = false; #endif long g_nMaxContextIdPerThread = 5000; long g_nNumThreads = 0; long g_nMaxCallsPerSecond = 0; long g_nMaxRetry = 50; bool g_bWriteTuple = false; bool g_bInsertInitial = false; bool g_bVerifyInitial = false; NdbMutex* g_pNdbMutexPrintf = 0; NdbMutex* g_pNdbMutexIncrement = 0; long g_nNumCallsProcessed = 0; NDB_TICKS g_tStartTime = 0; NDB_TICKS g_tEndTime = 0; long g_nNumberOfInitialInsert = 0; long g_nNumberOfInitialVerify = 0; const long c_nMaxMillisecForAllCall = 5000; long* g_plCountMillisecForCall = 0; const long c_nMaxMillisecForAllTrans = 5000; long* g_plCountMillisecForTrans = 0; bool g_bReport = false; bool g_bReportPlus = false; // data for CALL_CONTEXT and GROUP_RESOURCE static char STATUS_DATA[]= "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F" "101112131415161718191A1B1C1D1E1F000102030405060708090A0B0C0D0E0F" "202122232425262728292A2B2C2D2E2F000102030405060708090A0B0C0D0E0F" "303132333435363738393A3B3C3D3E3F000102030405060708090A0B0C0D0E0F" "404142434445464748494A4B4C4D4E4F000102030405060708090A0B0C0D0E0F" "505152535455565758595A5B5C5D5E5F000102030405060708090A0B0C0D0E0F" "606162636465666768696A6B6C6D6E6F000102030405060708090A0B0C0D0E0F" "707172737475767778797A7B7C7D7E7F000102030405060708090A0B0C0D0E0F" "808182838485868788898A8B8C8D8E8F000102030405060708090A0B0C0D0E0F" "909192939495969798999A9B9C9D9E9F000102030405060708090A0B0C0D0E0F" "10010110210310410510610710810910A000102030405060708090A0B0C0D0EF" "10B10C10D10E10F110111112113114115000102030405060708090A0B0C0D0EF" "11611711811911A11B11C11D11E11F120000102030405060708090A0B0C0D0EF" "12112212312412512612712812912A12B000102030405060708090A0B0C0D0EF" "12C12D12E12F130131132134135136137000102030405060708090A0B0C0D0EF" "13813913A13B13C13D13E13F140141142000102030405060708090A0B0C0D0EF" "14314414514614714814914A14B14C14D000102030405060708090A0B0C0D0EF" "14E14F150151152153154155156157158000102030405060708090A0B0C0D0EF" "15915A15B15C15D15E15F160161162163000102030405060708090A0B0C0D0EF" "16416516616716816916A16B16C16D16E000102030405060708090A0B0C0D0EF" "16F170171172173174175176177178179000102030405060708090A0B0C0D0EF" "17A17B17C17D17E17F180181182183184000102030405060708090A0B0C0D0EF" "18518618718818918A18B18C18D18E18F000102030405060708090A0B0C0D0EF" "19019119219319419519619719819919A000102030405060708090A0B0C0D0EF" "19B19C19D19E19F200201202203204205000102030405060708090A0B0C0D0EF" "20620720820920A20B20C20D20F210211000102030405060708090A0B0C0D0EF" "21221321421521621721821921A21B21C000102030405060708090A0B0C0D0EF" "21D21E21F220221222223224225226227000102030405060708090A0B0C0D0EF" "22822922A22B22C22D22E22F230231232000102030405060708090A0B0C0D0EF" "23323423523623723823923A23B23C23D000102030405060708090A0B0C0D0EF" "23E23F240241242243244245246247248000102030405060708090A0B0C0D0EF" "24924A24B24C24D24E24F250251252253000102030405060708090A0B0C0D0EF" "101112131415161718191A1B1C1D1E1F000102030405060708090A0B0C0D0E0F" "202122232425262728292A2B2C2D2E2F000102030405060708090A0B0C0D0E0F" "303132333435363738393A3B3C3D3E3F000102030405060708090A0B0C0D0E0F" "404142434445464748494A4B4C4D4E4F000102030405060708090A0B0C0D0E0F" "505152535455565758595A5B5C5D5E5F000102030405060708090A0B0C0D0E0F" "606162636465666768696A6B6C6D6E6F000102030405060708090A0B0C0D0E0F" "707172737475767778797A7B7C7D7E7F000102030405060708090A0B0C0D0E0F" "808182838485868788898A8B8C8D8E8F000102030405060708090A0B0C0D0E0F" "909192939495969798999A9B9C9D9E9F000102030405060708090A0B0C0D0E0F" "10010110210310410510610710810910A000102030405060708090A0B0C0D0EF" "10B10C10D10E10F110111112113114115000102030405060708090A0B0C0D0EF" "11611711811911A11B11C11D11E11F120000102030405060708090A0B0C0D0EF" "12112212312412512612712812912A12B000102030405060708090A0B0C0D0EF" "12C12D12E12F130131132134135136137000102030405060708090A0B0C0D0EF" "13813913A13B13C13D13E13F140141142000102030405060708090A0B0C0D0EF" "14314414514614714814914A14B14C14D000102030405060708090A0B0C0D0EF" "14E14F150151152153154155156157158000102030405060708090A0B0C0D0EF" "15915A15B15C15D15E15F160161162163000102030405060708090A0B0C0D0EF" "16416516616716816916A16B16C16D16E000102030405060708090A0B0C0D0EF" "16F170171172173174175176177178179000102030405060708090A0B0C0D0EF" "17A17B17C17D17E17F180181182183184000102030405060708090A0B0C0D0EF" "18518618718818918A18B18C18D18E18F000102030405060708090A0B0C0D0EF" "19019119219319419519619719819919A000102030405060708090A0B0C0D0EF" "19B19C19D19E19F200201202203204205000102030405060708090A0B0C0D0EF" "20620720820920A20B20C20D20F210211000102030405060708090A0B0C0D0EF" "21221321421521621721821921A21B21C000102030405060708090A0B0C0D0EF" "21D21E21F220221222223224225226227000102030405060708090A0B0C0D0EF" "22822922A22B22C22D22E22F230231232000102030405060708090A0B0C0D0EF" "23323423523623723823923A23B23C23D000102030405060708090A0B0C0D0EF" "2366890FE1438751097E7F6325DC0E6326F" "25425525625725825925A25B25C25D25E25F000102030405060708090A0B0C0F"; long g_nStatusDataSize = sizeof(STATUS_DATA); // Thread function for Call Context Inserts #ifdef NDB_WIN32 BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType) { if(CTRL_C_EVENT == dwCtrlType) { SetEvent(hShutdownEvent); return TRUE; } return FALSE; } #else void CtrlCHandler(int) { bShutdownEvent = true; } #endif void ReportNdbError(const char* szMsg, const NdbError& err) { NdbMutex_Lock(g_pNdbMutexPrintf); printf("%s: %d: %s\n", szMsg, err.code, (err.message ? err.message : "")); NdbMutex_Unlock(g_pNdbMutexPrintf); } void ReportCallsPerSecond(long nNumCallsProcessed, NDB_TICKS tStartTime, NDB_TICKS tEndTime) { NDB_TICKS tElapsed = tEndTime - tStartTime; long lCallsPerSec; if(tElapsed>0) lCallsPerSec = (long)((1000*nNumCallsProcessed)/tElapsed); else lCallsPerSec = 0; NdbMutex_Lock(g_pNdbMutexPrintf); printf("Time Taken for %ld Calls is %ld msec (= %ld calls/sec)\n", nNumCallsProcessed, (long)tElapsed, lCallsPerSec); NdbMutex_Unlock(g_pNdbMutexPrintf); } #ifndef NDB_WIN32 void InterlockedIncrement(long* lp) // expensive { NdbMutex_Lock(g_pNdbMutexIncrement); (*lp)++; NdbMutex_Unlock(g_pNdbMutexIncrement); } #endif void InterlockedIncrementAndReport(void) { NdbMutex_Lock(g_pNdbMutexIncrement); ++g_nNumCallsProcessed; if((g_nNumCallsProcessed%1000)==0) { g_tEndTime = NdbTick_CurrentMillisecond(); if(g_tStartTime) ReportCallsPerSecond(1000, g_tStartTime, g_tEndTime); g_tStartTime = g_tEndTime; } NdbMutex_Unlock(g_pNdbMutexIncrement); } void SleepOneCall(void) { int iMillisecToSleep; if(g_nMaxCallsPerSecond>0) iMillisecToSleep = (1000*g_nNumThreads)/g_nMaxCallsPerSecond; else iMillisecToSleep = 50; if(iMillisecToSleep>0) NdbSleep_MilliSleep(iMillisecToSleep); } int QueryTransaction(Ndb* pNdb, long iContextId, long* piVersion, long* piLockFlag, long* piLockTime, long* piLockTimeUSec, char* pchContextData, NdbError& err) { int iRes = -1; NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextId, 4); if(pNdbConnection) { NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName); if(pNdbOperation) { NdbRecAttr* pNdbRecAttrVersion; NdbRecAttr* pNdbRecAttrLockFlag; NdbRecAttr* pNdbRecAttrLockTime; NdbRecAttr* pNdbRecAttrLockTimeUSec; NdbRecAttr* pNdbRecAttrContextData; if(!pNdbOperation->readTuple() && !pNdbOperation->equal(c_szContextId, (Int32)iContextId) && (pNdbRecAttrVersion=pNdbOperation->getValue(c_szVersion, (char*)piVersion)) && (pNdbRecAttrLockFlag=pNdbOperation->getValue(c_szLockFlag, (char*)piLockFlag)) && (pNdbRecAttrLockTime=pNdbOperation->getValue(c_szLockTime, (char*)piLockTime)) && (pNdbRecAttrLockTimeUSec=pNdbOperation->getValue(c_szLockTimeUSec, (char*)piLockTimeUSec)) && (pNdbRecAttrContextData=pNdbOperation->getValue(c_szContextData, pchContextData))) { if(!pNdbConnection->execute(Commit)) iRes = 0; else err = pNdbConnection->getNdbError(); } else err = pNdbOperation->getNdbError(); } else err = pNdbConnection->getNdbError(); pNdb->closeTransaction(pNdbConnection); } else err = pNdb->getNdbError(); return iRes; } int RetryQueryTransaction(Ndb* pNdb, long iContextId, long* piVersion, long* piLockFlag, long* piLockTime, long* piLockTimeUSec, char* pchContextData, NdbError& err, int& nRetry) { int iRes = -1; nRetry = 0; bool bRetry = true; while(bRetry && nRetrystartTransaction(0, (const char*)&iContextId, 4); if(pNdbConnection) { NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName); if(pNdbOperation) { if(!pNdbOperation->deleteTuple() && !pNdbOperation->equal(c_szContextId, (Int32)iContextId)) { if(pNdbConnection->execute(Commit) == 0) iRes = 0; else err = pNdbConnection->getNdbError(); } else err = pNdbOperation->getNdbError(); } else err = pNdbConnection->getNdbError(); pNdb->closeTransaction(pNdbConnection); } else err = pNdb->getNdbError(); return iRes; } int RetryDeleteTransaction(Ndb* pNdb, long iContextId, NdbError& err, int& nRetry) { int iRes = -1; nRetry = 0; bool bRetry = true; bool bUnknown = false; while(bRetry && nRetrystartTransaction(0, (const char*)&iContextID, 4); if(pNdbConnection) { NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName); if(pNdbOperation) { if(!(g_bWriteTuple ? pNdbOperation->writeTuple() : pNdbOperation->insertTuple()) && !pNdbOperation->equal(c_szContextId, (Int32)iContextID) && !pNdbOperation->setValue(c_szVersion, (Int32)iVersion) && !pNdbOperation->setValue(c_szLockFlag, (Int32)iLockFlag) && !pNdbOperation->setValue(c_szLockTime, (Int32)iLockTime) && !pNdbOperation->setValue(c_szLockTimeUSec, (Int32)iLockTimeUSec) && !pNdbOperation->setValue(c_szContextData, pchContextData, g_nStatusDataSize)) { if(!pNdbConnection->execute(Commit)) iRes = 0; else err = pNdbConnection->getNdbError(); } else err = pNdbOperation->getNdbError(); } else err = pNdbConnection->getNdbError(); pNdb->closeTransaction(pNdbConnection); } else err = pNdb->getNdbError(); return iRes; } int RetryInsertTransaction(Ndb* pNdb, long iContextId, long iVersion, long iLockFlag, long iLockTime, long iLockTimeUSec, const char* pchContextData, NdbError& err, int& nRetry) { int iRes = -1; nRetry = 0; bool bRetry = true; bool bUnknown = false; while(bRetry && nRetrystartTransaction(0, (const char*)&iContextId, 4); if(pNdbConnection) { NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName); if(pNdbOperation) { if(!pNdbOperation->updateTuple() && !pNdbOperation->equal(c_szContextId, (Int32)iContextId) && !pNdbOperation->setValue(c_szContextData, STATUS_DATA, g_nStatusDataSize)) { if(!pNdbConnection->execute(Commit)) iRes = 0; else err = pNdbConnection->getNdbError(); } else err = pNdbOperation->getNdbError(); } else err = pNdbConnection->getNdbError(); pNdb->closeTransaction(pNdbConnection); } else err = pNdb->getNdbError(); return iRes; } int RetryUpdateTransaction(Ndb* pNdb, long iContextId, NdbError& err, int& nRetry) { int iRes = -1; nRetry = 0; bool bRetry = true; while(bRetry && nRetry0) { sprintf(szMsg, "insert retried %d times, time %ld msec.", nRetry, lMillisecForThisTrans); ReportNdbError(szMsg, err); } if(iRes) { ReportNdbError("Insert initial record failed", err); return iRes; } InterlockedIncrement(&g_nNumberOfInitialInsert); } return iRes; } int VerifyInitialRecords(Ndb* pNdb, long nVerify, long nSeed) { int iRes = -1; char* pchContextData = new char[g_nStatusDataSize]; char szMsg[100]; long iPrevLockTime = -1; long iPrevLockTimeUSec = -1; for(long i=0; i0) { sprintf(szMsg, "verify retried %d times, time %ld msec.", nRetry, lMillisecForThisTrans); ReportNdbError(szMsg, err); } if(iRes) { ReportNdbError("Read initial record failed", err); delete[] pchContextData; return iRes; } if(memcmp(pchContextData, STATUS_DATA, g_nStatusDataSize)) { sprintf(szMsg, "wrong context data in tuple %d", iContextID); ReportNdbError(szMsg, err); delete[] pchContextData; return -1; } if(iVersion!=nSeed || iLockFlag!=iContextID || iLockTimeinit(1) || pNdb->waitUntilReady()) { ReportNdbError("init of Ndb failed", pNdb->getNdbError()); delete pNdb; delete[] pchContextData; return 0; } if(g_bInsertInitial) { if(InsertInitialRecords(pNdb, g_nMaxContextIdPerThread, -nStartingRecordID-g_nMaxContextIdPerThread)) { delete pNdb; delete[] pchContextData; return 0; } } if(g_bVerifyInitial) { NdbError err; memset(&err, 0, sizeof(err)); if(VerifyInitialRecords(pNdb, g_nMaxContextIdPerThread, -nStartingRecordID-g_nMaxContextIdPerThread)) { delete pNdb; delete[] pchContextData; return 0; } } if(g_bInsertInitial || g_bVerifyInitial) { delete[] pchContextData; return 0; } long nContextID = nStartingRecordID; #ifdef NDB_WIN32 while(WaitForSingleObject(hShutdownEvent,0) != WAIT_OBJECT_0) #else while(!bShutdownEvent) #endif { ++nContextID; nContextID %= g_nMaxContextIdPerThread; nContextID += nStartingRecordID; bool bTimeLatency = (nContextID==100); NDB_TICKS tStartCall = NdbTick_CurrentMillisecond(); for (int i=0; i < 20; i++) { int nRetry = 0; NdbError err; memset(&err, 0, sizeof(err)); NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond(); switch(i) { case 3: case 6: case 9: case 11: case 12: case 15: case 18: // Query Record szOp = "Read"; iRes = RetryQueryTransaction(pNdb, nContextID, &iVersion, &iLockFlag, &iLockTime, &iLockTimeUSec, pchContextData, err, nRetry); break; case 19: // Delete Record szOp = "Delete"; iRes = RetryDeleteTransaction(pNdb, nContextID, err, nRetry); break; case 0: // Insert Record szOp = "Insert"; iRes = RetryInsertTransaction(pNdb, nContextID, 1, 1, 1, 1, STATUS_DATA, err, nRetry); break; default: // Update Record szOp = "Update"; iRes = RetryUpdateTransaction(pNdb, nContextID, err, nRetry); break; } NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond(); long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans); if(g_bReport) { assert(lMillisecForThisTrans>=0 && lMillisecForThisTrans0) { sprintf(szMsg, "%s retried %d times, time %ld msec.", szOp, nRetry, lMillisecForThisTrans); ReportNdbError(szMsg, err); } else if(bTimeLatency) { NdbMutex_Lock(g_pNdbMutexPrintf); printf("%s = %ld msec.\n", szOp, lMillisecForThisTrans); NdbMutex_Unlock(g_pNdbMutexPrintf); } if(iRes) { sprintf(szMsg, "%s failed after %ld calls, terminating thread", szOp, nNumCallsProcessed); ReportNdbError(szMsg, err); delete pNdb; delete[] pchContextData; return 0; } } NDB_TICKS tEndCall = NdbTick_CurrentMillisecond(); long lMillisecForThisCall = (long)(tEndCall-tStartCall); if(g_bReport) { assert(lMillisecForThisCall>=0 && lMillisecForThisCall0) { int iMillisecToSleep = (1000*g_nNumThreads)/g_nMaxCallsPerSecond; iMillisecToSleep -= lMillisecForThisCall; if(iMillisecToSleep>0) { NdbSleep_MilliSleep(iMillisecToSleep); } } } NdbMutex_Lock(g_pNdbMutexPrintf); printf("Terminating thread after %ld calls\n", nNumCallsProcessed); NdbMutex_Unlock(g_pNdbMutexPrintf); delete pNdb; delete[] pchContextData; return 0; } int CreateCallContextTable(Ndb* pNdb, const char* szTableName, bool bStored) { int iRes = -1; NdbError err; memset(&err, 0, sizeof(err)); NdbSchemaCon* pNdbSchemaCon = NdbSchemaCon::startSchemaTrans(pNdb); if(pNdbSchemaCon) { NdbSchemaOp* pNdbSchemaOp = pNdbSchemaCon->getNdbSchemaOp(); if(pNdbSchemaOp) { if(!pNdbSchemaOp->createTable(szTableName, 8, TupleKey, 2, All, 6, 78, 80, 1, bStored) && !pNdbSchemaOp->createAttribute(c_szContextId, TupleKey, 32, 1, Signed) && !pNdbSchemaOp->createAttribute(c_szVersion, NoKey, 32, 1, Signed) && !pNdbSchemaOp->createAttribute(c_szLockFlag, NoKey, 32, 1, Signed) && !pNdbSchemaOp->createAttribute(c_szLockTime, NoKey, 32, 1, Signed) && !pNdbSchemaOp->createAttribute(c_szLockTimeUSec, NoKey, 32, 1, Signed) && !pNdbSchemaOp->createAttribute(c_szContextData, NoKey, 8, g_nStatusDataSize, String)) { if(!pNdbSchemaCon->execute()) iRes = 0; else err = pNdbSchemaCon->getNdbError(); } else err = pNdbSchemaOp->getNdbError(); } else err = pNdbSchemaCon->getNdbError(); NdbSchemaCon::closeSchemaTrans(pNdbSchemaCon); } else err = pNdb->getNdbError(); if(iRes) { ReportNdbError("create call context table failed", err); } return iRes; } void ReportResponseTimeStatistics(const char* szStat, long* plCount, const long lSize) { long lCount = 0; Int64 llSum = 0; Int64 llSum2 = 0; long lMin = -1; long lMax = -1; for(long l=0; l0) { lCount += plCount[l]; llSum += (Int64)l*(Int64)plCount[l]; llSum2 += (Int64)l*(Int64)l*(Int64)plCount[l]; if(lMin==-1 || llMax) { lMax = l; } } } long lAvg = long(llSum/lCount); double dblVar = ((double)lCount*(double)llSum2 - (double)llSum*(double)llSum)/((double)lCount*(double)(lCount-1)); long lStd = long(sqrt(dblVar)); long lMed = -1; long l95 = -1; long lSel = -1; for(long l=lMin; l<=lMax; ++l) { if(plCount[l]>0) { lSel += plCount[l]; if(lMed==-1 && lSel>=(lCount/2)) { lMed = l; } if(l95==-1 && lSel>=((lCount*95)/100)) { l95 = l; } if(g_bReportPlus) { printf("%ld\t%ld\n", l, plCount[l]); } } } printf("%s: Count=%ld, Min=%ld, Max=%ld, Avg=%ld, Std=%ld, Med=%ld, 95%%=%ld\n", szStat, lCount, lMin, lMax, lAvg, lStd, lMed, l95); } void ShowHelp(const char* szCmd) { printf("%s -t [-s] [-b] [-c] [-m] [-d] [-i] [-v] [-f] [-w] [-r[+]]\n", szCmd); printf("%s -?\n", szCmd); puts("-d\t\tcreate the table"); puts("-i\t\tinsert initial records"); puts("-v\t\tverify initial records"); puts("-t\tnumber of threads making calls"); puts("-s\toffset for primary key"); puts("-b\tbatch size per thread"); puts("-c\tmax number of calls per second for this process"); puts("-m\tsize of context data"); puts("-f\t\tno checkpointing and no logging"); puts("-w\t\tuse writeTuple instead of insertTuple"); puts("-r\t\treport response time statistics"); puts("-r+\t\treport response time distribution"); puts("-?\t\thelp"); } int main(int argc, char* argv[]) { ndb_init(); int iRes = -1; g_nNumThreads = 0; g_nMaxCallsPerSecond = 0; long nSeed = 0; bool bStoredTable = true; bool bCreateTable = false; g_bWriteTuple = false; g_bReport = false; g_bReportPlus = false; for(int i=1; isizeof(STATUS_DATA)) { g_nStatusDataSize = sizeof(STATUS_DATA); } break; case 'i': g_bInsertInitial = true; break; case 'v': g_bVerifyInitial = true; break; case 'd': bCreateTable = true; break; case 'f': bStoredTable = false; break; case 'w': g_bWriteTuple = true; break; case 'r': g_bReport = true; if(argv[i][2]=='+') { g_bReportPlus = true; } break; case 'c': g_nMaxCallsPerSecond = atol(argv[i]+2); break; case '?': default: ShowHelp(argv[0]); return -1; } } else { ShowHelp(argv[0]); return -1; } } if(bCreateTable) puts("-d\tcreate the table"); if(g_bInsertInitial) printf("-i\tinsert initial records\n"); if(g_bVerifyInitial) printf("-v\tverify initial records\n"); if(g_nNumThreads>0) printf("-t%ld\tnumber of threads making calls\n", g_nNumThreads); if(g_nNumThreads>0) { printf("-s%ld\toffset for primary key\n", nSeed); printf("-b%ld\tbatch size per thread\n", g_nMaxContextIdPerThread); } if(g_nMaxCallsPerSecond>0) printf("-c%ld\tmax number of calls per second for this process\n", g_nMaxCallsPerSecond); if(!bStoredTable) puts("-f\tno checkpointing and no logging to disk"); if(g_bWriteTuple) puts("-w\tuse writeTuple instead of insertTuple"); if(g_bReport) puts("-r\treport response time statistics"); if(g_bReportPlus) puts("-r+\treport response time distribution"); if(!bCreateTable && g_nNumThreads<=0) { ShowHelp(argv[0]); return -1; } printf("-m%ld\tsize of context data\n", g_nStatusDataSize); g_szTableName = (bStoredTable ? c_szTableNameStored : c_szTableNameTemp); #ifdef NDB_WIN32 SetConsoleCtrlHandler(ConsoleCtrlHandler, true); #else signal(SIGINT, CtrlCHandler); #endif if(g_bReport) { g_plCountMillisecForCall = new long[c_nMaxMillisecForAllCall]; memset(g_plCountMillisecForCall, 0, c_nMaxMillisecForAllCall*sizeof(long)); g_plCountMillisecForTrans = new long[c_nMaxMillisecForAllTrans]; memset(g_plCountMillisecForTrans, 0, c_nMaxMillisecForAllTrans*sizeof(long)); } g_pNdbMutexIncrement = NdbMutex_Create(); g_pNdbMutexPrintf = NdbMutex_Create(); #ifdef NDB_WIN32 hShutdownEvent = CreateEvent(NULL,TRUE,FALSE,NULL); #endif Ndb* pNdb = new Ndb(c_szDatabaseName); if(!pNdb) { printf("could not construct ndb\n"); return 1; } if(pNdb->init(1) || pNdb->waitUntilReady()) { ReportNdbError("could not initialize ndb\n", pNdb->getNdbError()); delete pNdb; return 2; } if(bCreateTable) { printf("Create CallContext table\n"); if (bStoredTable) { if (CreateCallContextTable(pNdb, c_szTableNameStored, true)) { printf("Create table failed\n"); delete pNdb; return 3; } } else { if (CreateCallContextTable(pNdb, c_szTableNameTemp, false)) { printf("Create table failed\n"); delete pNdb; return 3; } } } if(g_nNumThreads>0) { printf("creating %d threads\n", (int)g_nNumThreads); if(g_bInsertInitial) { printf("each thread will insert %ld initial records, total %ld inserts\n", g_nMaxContextIdPerThread, g_nNumThreads*g_nMaxContextIdPerThread); } if(g_bVerifyInitial) { printf("each thread will verify %ld initial records, total %ld reads\n", g_nMaxContextIdPerThread, g_nNumThreads*g_nMaxContextIdPerThread); } g_nNumberOfInitialInsert = 0; g_nNumberOfInitialVerify = 0; NDB_TICKS tStartTime = NdbTick_CurrentMillisecond(); NdbThread* pThreads[256]; int pnStartingRecordNum[256]; int ij; for(ij=0;ij