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; }
Ndb* asyncDbConnect(int parallellism){ NdbMutex_Lock(startupMutex); Ndb * pNDB = new Ndb(""); pNDB->init(parallellism + 1); while(pNDB->waitUntilReady() != 0){ } NdbMutex_Unlock(startupMutex); return pNDB; }
int runBackupBank(NDBT_Context* ctx, NDBT_Step* step){ int loops = ctx->getNumLoops(); int l = 0; int maxSleep = 30; // Max seconds between each backup Ndb* pNdb = GETNDB(step); NdbBackup backup(GETNDB(step)->getNodeId()+1); unsigned minBackupId = ~0; unsigned maxBackupId = 0; unsigned backupId = 0; int result = NDBT_OK; while (l < loops && result != NDBT_FAILED){ if (pNdb->waitUntilReady() != 0){ result = NDBT_FAILED; continue; } // Sleep for a while NdbSleep_SecSleep(maxSleep); // Perform backup if (backup.start(backupId) != 0){ ndbout << "backup.start failed" << endl; result = NDBT_FAILED; continue; } ndbout << "Started backup " << backupId << endl; // Remember min and max backupid if (backupId < minBackupId) minBackupId = backupId; if (backupId > maxBackupId) maxBackupId = backupId; ndbout << " maxBackupId = " << maxBackupId << ", minBackupId = " << minBackupId << endl; ctx->setProperty("MinBackupId", minBackupId); ctx->setProperty("MaxBackupId", maxBackupId); l++; } ctx->stopTest(); return result; }
UserHandle* userDbConnect(uint32 createDb, const char *dbName) { Ndb_cluster_connection *con= new Ndb_cluster_connection(); if(con->connect(12, 5, 1) != 0) { ndbout << "Unable to connect to management server." << endl; return 0; } if (con->wait_until_ready(30,0) < 0) { ndbout << "Cluster nodes not ready in 30 seconds." << endl; return 0; } Ndb * pNdb = new Ndb(con, dbName); //printf("Initializing...\n"); pNdb->init(); //printf("Waiting..."); while(pNdb->waitUntilReady() != 0){ //printf("..."); } // printf("done\n"); if( createDb ) dbCreate(pNdb); UserHandle * uh = new UserHandle; uh->pNCC = con; uh->pNDB = pNdb; uh->pCurrTrans = 0; return uh; }
int runTestSingleUserMode(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; int loops = ctx->getNumLoops(); int records = ctx->getNumRecords(); Ndb* pNdb = GETNDB(step); NdbRestarter restarter; char tabName[255]; strncpy(tabName, ctx->getTab()->getName(), 255); ndbout << "tabName="<<tabName<<endl; int i = 0; int count; HugoTransactions hugoTrans(*ctx->getTab()); UtilTransactions utilTrans(*ctx->getTab()); while (i<loops && result == NDBT_OK) { g_info << i << ": "; int timeout = 120; // Test that the single user mode api can do everything CHECK(restarter.enterSingleUserMode(pNdb->getNodeId()) == 0); CHECK(restarter.waitClusterSingleUser(timeout) == 0); CHECK(hugoTrans.loadTable(pNdb, records, 128) == 0); CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0); CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0); CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(count == records); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0); CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(count == (records/2)); CHECK(utilTrans.clearTable(pNdb, records/2) == 0); CHECK(restarter.exitSingleUserMode() == 0); CHECK(restarter.waitClusterStarted(timeout) == 0); // Test create index in single user mode CHECK(restarter.enterSingleUserMode(pNdb->getNodeId()) == 0); CHECK(restarter.waitClusterSingleUser(timeout) == 0); CHECK(create_index_on_pk(pNdb, tabName) == 0); CHECK(hugoTrans.loadTable(pNdb, records, 128) == 0); CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0); CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0); CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(count == records); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); CHECK(drop_index_on_pk(pNdb, tabName) == 0); CHECK(restarter.exitSingleUserMode() == 0); CHECK(restarter.waitClusterStarted(timeout) == 0); // Test recreate index in single user mode CHECK(create_index_on_pk(pNdb, tabName) == 0); CHECK(hugoTrans.loadTable(pNdb, records, 128) == 0); CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(restarter.enterSingleUserMode(pNdb->getNodeId()) == 0); CHECK(restarter.waitClusterSingleUser(timeout) == 0); CHECK(drop_index_on_pk(pNdb, tabName) == 0); CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(create_index_on_pk(pNdb, tabName) == 0); CHECK(restarter.exitSingleUserMode() == 0); CHECK(restarter.waitClusterStarted(timeout) == 0); CHECK(drop_index_on_pk(pNdb, tabName) == 0); CHECK(utilTrans.clearTable(GETNDB(step), records) == 0); ndbout << "Restarting cluster" << endl; CHECK(restarter.restartAll() == 0); CHECK(restarter.waitClusterStarted(timeout) == 0); CHECK(pNdb->waitUntilReady(timeout) == 0); i++; } return result; }
int main(int argc, const char** argv) { ndb_init(); int _row = 0; int _hex = 0; int _primaryKey = 0; const char* _tableName = NULL; struct getargs args[] = { { "row", 'r', arg_integer, &_row, "The row number", "row" }, { "primarykey", 'p', arg_integer, &_primaryKey, "The primary key", "primarykey" }, { "hex", 'h', arg_flag, &_hex, "Print hex", "hex" } }; int num_args = sizeof(args) / sizeof(args[0]); int optind = 0, i; if(getarg(args, num_args, argc, argv, &optind) || argv[optind] == NULL) { arg_printusage(args, num_args, argv[0], "table name\n"); return NDBT_WRONGARGS; } // Check if table name is supplied if (argv[optind] != NULL) _tableName = argv[optind]; const NdbDictionary::Table* table = NDBT_Tables::getTable(_tableName); // const NDBT_Attribute* attribute = table->getAttribute(_column); g_info << "Table " << _tableName << endl << "Row: " << _row << ", PrimaryKey: " << _primaryKey << endl; Ndb_cluster_connection con; if(con.connect(12, 5, 1) != 0) { return NDBT_ProgramExit(NDBT_FAILED); } Ndb* ndb = new Ndb(&con, "TEST_DB"); if (ndb->init() == 0 && ndb->waitUntilReady(30) == 0) { NdbConnection* conn = ndb->startTransaction(); if (conn == NULL) { g_info << "ERROR: " << ndb->getNdbError() << endl; delete ndb; return -1; } NdbOperation* op = conn->getNdbOperation(_tableName); if (op == NULL) { g_info << "ERROR: " << conn->getNdbError() << endl; delete ndb; return -1; } op->readTuple(); NdbRecAttr** data = new NdbRecAttr*[table->getNoOfColumns()]; for (i = 0; i < table->getNoOfColumns(); i++) { const NdbDictionary::Column* c = table->getColumn(i); if (c->getPrimaryKey()) { op->equal(c->getName(), _primaryKey); data[i] = op->getValue(c->getName(), NULL); } else { data[i] = op->getValue(c->getName(), NULL); } } if (conn->execute(Commit) == 0) { // Print column names for (i = 0; i < table->getNoOfColumns(); i++) { const NdbDictionary::Column* c = table->getColumn(i); g_info << c->getName() << "[" << c->getType() << "] "; } g_info << endl; if (_hex) { g_info << hex; } for (i = 0; i < table->getNoOfColumns(); i++) { NdbRecAttr* a = data[i]; ndbout << (* a) << " "; } // for g_info << endl; } // if (conn else { g_info << "Failed to commit read transaction... " << conn->getNdbError() << ", commitStatus = " << conn->commitStatus() << endl; } delete[] data; ndb->closeTransaction(conn); } // if (ndb.init else { g_info << "ERROR: Unable to connect to NDB, " << ndb->getNdbError() << endl; } delete ndb; return 0; }
int main(int argc, char* argv[]) { // setlocale(LC_ALL, ""); if (argc < 2) { printf("No connection string specified.\n"); print_help(); return -1; } if (argc < 3) { printf("No database specified.\n"); print_help(); return -1; } if (argc < 4) { printf("No filepath specified.\n"); print_help(); return -1; } if (argc < 5) { printf("No table format file specified.\n"); print_help(); return -1; } if (argc >= 6) { tNoOfParallelTrans = atoi(argv[5]); } if (argc >= 7) { sleepTimeMilli = atoi(argv[6]); } strcpy(connstring, argv[1]); strcpy(database, argv[2]); strcpy(filepath, argv[3]); strcpy(tablefilepath, argv[4]); ifstream fin(tablefilepath); // first line is table name. string tmpTableName; getline(fin, tmpTableName); strcpy(tablename, tmpTableName.c_str()); // find a "nokey" in table name istringstream lineReader(tmpTableName); string firstpart; if( getline(lineReader, firstpart, ' ') ) { // printf("first part: %s", firstpart.c_str()); string secondpart; if( getline(lineReader, secondpart) ) { // "firstpart secondpart" if (secondpart != NOKEY_IDENTIFIER) { cerr << "ERROR: could not recognize identifier: " << secondpart << endl; cerr << "Do you mean: '" << NOKEY_IDENTIFIER << "'?"<< endl; exit(-1); } else { noKey = true; } // printf("Attr: %s %s\n", key.c_str(), value.c_str()); } strcpy(tablename, firstpart.c_str()); } // Initialize transaction array for(int i = 0 ; i < MAXTRANS ; i++) { transaction[i].used = 0; transaction[i].conn = 0; } // each line is a column for (string row; getline(fin, row); ) { istringstream lineReader(row); string key; if( getline(lineReader, key, ' ') ) { string value; if( getline(lineReader, value) ) { // "key value" fieldName.push_back(key); fieldType.push_back(value); // printf("Attr: %s %s\n", key.c_str(), value.c_str()); } } } fin.close(); Ndb_cluster_connection *conn = connect_to_cluster(connstring); Ndb* ndb = new Ndb(conn, database); if (ndb->init(1024) == -1) { // pass } ndb->waitUntilReady(10000); printf("Connected: database [%s], connstr [%s], #parallelTrans=[%d]. Load table [%s] from file [%s]...\n", database, connstring, tNoOfParallelTrans, tablename, filepath); // do_insert(*ndb); const NdbDictionary::Dictionary* myDict= ndb->getDictionary(); // printf("table name: %s\n", tablename); const NdbDictionary::Table *myTable= myDict->getTable(tablename); if (myTable == NULL) APIERROR(myDict->getNdbError()); // Load the data bool dataleft = false; typedef vector<vector<string> > Rows; // Rows rows; ifstream input(filepath); char const row_delim = '\n'; char const field_delim = '\t'; int rowCounter = 0; for (string row; getline(input, row, row_delim); ) { // Find a slot in the transaction array async_callback_t * cb; // int retries = 0; int current = -1; int cursor = transTail + 1; if (cursor >= MAXTRANS) { cursor = 0; } for(int retries = 0; retries < MAX_TRANSALLOC_RETRY; retries++) { // for(int cursor=0; cursor < MAXTRANS; cursor++) while(true) { if(transaction[cursor].used == 0) { current = cursor; cb = new async_callback_t; /** * Set data used by the callback */ cb->ndb = ndb; //handle to Ndb object so that we can close transaction // in the callback (alt. make myNdb global). cb->transaction = current; //This is the number (id) of this transaction transaction[current].used = 1 ; //Mark the transaction as used transTail = current; // optimizing scan break; } else { // used cursor += 1; if (cursor >= MAXTRANS) { cursor = 0; } } } if(current == -1) { cerr << "WARNING: Number of transactions in parallel exceeds the maximum. retrying..." << endl; usleep(1000); continue; } else { break; } } transaction[current].conn = ndb->startTransaction(); istringstream ss(row); // NdbOperation *myOperation= myTransaction->getNdbOperation(myTable); NdbOperation *myOperation= transaction[current].conn->getNdbOperation(myTable); myOperation->insertTuple(); // If no primary key is assigned, have to set the tupleId explicitly if (noKey) { unsigned long long tupleId = 0; // int // Ndb::getAutoIncrementValue(const char* aTableName, // Uint64 & autoValue, Uint32 cacheSize, // Uint64 step, Uint64 start) if (ndb->getAutoIncrementValue(myTable, tupleId, TUPLEID_FETCH_SIZE, 1, 1) != 0) { cerr << "Error occurs while getting tupleID to insert.\n"; exit(-1); } myOperation->equal("$PK", tupleId); //if (tupleId % 10000 == 0) { // cerr <<"DEBUG: set tupleID to " << tupleId << endl; //} } // Iterate for each field int i = 0; for (string field; getline(ss, field, field_delim); i++) { // For NULL value, do not set value for this field if (strcmp(field.c_str(), "\\N") == 0) { continue; } if (strcmp(fieldType[i].c_str(), "int") == 0) { // using a int64 to prevent problems.. long long value = atoll(field.c_str()); myOperation->setValue(fieldName[i].c_str(), value); } if (strcmp(fieldType[i].c_str(), "real") == 0) { double value = atof(field.c_str()); myOperation->setValue(fieldName[i].c_str(), value); } if (strcmp(fieldType[i].c_str(), "varchar") == 0) { char buffer[65535] = {}; make_ndb_varchar(buffer, field.c_str()); myOperation->setValue(fieldName[i].c_str(), buffer); } if (strcmp(fieldType[i].c_str(), "char") == 0) { char buffer[65535] = {}; make_ndb_char(buffer, field.c_str()); myOperation->setValue(fieldName[i].c_str(), buffer); // myOperation->setValue(fieldName[i].c_str(), field.c_str()); } if (strcmp(fieldType[i].c_str(), "boolean") == 0) { int value = atoi(field.c_str()); myOperation->setValue(fieldName[i].c_str(), value); } if (strcmp(fieldType[i].c_str(), "text") == 0) { NdbBlob *myBlobHandle = myOperation->getBlobHandle(fieldName[i].c_str()); if (myBlobHandle == NULL) { cerr << "Hint: in the TSV file any TEXT/BLOB attribute must come after the primary key column.\n"; APIERROR(myOperation->getNdbError()); } myBlobHandle->setValue(field.c_str(), field.length()); // myBlobHandle->setNull(); } } transaction[current].conn->executeAsynchPrepare( NdbTransaction::Commit, &callback, cb ); nPreparedTransactions++; rowCounter++; dataleft = true; /** * When we have prepared parallelism number of transactions -> * send the transaction to ndb. * Next time we will deal with the transactions are in the * callback. There we will see which ones that were successful * and which ones to retry. */ if (nPreparedTransactions >= tNoOfParallelTrans) { // send-poll all transactions // close transaction is done in callback ndb->sendPollNdb(3000, tNoOfParallelTrans ); nPreparedTransactions=0; dataleft = false; usleep(sleepTimeMilli); } // The SYNC way that can set multiple operations in one commit: // if (myTransaction->execute( NdbTransaction::NoCommit ) == -1) // APIERROR(myTransaction->getNdbError()); // if (rowCounter % TRANACTION_SIZE == 0) { // // commit // if (myTransaction->execute( NdbTransaction::Commit ) == -1) // APIERROR(myTransaction->getNdbError()); // ndb->closeTransaction(myTransaction); // myTransaction = ndb->startTransaction(); // dataleft = false; // } } if (dataleft) { ndb->sendPollNdb(3000, nPreparedTransactions ); nPreparedTransactions=0; // SYNC way // if (myTransaction->execute( NdbTransaction::Commit ) == -1) // APIERROR(myTransaction->getNdbError()); // ndb->closeTransaction(myTransaction); } ndb->waitUntilReady(10000); delete ndb; disconnect_from_cluster(conn); return EXIT_SUCCESS; }
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; i<argc; ++i) { if(argv[i][0]=='-' || argv[i][0]=='/') { switch(argv[i][1]) { case 't': g_nNumThreads = atol(argv[i]+2); break; case 's': nSeed = atol(argv[i]+2); break; case 'b': g_nMaxContextIdPerThread = atol(argv[i]+2); break; case 'm': g_nStatusDataSize = atol(argv[i]+2); if(g_nStatusDataSize>sizeof(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<g_nNumThreads;ij++) { pnStartingRecordNum[ij] = (ij*g_nMaxContextIdPerThread) + nSeed; } for(ij=0;ij<g_nNumThreads;ij++) { pThreads[ij] = NdbThread_Create(RuntimeCallContext, (void**)(pnStartingRecordNum+ij), 0, "RuntimeCallContext", NDB_THREAD_PRIO_LOW); } //Wait for the threads to finish for(ij=0;ij<g_nNumThreads;ij++) { void* status; NdbThread_WaitFor(pThreads[ij], &status); } NDB_TICKS tEndTime = NdbTick_CurrentMillisecond(); //Print time taken printf("Time Taken for %ld Calls is %ld msec (= %ld calls/sec)\n", g_nNumCallsProcessed, (long)(tEndTime-tStartTime), (long)((1000*g_nNumCallsProcessed)/(tEndTime-tStartTime))); if(g_bInsertInitial) printf("successfully inserted %ld tuples\n", g_nNumberOfInitialInsert); if(g_bVerifyInitial) printf("successfully verified %ld tuples\n", g_nNumberOfInitialVerify); } delete pNdb; #ifdef NDB_WIN32 CloseHandle(hShutdownEvent); #endif NdbMutex_Destroy(g_pNdbMutexIncrement); NdbMutex_Destroy(g_pNdbMutexPrintf); if(g_bReport) { ReportResponseTimeStatistics("Calls", g_plCountMillisecForCall, c_nMaxMillisecForAllCall); ReportResponseTimeStatistics("Transactions", g_plCountMillisecForTrans, c_nMaxMillisecForAllTrans); delete[] g_plCountMillisecForCall; delete[] g_plCountMillisecForTrans; } return 0; }
void* RuntimeCallContext(void* lpParam) { long nNumCallsProcessed = 0; int nStartingRecordID = *(int*)lpParam; Ndb* pNdb; char* pchContextData = new char[g_nStatusDataSize]; char szMsg[100]; int iRes; const char* szOp; long iVersion; long iLockFlag; long iLockTime; long iLockTimeUSec; pNdb = new Ndb("TEST_DB"); if(!pNdb) { NdbMutex_Lock(g_pNdbMutexPrintf); printf("new Ndb failed\n"); NdbMutex_Unlock(g_pNdbMutexPrintf); delete[] pchContextData; return 0; } if(pNdb->init(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 && lMillisecForThisTrans<c_nMaxMillisecForAllTrans); InterlockedIncrement(g_plCountMillisecForTrans+lMillisecForThisTrans); } if(nRetry>0) { 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 && lMillisecForThisCall<c_nMaxMillisecForAllCall); InterlockedIncrement(g_plCountMillisecForCall+lMillisecForThisCall); } if(bTimeLatency) { NdbMutex_Lock(g_pNdbMutexPrintf); printf("Total time for call is %ld msec.\n", (long)lMillisecForThisCall); NdbMutex_Unlock(g_pNdbMutexPrintf); } nNumCallsProcessed++; InterlockedIncrementAndReport(); if(g_nMaxCallsPerSecond>0) { 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 main(int argc, const char** argv) { ndb_init(); int operationType = 0; int tupTest = 0; int scanTest = 0; Ndb* pNdb = new Ndb("TEST_DB"); pNdb->init(); if (argc != 4 || sscanf(argv[1],"%d", &operationType) != 1) { operationType = 1 ; } if (argc != 4 || sscanf(argv[2],"%d", &tupTest) != 1) { tupTest = 1 ; } if (argc != 4 || sscanf(argv[3],"%d", &scanTest) != 1) { scanTest = 1 ; } ndbout << endl << "Test the interpreter in TUP using SimpleTable with\n" << nRecords << " records" << endl << endl ; if (pNdb->waitUntilReady(30) != 0) { ndbout << "NDB is not ready" << endl; return -1; } // Init the pk and attr values. for (int i = 0; i < NUMBEROFRECORDS; i ++) pkValue[i] = attrValue[i] = i ; setAttrNames() ; setTableNames() ; const void * p = NDBT_Table::discoverTableFromDb(pNdb, tableName); if (p != 0) { create_table(pNdb); } write_rows(pNdb); ndbout << endl << "Starting interpreter in TUP test." << endl << "Operation type: " ; switch(operationType) { case 1: ndbout << "openScanRead" << endl; scan_rows(pNdb, operationType, tupTest, scanTest); break; case 2: ndbout << "openScanExclusive" << endl; scan_rows(pNdb, operationType, tupTest, scanTest); break; case 3: ndbout << "interpretedUpdateTuple" << endl; update_rows(pNdb, tupTest, operationType); break; case 4: ndbout << "interpretedDirtyUpdate" << endl; update_rows(pNdb, tupTest, operationType); break; case 5: ndbout << "interpretedDeleteTuple" << endl; delete_rows(pNdb, tupTest, operationType); break; case 6: ndbout << "deleteTuple" << endl; break; case 7: ndbout << "insertTuple" << endl; break; case 8: ndbout << "updateTuple" << endl; break; case 9: ndbout << "writeTuple" << endl; break; case 10: ndbout << "readTuple" << endl; break; case 11: ndbout << "readTupleExclusive" << endl; break; case 12: ndbout << "simpleRead" << endl; break; case 13: ndbout << "dirtyRead" << endl; break; case 14: ndbout << "dirtyUpdate" << endl; break; case 15: ndbout << "dirtyWrite" << endl; break; default: break ; } // read_and_verify_rows(pNdb, false); // delete_rows(pNdb, 0, 0) ; delete pNdb ; if (bTestPassed == 0) { ndbout << "OK: test passed" << endl; exit(0); } else { ndbout << "FAIL: test failed" << endl; exit(-1); } }