HugoOperations::~HugoOperations(){ deallocRows(); if (pTrans != NULL) { pTrans->close(); pTrans = NULL; } }
int HugoAsynchTransactions::pkReadRecordsAsynch(Ndb* pNdb, int records, int batch, int trans, int operations) { g_info << "|- Reading records asynchronous..." << endl; allocRows(trans*operations); int result = executeAsynchOperation(pNdb, records, batch, trans, operations, NO_READ); g_info << "|- " << (unsigned int)transactionsCompleted * operations << " read..." << endl; deallocRows(); return result; }
int HugoTransactions::pkUpdateRecords(Ndb* pNdb, int records, int batch, int doSleep){ int updated = 0; int r = 0; int retryAttempt = 0; int check, b; allocRows(batch); g_info << "|- Updating records (batch=" << batch << ")..." << endl; int batch_no = 0; while (r < records){ if(r + batch > records) batch = records - r; if (m_thr_count != 0 && m_thr_no != batch_no % m_thr_count) { r += batch; batch_no++; continue; } if (retryAttempt >= m_retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; return NDBT_FAILED; } if (doSleep > 0) NdbSleep_MilliSleep(doSleep); pTrans = pNdb->startTransaction(); if (pTrans == NULL) { const NdbError err = pNdb->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); return NDBT_FAILED; } if(pkReadRecord(pNdb, r, batch, NdbOperation::LM_Exclusive) != NDBT_OK) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); closeTransaction(pNdb); return NDBT_FAILED; } MicroSecondTimer timer_start; MicroSecondTimer timer_stop; bool timer_active = m_stats_latency != 0 && r >= batch && // first batch is "warmup" r + batch != records; // last batch is usually partial if (timer_active) NdbTick_getMicroTimer(&timer_start); if(pIndexScanOp) { int rows_found = 0; while((check = pIndexScanOp->nextResult(true)) == 0) { do { if (calc.verifyRowValues(rows[0]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; } int updates = calc.getUpdatesValue(rows[0]) + 1; if(pkUpdateRecord(pNdb, r+rows_found, 1, updates) != NDBT_OK) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } rows_found++; } while((check = pIndexScanOp->nextResult(false)) == 0); if(check != 2) break; if((check = pTrans->execute(NoCommit, AbortOnError)) != 0) break; } if(check != 1 || rows_found != batch) { closeTransaction(pNdb); return NDBT_FAILED; } } else { for(b = 0; b<batch && (b+r)<records; b++) { if (calc.verifyRowValues(rows[b]) != 0) { closeTransaction(pNdb); return NDBT_FAILED; } int updates = calc.getUpdatesValue(rows[b]) + 1; if(pkUpdateRecord(pNdb, r+b, 1, updates) != NDBT_OK) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } } check = pTrans->execute(Commit, AbortOnError); } if( check == -1 ) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); ndbout << "r = " << r << endl; closeTransaction(pNdb); return NDBT_FAILED; } else{ updated += batch; m_latest_gci = pTrans->getGCI(); } closeTransaction(pNdb); if (timer_active) { NdbTick_getMicroTimer(&timer_stop); NDB_TICKS ticks = NdbTick_getMicrosPassed(timer_start, timer_stop); m_stats_latency->addObservation((double)ticks); } r += batch; // Read next record batch_no++; } deallocRows(); g_info << "|- " << updated << " records updated" << endl; return NDBT_OK; }
int HugoTransactions::pkReadRecords(Ndb* pNdb, int records, int batch, NdbOperation::LockMode lm){ int reads = 0; int r = 0; int retryAttempt = 0; int check; if (batch == 0) { g_info << "ERROR: Argument batch == 0 in pkReadRecords(). Not allowed." << endl; return NDBT_FAILED; } while (r < records){ if(r + batch > records) batch = records - r; if (retryAttempt >= m_retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; return NDBT_FAILED; } pTrans = pNdb->startTransaction(); if (pTrans == NULL) { const NdbError err = pNdb->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); return NDBT_FAILED; } MicroSecondTimer timer_start; MicroSecondTimer timer_stop; bool timer_active = m_stats_latency != 0 && r >= batch && // first batch is "warmup" r + batch != records; // last batch is usually partial if (timer_active) NdbTick_getMicroTimer(&timer_start); if(pkReadRecord(pNdb, r, batch, lm) != NDBT_OK) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } check = pTrans->execute(Commit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } switch(err.code){ case 626: // Tuple did not exist g_info << r << ": " << err.code << " " << err.message << endl; r++; break; default: ERR(err); closeTransaction(pNdb); return NDBT_FAILED; } } else { if(pIndexScanOp) { int rows_found = 0; while((check = pIndexScanOp->nextResult()) == 0) { rows_found++; if (calc.verifyRowValues(rows[0]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; } } if(check != 1 || rows_found > batch) { closeTransaction(pNdb); return NDBT_FAILED; } else if(rows_found < batch) { if(batch == 1){ g_info << r << ": not found" << endl; abort(); } else g_info << "Found " << rows_found << " of " << batch << " rows" << endl; } r += batch; reads += rows_found; } else { for (int b=0; (b<batch) && (r+b<records); b++){ if (calc.verifyRowValues(rows[b]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; } reads++; r++; } } } closeTransaction(pNdb); if (timer_active) { NdbTick_getMicroTimer(&timer_stop); NDB_TICKS ticks = NdbTick_getMicrosPassed(timer_start, timer_stop); m_stats_latency->addObservation((double)ticks); } } deallocRows(); g_info << reads << " records read" << endl; return NDBT_OK; }
HugoTransactions::~HugoTransactions(){ deallocRows(); }
int HugoTransactions::indexReadRecords(Ndb* pNdb, const char * idxName, int records, int batch){ int reads = 0; int r = 0; int retryAttempt = 0; int check, a; NdbOperation *pOp; NdbIndexScanOperation *sOp; const NdbDictionary::Index* pIndex = pNdb->getDictionary()->getIndex(idxName, tab.getName()); const bool ordered = (pIndex->getType()==NdbDictionary::Index::OrderedIndex); if (batch == 0) { g_info << "ERROR: Argument batch == 0 in indexReadRecords(). " << "Not allowed." << endl; return NDBT_FAILED; } if (ordered) { batch = 1; } allocRows(batch); while (r < records){ if (retryAttempt >= m_retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; return NDBT_FAILED; } pTrans = pNdb->startTransaction(); if (pTrans == NULL) { const NdbError err = pNdb->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); return NDBT_FAILED; } for(int b=0; (b<batch) && (r+b < records); b++){ if(!ordered){ pOp = pTrans->getNdbIndexOperation(idxName, tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } check = pOp->readTuple(); } else { pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName()); if (sOp == NULL) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } check = sOp->readTuples(); } if( check == -1 ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } // Define primary keys if (equalForRow(pOp, r+b) != 0) { closeTransaction(pNdb); return NDBT_FAILED; } // Define attributes to read for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[b]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } } } check = pTrans->execute(Commit, AbortOnError); check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true)); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } switch(err.code){ case 626: // Tuple did not exist g_info << r << ": " << err.code << " " << err.message << endl; r++; break; default: ERR(err); closeTransaction(pNdb); return NDBT_FAILED; } } else{ for (int b=0; (b<batch) && (r+b<records); b++){ if (calc.verifyRowValues(rows[b]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; } reads++; r++; } if(ordered && sOp->nextResult(true) == 0){ ndbout << "Error when comparing records " << " - index op next_result to many" << endl; closeTransaction(pNdb); return NDBT_FAILED; } } closeTransaction(pNdb); } deallocRows(); g_info << reads << " records read" << endl; return NDBT_OK; }
int HugoTransactions::lockRecords(Ndb* pNdb, int records, int percentToLock, int lockTime){ // Place a lock on percentToLock% of the records in the Db // Keep the locks for lockTime ms, commit operation // and lock som other records int r = 0; int retryAttempt = 0; int check; NdbOperation::LockMode lm = NdbOperation::LM_Exclusive; // Calculate how many records to lock in each batch if (percentToLock <= 0) percentToLock = 1; double percentVal = (double)percentToLock / 100; int lockBatch = (int)(records * percentVal); if (lockBatch <= 0) lockBatch = 1; allocRows(lockBatch); while (r < records){ if(r + lockBatch > records) lockBatch = records - r; g_info << "|- Locking " << lockBatch << " records..." << endl; if (retryAttempt >= m_retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; return NDBT_FAILED; } pTrans = pNdb->startTransaction(); if (pTrans == NULL) { const NdbError err = pNdb->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); return NDBT_FAILED; } if(pkReadRecord(pNdb, r, lockBatch, lm) != NDBT_OK) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } // NoCommit lockTime times with 100 millis interval int sleepInterval = 50; int lockCount = lockTime / sleepInterval; int commitCount = 0; do { check = pTrans->execute(NoCommit, AbortOnError); if( check == -1) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); closeTransaction(pNdb); return NDBT_FAILED; } for (int b=0; (b<lockBatch) && (r+b<records); b++){ if (calc.verifyRowValues(rows[b]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; } } commitCount++; NdbSleep_MilliSleep(sleepInterval); } while (commitCount < lockCount); // Really commit the trans, puuh! check = pTrans->execute(Commit, AbortOnError); if( check == -1) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); closeTransaction(pNdb); return NDBT_FAILED; } else{ for (int b=0; (b<lockBatch) && (r<records); b++){ if (calc.verifyRowValues(rows[b]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; } r++; // Read next record } } closeTransaction(pNdb); } deallocRows(); g_info << "|- Record locking completed" << endl; return NDBT_OK; }
int HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, int records, int batch, int trans, int operations) { g_info << "|- Updating records asynchronous..." << endl; int check = 0; int cTrans = 0; int cReadRecords = 0; int cReadIndex = 0; int cRecords = 0; int cIndex = 0; transactionsCompleted = 0; allocRows(trans*operations); allocTransactions(trans); int a, t, r; for (int i = 0; i < batch; i++) { // For each batch while (cRecords < records*batch) { cTrans = 0; cReadIndex = 0; for (t = 0; t < trans; t++) { // For each transaction transactions[t] = pNdb->startTransaction(); if (transactions[t] == NULL) { ERR(pNdb->getNdbError()); return NDBT_FAILED; } for (int k = 0; k < operations; k++) { // For each operation NdbOperation* pOp = transactions[t]->getNdbOperation(tab.getName()); if (pOp == NULL) { ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); return NDBT_FAILED; } // Read // Define primary keys check = pOp->readTupleExclusive(); for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == true) { if (equalForAttr(pOp, a, cReadRecords) != 0){ ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); return NDBT_FAILED; } } } // Define attributes to read for (a = 0; a < tab.getNoOfColumns(); a++) { if ((rows[cReadIndex]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); return NDBT_FAILED; } } cReadIndex++; cReadRecords++; } // For each operation // Let's prepare... transactions[t]->executeAsynchPrepare(NoCommit, &asynchCallback, this); cTrans++; if (cReadRecords >= records) { // No more transactions needed break; } } // For each transaction // Wait for all outstanding transactions pNdb->sendPollNdb(3000, 0, 0); // Verify the data! for (r = 0; r < trans*operations; r++) { if (calc.verifyRowValues(rows[r]) != 0) { g_info << "|- Verify failed..." << endl; // Close all transactions for (int t = 0; t < cTrans; t++) { pNdb->closeTransaction(transactions[t]); } return NDBT_FAILED; } } // Update cTrans = 0; cIndex = 0; for (t = 0; t < trans; t++) { // For each transaction for (int k = 0; k < operations; k++) { // For each operation NdbOperation* pOp = transactions[t]->getNdbOperation(tab.getName()); if (pOp == NULL) { ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); return NDBT_FAILED; } int updates = calc.getUpdatesValue(rows[cIndex]) + 1; check = pOp->updateTuple(); if (check == -1) { ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); return NDBT_FAILED; } // Set search condition for the record for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == true) { if (equalForAttr(pOp, a, cRecords) != 0) { ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); return NDBT_FAILED; } } } // Update the record for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == false) { if (setValueForAttr(pOp, a, cRecords, updates) != 0) { ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); return NDBT_FAILED; } } } cIndex++; cRecords++; } // For each operation // Let's prepare... transactions[t]->executeAsynchPrepare(Commit, &asynchCallback, this); cTrans++; if (cRecords >= records) { // No more transactions needed break; } } // For each transaction // Wait for all outstanding transactions pNdb->sendPollNdb(3000, 0, 0); // Close all transactions for (t = 0; t < cTrans; t++) { pNdb->closeTransaction(transactions[t]); } } // while (cRecords < records*batch) } // For each batch deallocTransactions(); deallocRows(); g_info << "|- " << ((unsigned int)transactionsCompleted * operations)/2 << " updated..." << endl; return NDBT_OK; }